Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(83)

Side by Side Diff: observatory_pub_packages/analyzer/src/analyzer_impl.dart

Issue 816693004: Add observatory_pub_packages snapshot to third_party (Closed) Base URL: http://dart.googlecode.com/svn/third_party/
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2013, 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 analyzer_impl;
6
7 import 'dart:async';
8
9 import 'dart:io';
10
11 import 'generated/constant.dart';
12 import 'generated/engine.dart';
13 import 'generated/element.dart';
14 import 'generated/error.dart';
15 import 'generated/java_io.dart';
16 import 'generated/sdk.dart';
17 import 'generated/sdk_io.dart';
18 import 'generated/source_io.dart';
19 import '../options.dart';
20
21 import 'dart:collection';
22
23 import 'package:analyzer/src/generated/java_core.dart' show JavaSystem;
24 import 'package:analyzer/src/error_formatter.dart';
25
26 /**
27 * The maximum number of sources for which AST structures should be kept in the cache.
28 */
29 const int _MAX_CACHE_SIZE = 512;
30
31 DartSdk sdk;
32
33 /// Analyzes single library [File].
34 class AnalyzerImpl {
35 final String sourcePath;
36 final CommandLineOptions options;
37 final int startTime;
38
39 ContentCache contentCache = new ContentCache();
40 SourceFactory sourceFactory;
41 AnalysisContext context;
42 Source librarySource;
43
44 /// All [Source]s references by the analyzed library.
45 final Set<Source> sources = new Set<Source>();
46
47 /// All [AnalysisErrorInfo]s in the analyzed library.
48 final List<AnalysisErrorInfo> errorInfos = new List<AnalysisErrorInfo>();
49
50 /// [HashMap] between sources and analysis error infos.
51 final HashMap<Source, AnalysisErrorInfo> sourceErrorsMap = new HashMap<Source, AnalysisErrorInfo>();
52
53 AnalyzerImpl(this.sourcePath, this.options, this.startTime) {
54 if (sdk == null) {
55 sdk = new DirectoryBasedDartSdk(new JavaFile(options.dartSdkPath));
56 }
57 }
58
59 /**
60 * Treats the [sourcePath] as the top level library and analyzes it using a
61 * synchronous algorithm over the analysis engine. If [printMode] is `0`,
62 * then no error or performance information is printed. If [printMode] is `1`,
63 * then both will be printed. If [printMode] is `2`, then only performance
64 * information will be printed, and it will be marked as being for a cold VM.
65 */
66 ErrorSeverity analyzeSync({int printMode : 1}) {
67 setupForAnalysis();
68 return _analyzeSync(printMode);
69 }
70
71 /**
72 * Treats the [sourcePath] as the top level library and analyzes it using a
73 * asynchronous algorithm over the analysis engine.
74 */
75 void analyzeAsync() {
76 setupForAnalysis();
77 _analyzeAsync();
78 }
79
80 /**
81 * Setup local fields such as the analysis context for analysis.
82 */
83 void setupForAnalysis() {
84 sources.clear();
85 errorInfos.clear();
86 if (sourcePath == null) {
87 throw new ArgumentError("sourcePath cannot be null");
88 }
89 JavaFile sourceFile = new JavaFile(sourcePath);
90 Uri uri = getUri(sourceFile);
91 librarySource = new FileBasedSource.con2(uri, sourceFile);
92
93 // prepare context
94 prepareAnalysisContext(sourceFile, librarySource);
95 }
96
97 /// The sync version of analysis.
98 ErrorSeverity _analyzeSync(int printMode) {
99 // don't try to analyze parts
100 if (context.computeKindOf(librarySource) == SourceKind.PART) {
101 print("Only libraries can be analyzed.");
102 print("$sourcePath is a part and can not be analyzed.");
103 return ErrorSeverity.ERROR;
104 }
105 // resolve library
106 var libraryElement = context.computeLibraryElement(librarySource);
107 // prepare source and errors
108 prepareSources(libraryElement);
109 prepareErrors();
110
111 // print errors and performance numbers
112 if (printMode == 1) {
113 _printErrorsAndPerf();
114 } else if (printMode == 2) {
115 _printColdPerf();
116 }
117
118 // compute max severity and set exitCode
119 ErrorSeverity status = maxErrorSeverity;
120 if (status == ErrorSeverity.WARNING && options.warningsAreFatal) {
121 status = ErrorSeverity.ERROR;
122 }
123 return status;
124 }
125
126 /// The async version of the analysis
127 void _analyzeAsync() {
128 new Future(context.performAnalysisTask).then((AnalysisResult result) {
129 List<ChangeNotice> notices = result.changeNotices;
130 if (result.hasMoreWork) {
131 // There is more work, record the set of sources, and then call self
132 // again to perform next task
133 for (ChangeNotice notice in notices) {
134 sources.add(notice.source);
135 sourceErrorsMap[notice.source] = notice;
136 }
137 return _analyzeAsync();
138 }
139 //
140 // There are not any more tasks, set error code and print performance
141 // numbers.
142 //
143 // prepare errors
144 sourceErrorsMap.forEach((k,v) {
145 errorInfos.add(sourceErrorsMap[k]);
146 });
147
148 // print errors and performance numbers
149 _printErrorsAndPerf();
150
151 // compute max severity and set exitCode
152 ErrorSeverity status = maxErrorSeverity;
153 if (status == ErrorSeverity.WARNING && options.warningsAreFatal) {
154 status = ErrorSeverity.ERROR;
155 }
156 exitCode = status.ordinal;
157 }).catchError((ex, st) {
158 AnalysisEngine.instance.logger.logError("${ex}\n${st}");
159 });
160 }
161
162 bool _excludeTodo(AnalysisError error) => error.errorCode.type != ErrorType.TO DO;
163
164 _printErrorsAndPerf() {
165 // The following is a hack. We currently print out to stderr to ensure that
166 // when in batch mode we print to stderr, this is because the prints from
167 // batch are made to stderr. The reason that options.shouldBatch isn't used
168 // is because when the argument flags are constructed in BatchRunner and
169 // passed in from batch mode which removes the batch flag to prevent the
170 // "cannot have the batch flag and source file" error message.
171 IOSink sink = options.machineFormat ? stderr : stdout;
172
173 // print errors
174 ErrorFormatter formatter = new ErrorFormatter(sink, options, _excludeTodo);
175 formatter.formatErrors(errorInfos);
176
177 // print performance numbers
178 if (options.perf || options.warmPerf) {
179 int totalTime = JavaSystem.currentTimeMillis() - startTime;
180 int ioTime = PerformanceStatistics.io.result;
181 int scanTime = PerformanceStatistics.scan.result;
182 int parseTime = PerformanceStatistics.parse.result;
183 int resolveTime = PerformanceStatistics.resolve.result;
184 int errorsTime = PerformanceStatistics.errors.result;
185 int hintsTime = PerformanceStatistics.hints.result;
186 int angularTime = PerformanceStatistics.angular.result;
187 stdout.writeln("io:$ioTime");
188 stdout.writeln("scan:$scanTime");
189 stdout.writeln("parse:$parseTime");
190 stdout.writeln("resolve:$resolveTime");
191 stdout.writeln("errors:$errorsTime");
192 stdout.writeln("hints:$hintsTime");
193 stdout.writeln("angular:$angularTime");
194 stdout.writeln("other:${totalTime
195 - (ioTime + scanTime + parseTime + resolveTime + errorsTime + hintsTim e
196 + angularTime)}");
197 stdout.writeln("total:$totalTime");
198 }
199 }
200
201 _printColdPerf() {
202 // print cold VM performance numbers
203 int totalTime = JavaSystem.currentTimeMillis() - startTime;
204 int ioTime = PerformanceStatistics.io.result;
205 int scanTime = PerformanceStatistics.scan.result;
206 int parseTime = PerformanceStatistics.parse.result;
207 int resolveTime = PerformanceStatistics.resolve.result;
208 int errorsTime = PerformanceStatistics.errors.result;
209 int hintsTime = PerformanceStatistics.hints.result;
210 int angularTime = PerformanceStatistics.angular.result;
211 stdout.writeln("io-cold:$ioTime");
212 stdout.writeln("scan-cold:$scanTime");
213 stdout.writeln("parse-cold:$parseTime");
214 stdout.writeln("resolve-cold:$resolveTime");
215 stdout.writeln("errors-cold:$errorsTime");
216 stdout.writeln("hints-cold:$hintsTime");
217 stdout.writeln("angular-cold:$angularTime");
218 stdout.writeln("other-cold:${totalTime
219 - (ioTime + scanTime + parseTime + resolveTime + errorsTime + hintsTime
220 + angularTime)}");
221 stdout.writeln("total-cold:$totalTime");
222 }
223
224 /// Returns the maximal [ErrorSeverity] of the recorded errors.
225 ErrorSeverity get maxErrorSeverity {
226 var status = ErrorSeverity.NONE;
227 for (AnalysisErrorInfo errorInfo in errorInfos) {
228 for (AnalysisError error in errorInfo.errors) {
229 var severity = error.errorCode.errorSeverity;
230 status = status.max(severity);
231 }
232 }
233 return status;
234 }
235
236 void prepareAnalysisContext(JavaFile sourceFile, Source source) {
237 List<UriResolver> resolvers = [new DartUriResolver(sdk), new FileUriResolver ()];
238 // may be add package resolver
239 {
240 JavaFile packageDirectory;
241 if (options.packageRootPath != null) {
242 packageDirectory = new JavaFile(options.packageRootPath);
243 } else {
244 packageDirectory = getPackageDirectoryFor(sourceFile);
245 }
246 if (packageDirectory != null) {
247 resolvers.add(new PackageUriResolver([packageDirectory]));
248 }
249 }
250 sourceFactory = new SourceFactory(resolvers);
251 context = AnalysisEngine.instance.createAnalysisContext();
252 context.sourceFactory = sourceFactory;
253 Map<String, String> definedVariables = options.definedVariables;
254 if (!definedVariables.isEmpty) {
255 DeclaredVariables declaredVariables = context.declaredVariables;
256 definedVariables.forEach((String variableName, String value) {
257 declaredVariables.define(variableName, value);
258 });
259 }
260 // Uncomment the following to have errors reported on stdout and stderr
261 AnalysisEngine.instance.logger = new StdLogger(options.log);
262
263 // set options for context
264 AnalysisOptionsImpl contextOptions = new AnalysisOptionsImpl();
265 contextOptions.cacheSize = _MAX_CACHE_SIZE;
266 contextOptions.hint = !options.disableHints;
267 contextOptions.enableAsync = options.enableAsync;
268 contextOptions.enableEnum = options.enableEnum;
269 context.analysisOptions = contextOptions;
270
271 // Create and add a ChangeSet
272 ChangeSet changeSet = new ChangeSet();
273 changeSet.addedSource(source);
274 context.applyChanges(changeSet);
275 }
276
277 void addCompilationUnitSource(CompilationUnitElement unit, Set<LibraryElement> libraries,
278 Set<CompilationUnitElement> units) {
279 if (unit == null || units.contains(unit)) {
280 return;
281 }
282 units.add(unit);
283 sources.add(unit.source);
284 }
285
286 void addLibrarySources(LibraryElement library, Set<LibraryElement> libraries,
287 Set<CompilationUnitElement> units) {
288 if (library == null || !libraries.add(library) ) {
289 return;
290 }
291 // may be skip library
292 {
293 UriKind uriKind = library.source.uriKind;
294 // Optionally skip package: libraries.
295 if (!options.showPackageWarnings && uriKind == UriKind.PACKAGE_URI) {
296 return;
297 }
298 // Optionally skip SDK libraries.
299 if (!options.showSdkWarnings && uriKind == UriKind.DART_URI) {
300 return;
301 }
302 }
303 // add compilation units
304 addCompilationUnitSource(library.definingCompilationUnit, libraries, units);
305 for (CompilationUnitElement child in library.parts) {
306 addCompilationUnitSource(child, libraries, units);
307 }
308 // add referenced libraries
309 for (LibraryElement child in library.importedLibraries) {
310 addLibrarySources(child, libraries, units);
311 }
312 for (LibraryElement child in library.exportedLibraries) {
313 addLibrarySources(child, libraries, units);
314 }
315 }
316
317 /// Fills [sources].
318 void prepareSources(LibraryElement library) {
319 var units = new Set<CompilationUnitElement>();
320 var libraries = new Set<LibraryElement>();
321 addLibrarySources(library, libraries, units);
322 }
323
324 /// Fills [errorInfos] using [sources].
325 void prepareErrors() {
326 for (Source source in sources) {
327 context.computeErrors(source);
328 var sourceErrors = context.getErrors(source);
329 errorInfos.add(sourceErrors);
330 }
331 }
332
333 static JavaFile getPackageDirectoryFor(JavaFile sourceFile) {
334 // we are going to ask parent file, so get absolute path
335 sourceFile = sourceFile.getAbsoluteFile();
336 // look in the containing directories
337 JavaFile dir = sourceFile.getParentFile();
338 while (dir != null) {
339 JavaFile packagesDir = new JavaFile.relative(dir, "packages");
340 if (packagesDir.exists()) {
341 return packagesDir;
342 }
343 dir = dir.getParentFile();
344 }
345 // not found
346 return null;
347 }
348
349 /**
350 * Returns the [Uri] for the given input file.
351 *
352 * Usually it is a `file:` [Uri], but if [file] is located in the `lib`
353 * directory of the [sdk], then returns a `dart:` [Uri].
354 */
355 static Uri getUri(JavaFile file) {
356 // may be file in SDK
357 {
358 Source source = sdk.fromFileUri(file.toURI());
359 if (source != null) {
360 return source.uri;
361 }
362 }
363 // some generic file
364 return file.toURI();
365 }
366 }
367
368 /**
369 * This [Logger] prints out information comments to [stdout] and error messages
370 * to [stderr].
371 */
372 class StdLogger extends Logger {
373 final bool log;
374
375 StdLogger(this.log);
376
377 @override
378 void logError(String message) {
379 stderr.writeln(message);
380 }
381
382 @override
383 void logError2(String message, Exception exception) {
384 stderr.writeln(message);
385 }
386
387 @override
388 void logInformation(String message) {
389 if (log) {
390 stdout.writeln(message);
391 }
392 }
393
394 @override
395 void logInformation2(String message, Exception exception) {
396 if (log) {
397 stdout.writeln(message);
398 }
399 }
400 }
OLDNEW
« no previous file with comments | « observatory_pub_packages/analyzer/source/package_map_resolver.dart ('k') | observatory_pub_packages/analyzer/src/error.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698