Index: pkg/analyzer/lib/src/analyzer_impl.dart |
=================================================================== |
--- pkg/analyzer/lib/src/analyzer_impl.dart (revision 45350) |
+++ pkg/analyzer/lib/src/analyzer_impl.dart (working copy) |
@@ -1,498 +0,0 @@ |
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
-// for details. All rights reserved. Use of this source code is governed by a |
-// BSD-style license that can be found in the LICENSE file. |
- |
-library analyzer_impl; |
- |
-import 'dart:async'; |
-import 'dart:collection'; |
-import 'dart:io'; |
- |
-import 'package:analyzer/file_system/file_system.dart' show Folder; |
-import 'package:analyzer/file_system/physical_file_system.dart'; |
-import 'package:analyzer/source/package_map_provider.dart'; |
-import 'package:analyzer/source/package_map_resolver.dart'; |
-import 'package:analyzer/source/pub_package_map_provider.dart'; |
-import 'package:analyzer/src/error_formatter.dart'; |
-import 'package:analyzer/src/generated/java_core.dart' show JavaSystem; |
-import 'package:analyzer/src/generated/java_engine.dart'; |
-import 'package:analyzer/src/generated/utilities_general.dart'; |
- |
-import '../options.dart'; |
-import 'generated/constant.dart'; |
-import 'generated/element.dart'; |
-import 'generated/engine.dart'; |
-import 'generated/error.dart'; |
-import 'generated/java_io.dart'; |
-import 'generated/sdk_io.dart'; |
-import 'generated/source_io.dart'; |
- |
-DirectoryBasedDartSdk sdk; |
- |
-/** |
- * The maximum number of sources for which AST structures should be kept in the cache. |
- */ |
-const int _MAX_CACHE_SIZE = 512; |
- |
-/// Analyzes single library [File]. |
-class AnalyzerImpl { |
- final String sourcePath; |
- |
- final CommandLineOptions options; |
- final int startTime; |
- |
- /** |
- * True if the analyzer is running in batch mode. |
- */ |
- final bool isBatch; |
- |
- ContentCache contentCache = new ContentCache(); |
- |
- SourceFactory sourceFactory; |
- AnalysisContext context; |
- Source librarySource; |
- /// All [Source]s references by the analyzed library. |
- final Set<Source> sources = new Set<Source>(); |
- |
- /// All [AnalysisErrorInfo]s in the analyzed library. |
- final List<AnalysisErrorInfo> errorInfos = new List<AnalysisErrorInfo>(); |
- |
- /// [HashMap] between sources and analysis error infos. |
- final HashMap<Source, AnalysisErrorInfo> sourceErrorsMap = |
- new HashMap<Source, AnalysisErrorInfo>(); |
- |
- /** |
- * If the file specified on the command line is part of a package, the name |
- * of that package. Otherwise `null`. This allows us to analyze the file |
- * specified on the command line as though it is reached via a "package:" |
- * URI, but avoid suppressing its output in the event that the user has not |
- * specified the "--package-warnings" option. |
- */ |
- String _selfPackageName; |
- |
- AnalyzerImpl(String sourcePath, this.options, this.startTime, this.isBatch) |
- : sourcePath = _normalizeSourcePath(sourcePath) { |
- if (sdk == null) { |
- sdk = new DirectoryBasedDartSdk(new JavaFile(options.dartSdkPath)); |
- } |
- } |
- |
- /// Returns the maximal [ErrorSeverity] of the recorded errors. |
- ErrorSeverity get maxErrorSeverity { |
- var status = ErrorSeverity.NONE; |
- for (AnalysisErrorInfo errorInfo in errorInfos) { |
- for (AnalysisError error in errorInfo.errors) { |
- if (!_isDesiredError(error)) { |
- continue; |
- } |
- var severity = computeSeverity(error, options.enableTypeChecks); |
- status = status.max(severity); |
- } |
- } |
- return status; |
- } |
- |
- void addCompilationUnitSource(CompilationUnitElement unit, |
- Set<LibraryElement> libraries, Set<CompilationUnitElement> units) { |
- if (unit == null || units.contains(unit)) { |
- return; |
- } |
- units.add(unit); |
- sources.add(unit.source); |
- } |
- |
- void addLibrarySources(LibraryElement library, Set<LibraryElement> libraries, |
- Set<CompilationUnitElement> units) { |
- if (library == null || !libraries.add(library)) { |
- return; |
- } |
- // may be skip library |
- { |
- UriKind uriKind = library.source.uriKind; |
- // Optionally skip package: libraries. |
- if (!options.showPackageWarnings && _isOtherPackage(library.source.uri)) { |
- return; |
- } |
- // Optionally skip SDK libraries. |
- if (!options.showSdkWarnings && uriKind == UriKind.DART_URI) { |
- return; |
- } |
- } |
- // add compilation units |
- addCompilationUnitSource(library.definingCompilationUnit, libraries, units); |
- for (CompilationUnitElement child in library.parts) { |
- addCompilationUnitSource(child, libraries, units); |
- } |
- // add referenced libraries |
- for (LibraryElement child in library.importedLibraries) { |
- addLibrarySources(child, libraries, units); |
- } |
- for (LibraryElement child in library.exportedLibraries) { |
- addLibrarySources(child, libraries, units); |
- } |
- } |
- |
- /** |
- * Treats the [sourcePath] as the top level library and analyzes it using a |
- * asynchronous algorithm over the analysis engine. |
- */ |
- void analyzeAsync() { |
- setupForAnalysis(); |
- _analyzeAsync(); |
- } |
- |
- /** |
- * Treats the [sourcePath] as the top level library and analyzes it using a |
- * synchronous algorithm over the analysis engine. If [printMode] is `0`, |
- * then no error or performance information is printed. If [printMode] is `1`, |
- * then both will be printed. If [printMode] is `2`, then only performance |
- * information will be printed, and it will be marked as being for a cold VM. |
- */ |
- ErrorSeverity analyzeSync({int printMode: 1}) { |
- setupForAnalysis(); |
- return _analyzeSync(printMode); |
- } |
- |
- Source computeLibrarySource() { |
- JavaFile sourceFile = new JavaFile(sourcePath); |
- Source source = sdk.fromFileUri(sourceFile.toURI()); |
- if (source != null) { |
- return source; |
- } |
- source = new FileBasedSource.con2(sourceFile.toURI(), sourceFile); |
- Uri uri = context.sourceFactory.restoreUri(source); |
- if (uri == null) { |
- return source; |
- } |
- return new FileBasedSource.con2(uri, sourceFile); |
- } |
- |
- /** |
- * Create and return the source factory to be used by the analysis context. |
- */ |
- SourceFactory createSourceFactory() { |
- List<UriResolver> resolvers = [ |
- new CustomUriResolver(options.customUrlMappings), |
- new DartUriResolver(sdk) |
- ]; |
- if (options.packageRootPath != null) { |
- JavaFile packageDirectory = new JavaFile(options.packageRootPath); |
- resolvers.add(new PackageUriResolver([packageDirectory])); |
- } else { |
- PubPackageMapProvider pubPackageMapProvider = |
- new PubPackageMapProvider(PhysicalResourceProvider.INSTANCE, sdk); |
- PackageMapInfo packageMapInfo = pubPackageMapProvider.computePackageMap( |
- PhysicalResourceProvider.INSTANCE.getResource('.')); |
- Map<String, List<Folder>> packageMap = packageMapInfo.packageMap; |
- if (packageMap != null) { |
- resolvers.add(new PackageMapUriResolver( |
- PhysicalResourceProvider.INSTANCE, packageMap)); |
- } |
- } |
- resolvers.add(new FileUriResolver()); |
- return new SourceFactory(resolvers); |
- } |
- |
- void prepareAnalysisContext() { |
- sourceFactory = createSourceFactory(); |
- context = AnalysisEngine.instance.createAnalysisContext(); |
- context.sourceFactory = sourceFactory; |
- Map<String, String> definedVariables = options.definedVariables; |
- if (!definedVariables.isEmpty) { |
- DeclaredVariables declaredVariables = context.declaredVariables; |
- definedVariables.forEach((String variableName, String value) { |
- declaredVariables.define(variableName, value); |
- }); |
- } |
- // Uncomment the following to have errors reported on stdout and stderr |
- AnalysisEngine.instance.logger = new StdLogger(options.log); |
- |
- // set options for context |
- AnalysisOptionsImpl contextOptions = new AnalysisOptionsImpl(); |
- contextOptions.cacheSize = _MAX_CACHE_SIZE; |
- contextOptions.hint = !options.disableHints; |
- contextOptions.enableNullAwareOperators = options.enableNullAwareOperators; |
- contextOptions.enableStrictCallChecks = options.enableStrictCallChecks; |
- contextOptions.analyzeFunctionBodiesPredicate = |
- _analyzeFunctionBodiesPredicate; |
- contextOptions.generateImplicitErrors = options.showPackageWarnings; |
- contextOptions.generateSdkErrors = options.showSdkWarnings; |
- context.analysisOptions = contextOptions; |
- |
- librarySource = computeLibrarySource(); |
- |
- Uri libraryUri = librarySource.uri; |
- if (libraryUri.scheme == 'package' && libraryUri.pathSegments.length > 0) { |
- _selfPackageName = libraryUri.pathSegments[0]; |
- } |
- |
- // Create and add a ChangeSet |
- ChangeSet changeSet = new ChangeSet(); |
- changeSet.addedSource(librarySource); |
- context.applyChanges(changeSet); |
- } |
- |
- /// Fills [errorInfos] using [sources]. |
- void prepareErrors() { |
- for (Source source in sources) { |
- context.computeErrors(source); |
- var sourceErrors = context.getErrors(source); |
- errorInfos.add(sourceErrors); |
- } |
- } |
- |
- /// Fills [sources]. |
- void prepareSources(LibraryElement library) { |
- var units = new Set<CompilationUnitElement>(); |
- var libraries = new Set<LibraryElement>(); |
- addLibrarySources(library, libraries, units); |
- } |
- |
- /** |
- * Setup local fields such as the analysis context for analysis. |
- */ |
- void setupForAnalysis() { |
- sources.clear(); |
- errorInfos.clear(); |
- if (sourcePath == null) { |
- throw new ArgumentError("sourcePath cannot be null"); |
- } |
- // prepare context |
- prepareAnalysisContext(); |
- } |
- |
- /// The async version of the analysis |
- void _analyzeAsync() { |
- new Future(context.performAnalysisTask).then((AnalysisResult result) { |
- List<ChangeNotice> notices = result.changeNotices; |
- if (result.hasMoreWork) { |
- // There is more work, record the set of sources, and then call self |
- // again to perform next task |
- for (ChangeNotice notice in notices) { |
- sources.add(notice.source); |
- sourceErrorsMap[notice.source] = notice; |
- } |
- return _analyzeAsync(); |
- } |
- // |
- // There are not any more tasks, set error code and print performance |
- // numbers. |
- // |
- // prepare errors |
- sourceErrorsMap.forEach((k, v) { |
- errorInfos.add(sourceErrorsMap[k]); |
- }); |
- |
- // print errors and performance numbers |
- _printErrorsAndPerf(); |
- |
- // compute max severity and set exitCode |
- ErrorSeverity status = maxErrorSeverity; |
- if (status == ErrorSeverity.WARNING && options.warningsAreFatal) { |
- status = ErrorSeverity.ERROR; |
- } |
- exitCode = status.ordinal; |
- }).catchError((ex, st) { |
- AnalysisEngine.instance.logger.logError("$ex\n$st"); |
- }); |
- } |
- |
- bool _analyzeFunctionBodiesPredicate(Source source) { |
- // TODO(paulberry): This function will need to be updated when we add the |
- // ability to suppress errors, warnings, and hints for files reached via |
- // custom URI's using the "--url-mapping" flag. |
- if (source.uri.scheme == 'dart') { |
- if (isBatch) { |
- // When running in batch mode, the SDK files are cached from one |
- // analysis run to the next. So we need to parse function bodies even |
- // if the user hasn't asked for errors/warnings from the SDK, since |
- // they might ask for errors/warnings from the SDK in the future. |
- return true; |
- } |
- return options.showSdkWarnings; |
- } |
- if (_isOtherPackage(source.uri)) { |
- return options.showPackageWarnings; |
- } |
- return true; |
- } |
- |
- /// The sync version of analysis. |
- ErrorSeverity _analyzeSync(int printMode) { |
- // don't try to analyze parts |
- if (context.computeKindOf(librarySource) == SourceKind.PART) { |
- print("Only libraries can be analyzed."); |
- print("$sourcePath is a part and can not be analyzed."); |
- return ErrorSeverity.ERROR; |
- } |
- // resolve library |
- var libraryElement = context.computeLibraryElement(librarySource); |
- // prepare source and errors |
- prepareSources(libraryElement); |
- prepareErrors(); |
- |
- // print errors and performance numbers |
- if (printMode == 1) { |
- _printErrorsAndPerf(); |
- } else if (printMode == 2) { |
- _printColdPerf(); |
- } |
- |
- // compute max severity and set exitCode |
- ErrorSeverity status = maxErrorSeverity; |
- if (status == ErrorSeverity.WARNING && options.warningsAreFatal) { |
- status = ErrorSeverity.ERROR; |
- } |
- return status; |
- } |
- |
- bool _isDesiredError(AnalysisError error) { |
- if (error.errorCode.type == ErrorType.TODO) { |
- return false; |
- } |
- if (computeSeverity(error, options.enableTypeChecks) == |
- ErrorSeverity.INFO && |
- options.disableHints) { |
- return false; |
- } |
- return true; |
- } |
- |
- /** |
- * Determine whether the given URI refers to a package other than the package |
- * being analyzed. |
- */ |
- bool _isOtherPackage(Uri uri) { |
- if (uri.scheme != 'package') { |
- return false; |
- } |
- if (_selfPackageName != null && |
- uri.pathSegments.length > 0 && |
- uri.pathSegments[0] == _selfPackageName) { |
- return false; |
- } |
- return true; |
- } |
- |
- _printColdPerf() { |
- // print cold VM performance numbers |
- int totalTime = JavaSystem.currentTimeMillis() - startTime; |
- int otherTime = totalTime; |
- for (PerformanceTag tag in PerformanceTag.all) { |
- if (tag != PerformanceTag.UNKNOWN) { |
- int tagTime = tag.elapsedMs; |
- stdout.writeln('${tag.label}-cold:$tagTime'); |
- otherTime -= tagTime; |
- } |
- } |
- stdout.writeln('other-cold:$otherTime'); |
- stdout.writeln("total-cold:$totalTime"); |
- } |
- |
- _printErrorsAndPerf() { |
- // The following is a hack. We currently print out to stderr to ensure that |
- // when in batch mode we print to stderr, this is because the prints from |
- // batch are made to stderr. The reason that options.shouldBatch isn't used |
- // is because when the argument flags are constructed in BatchRunner and |
- // passed in from batch mode which removes the batch flag to prevent the |
- // "cannot have the batch flag and source file" error message. |
- IOSink sink = options.machineFormat ? stderr : stdout; |
- |
- // print errors |
- ErrorFormatter formatter = |
- new ErrorFormatter(sink, options, _isDesiredError); |
- formatter.formatErrors(errorInfos); |
- |
- // print performance numbers |
- if (options.perf || options.warmPerf) { |
- int totalTime = JavaSystem.currentTimeMillis() - startTime; |
- int otherTime = totalTime; |
- for (PerformanceTag tag in PerformanceTag.all) { |
- if (tag != PerformanceTag.UNKNOWN) { |
- int tagTime = tag.elapsedMs; |
- stdout.writeln('${tag.label}:$tagTime'); |
- otherTime -= tagTime; |
- } |
- } |
- stdout.writeln('other:$otherTime'); |
- stdout.writeln("total:$totalTime"); |
- } |
- } |
- |
- /** |
- * Compute the severity of the error; however, if |
- * [enableTypeChecks] is false, then de-escalate checked-mode compile time |
- * errors to a severity of [ErrorSeverity.INFO]. |
- */ |
- static ErrorSeverity computeSeverity( |
- AnalysisError error, bool enableTypeChecks) { |
- if (!enableTypeChecks && |
- error.errorCode.type == ErrorType.CHECKED_MODE_COMPILE_TIME_ERROR) { |
- return ErrorSeverity.INFO; |
- } |
- return error.errorCode.errorSeverity; |
- } |
- |
- static JavaFile getPackageDirectoryFor(JavaFile sourceFile) { |
- // we are going to ask parent file, so get absolute path |
- sourceFile = sourceFile.getAbsoluteFile(); |
- // look in the containing directories |
- JavaFile dir = sourceFile.getParentFile(); |
- while (dir != null) { |
- JavaFile packagesDir = new JavaFile.relative(dir, "packages"); |
- if (packagesDir.exists()) { |
- return packagesDir; |
- } |
- dir = dir.getParentFile(); |
- } |
- // not found |
- return null; |
- } |
- |
- /** |
- * Convert [sourcePath] into an absolute path. |
- */ |
- static String _normalizeSourcePath(String sourcePath) { |
- return new File(sourcePath).absolute.path; |
- } |
-} |
- |
-/** |
- * This [Logger] prints out information comments to [stdout] and error messages |
- * to [stderr]. |
- */ |
-class StdLogger extends Logger { |
- final bool log; |
- |
- StdLogger(this.log); |
- |
- @override |
- void logError(String message, [CaughtException exception]) { |
- stderr.writeln(message); |
- if (exception != null) { |
- stderr.writeln(exception); |
- } |
- } |
- |
- @override |
- void logError2(String message, Object exception) { |
- stderr.writeln(message); |
- } |
- |
- @override |
- void logInformation(String message, [CaughtException exception]) { |
- if (log) { |
- stdout.writeln(message); |
- if (exception != null) { |
- stderr.writeln(exception); |
- } |
- } |
- } |
- |
- @override |
- void logInformation2(String message, Object exception) { |
- if (log) { |
- stdout.writeln(message); |
- } |
- } |
-} |