OLD | NEW |
| (Empty) |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 library input.transformer.instrumentation; | |
6 | |
7 import 'dart:convert'; | |
8 | |
9 import 'package:analyzer/src/generated/java_engine.dart'; | |
10 import 'package:analyzer/instrumentation/instrumentation.dart'; | |
11 import 'package:logging/logging.dart'; | |
12 | |
13 import 'input_converter.dart'; | |
14 import 'operation.dart'; | |
15 | |
16 final int COLON = ':'.codeUnitAt(0); | |
17 | |
18 /** | |
19 * [InstrumentationInputConverter] converts an instrumentation stream | |
20 * into a series of operations to be sent to the analysis server. | |
21 */ | |
22 class InstrumentationInputConverter extends CommonInputConverter { | |
23 final Set<String> codesSeen = new Set<String>(); | |
24 | |
25 /** | |
26 * [readBuffer] holds the contents of the file being read from disk | |
27 * as recorded in the instrumentation log | |
28 * or `null` if not converting a "Read" entry. | |
29 */ | |
30 StringBuffer readBuffer = null; | |
31 | |
32 InstrumentationInputConverter( | |
33 String tmpSrcDirPath, Map<String, String> srcPathMap, | |
34 {int diagnosticPort}) | |
35 : super(tmpSrcDirPath, srcPathMap, diagnosticPort: diagnosticPort); | |
36 | |
37 @override | |
38 Operation convert(String line) { | |
39 List<String> fields; | |
40 try { | |
41 fields = _parseFields(line); | |
42 if (fields.length < 2) { | |
43 if (readBuffer != null) { | |
44 readBuffer.writeln(fields.length == 1 ? fields[0] : ''); | |
45 return null; | |
46 } | |
47 throw 'Failed to process line:\n$line'; | |
48 } | |
49 if (readBuffer != null) { | |
50 readBuffer = null; | |
51 } | |
52 } catch (e, s) { | |
53 throw new AnalysisException( | |
54 'Failed to parse line\n$line', new CaughtException(e, s)); | |
55 } | |
56 // int timeStamp = int.parse(fields[0], onError: (_) => -1); | |
57 String opCode = fields[1]; | |
58 if (opCode == InstrumentationService.TAG_NOTIFICATION) { | |
59 return convertNotification(decodeJson(line, fields[2])); | |
60 } else if (opCode == 'Read') { | |
61 // 1434096943209:Read:/some/file/path:1434095535000:<file content> | |
62 //String filePath = fields[2]; | |
63 readBuffer = new StringBuffer(fields.length > 4 ? fields[4] : ''); | |
64 return null; | |
65 } else if (opCode == InstrumentationService.TAG_REQUEST) { | |
66 return convertRequest(decodeJson(line, fields[2])); | |
67 } else if (opCode == InstrumentationService.TAG_RESPONSE) { | |
68 // 1434096937454:Res:{"id"::"0","result"::{"version"::"1.7.0"}} | |
69 return convertResponse(decodeJson(line, fields[2])); | |
70 } else if (opCode == InstrumentationService.TAG_ANALYSIS_TASK) { | |
71 // 1434096943208:Task:/Users/ | |
72 return null; | |
73 } else if (opCode == InstrumentationService.TAG_LOG_ENTRY) { | |
74 // 1434096937454:Res:{"id"::"0","result"::{"version"::"1.7.0"}} | |
75 return null; | |
76 } else if (opCode == InstrumentationService.TAG_PERFORMANCE) { | |
77 //1434096960092:Perf:analysis_full:16884:context_id=0 | |
78 return null; | |
79 } else if (opCode == InstrumentationService.TAG_SUBPROCESS_START) { | |
80 // 1434096938634:SPStart:0:/Users/da | |
81 return null; | |
82 } else if (opCode == InstrumentationService.TAG_SUBPROCESS_RESULT) { | |
83 // 1434096939068:SPResult:0:0:"{\"packages\"::{\"rpi_lidar\"::\"/Users | |
84 return null; | |
85 } else if (opCode == InstrumentationService.TAG_VERSION) { | |
86 // 1434096937358:Ver:1421765742287333878467:org.dartlang.dartplugin | |
87 return null; | |
88 } else if (opCode == InstrumentationService.TAG_WATCH_EVENT) { | |
89 // 1434097460414:Watch:/some/file/path | |
90 return null; | |
91 } | |
92 if (codesSeen.add(opCode)) { | |
93 logger.log( | |
94 Level.WARNING, 'Ignored instrumentation op code: $opCode\n $line'); | |
95 } | |
96 return null; | |
97 } | |
98 | |
99 Map<String, dynamic> decodeJson(String line, String text) { | |
100 try { | |
101 return JSON.decode(text); | |
102 } catch (e, s) { | |
103 throw new AnalysisException( | |
104 'Failed to decode JSON: $text\n$line', new CaughtException(e, s)); | |
105 } | |
106 } | |
107 | |
108 /** | |
109 * Determine if the given line is from an instrumentation file. | |
110 * For example: | |
111 * `1433175833005:Ver:1421765742287333878467:org.dartlang.dartplugin:0.0.0:1.6
.2:1.11.0-edge.131698` | |
112 */ | |
113 static bool isFormat(String line) { | |
114 List<String> fields = _parseFields(line); | |
115 if (fields.length < 2) return false; | |
116 int timeStamp = int.parse(fields[0], onError: (_) => -1); | |
117 String opCode = fields[1]; | |
118 return timeStamp > 0 && opCode == 'Ver'; | |
119 } | |
120 | |
121 /** | |
122 * Extract fields from the given [line]. | |
123 */ | |
124 static List<String> _parseFields(String line) { | |
125 List<String> fields = new List<String>(); | |
126 int index = 0; | |
127 StringBuffer sb = new StringBuffer(); | |
128 while (index < line.length) { | |
129 int code = line.codeUnitAt(index); | |
130 if (code == COLON) { | |
131 // Embedded colons are doubled | |
132 int next = index + 1; | |
133 if (next < line.length && line.codeUnitAt(next) == COLON) { | |
134 sb.write(':'); | |
135 ++index; | |
136 } else { | |
137 fields.add(sb.toString()); | |
138 sb.clear(); | |
139 } | |
140 } else { | |
141 sb.writeCharCode(code); | |
142 } | |
143 ++index; | |
144 } | |
145 if (sb.isNotEmpty) { | |
146 fields.add(sb.toString()); | |
147 } | |
148 return fields; | |
149 } | |
150 } | |
OLD | NEW |