blob: 746c77a22d14836f4e9475346f2086cc6ed2855c [file] [log] [blame]
// Copyright (c) 2015, 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_cli.src.package_analyzer;
import 'dart:core' hide Resource;
import 'dart:io' as io;
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/source/package_map_resolver.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/java_io.dart';
import 'package:analyzer/src/generated/sdk_io.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/source_io.dart';
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/package_bundle_reader.dart';
import 'package:analyzer/src/summary/summarize_elements.dart';
import 'package:analyzer_cli/src/analyzer_impl.dart';
import 'package:analyzer_cli/src/driver.dart';
import 'package:analyzer_cli/src/error_formatter.dart';
import 'package:analyzer_cli/src/options.dart';
import 'package:path/path.dart' as pathos;
/**
* The hermetic whole package analyzer.
*/
class PackageAnalyzer {
final CommandLineOptions options;
String packagePath;
String packageLibPath;
final ResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE;
InternalAnalysisContext context;
final List<Source> explicitSources = <Source>[];
PackageAnalyzer(this.options);
/**
* Perform package analysis according to the given [options].
*/
ErrorSeverity analyze() {
packagePath = options.packageModePath;
packageLibPath = resourceProvider.pathContext.join(packagePath, 'lib');
if (packageLibPath == null) {
errorSink.writeln('--package-mode-path must be set to the root '
'folder of the package to analyze.');
io.exitCode = ErrorSeverity.ERROR.ordinal;
return ErrorSeverity.ERROR;
}
// Write the progress message.
if (!options.machineFormat) {
outSink.writeln("Analyzing sources ${options.sourceFiles}...");
}
// Prepare the analysis context.
_createContext();
// Add sources.
ChangeSet changeSet = new ChangeSet();
for (String path in options.sourceFiles) {
if (AnalysisEngine.isDartFileName(path)) {
path = resourceProvider.pathContext.absolute(path);
File file = resourceProvider.getFile(path);
if (!file.exists) {
errorSink.writeln('File not found: $path');
io.exitCode = ErrorSeverity.ERROR.ordinal;
return ErrorSeverity.ERROR;
}
Source source = _createSourceInContext(file);
explicitSources.add(source);
changeSet.addedSource(source);
}
}
context.applyChanges(changeSet);
// Perform full analysis.
while (true) {
AnalysisResult analysisResult = context.performAnalysisTask();
if (!analysisResult.hasMoreWork) {
break;
}
}
// Write summary for Dart libraries.
if (options.packageSummaryOutput != null) {
PackageBundleAssembler assembler = new PackageBundleAssembler();
for (Source source in context.librarySources) {
if (pathos.isWithin(packageLibPath, source.fullName)) {
LibraryElement libraryElement = context.getLibraryElement(source);
if (libraryElement != null) {
assembler.serializeLibraryElement(libraryElement);
}
}
}
// Write the whole package bundle.
PackageBundleBuilder sdkBundle = assembler.assemble();
io.File file = new io.File(options.packageSummaryOutput);
file.writeAsBytesSync(sdkBundle.toBuffer(), mode: io.FileMode.WRITE_ONLY);
}
// Process errors.
_printErrors();
return _computeMaxSeverity();
}
ErrorSeverity _computeMaxSeverity() {
ErrorSeverity maxSeverity = ErrorSeverity.NONE;
for (Source source in explicitSources) {
AnalysisErrorInfo errorInfo = context.getErrors(source);
for (AnalysisError error in errorInfo.errors) {
ProcessedSeverity processedSeverity =
AnalyzerImpl.processError(error, options, context);
if (processedSeverity != null) {
maxSeverity = maxSeverity.max(processedSeverity.severity);
}
}
}
return maxSeverity;
}
void _createContext() {
DirectoryBasedDartSdk sdk =
new DirectoryBasedDartSdk(new JavaFile(options.dartSdkPath));
// Create the context.
context = AnalysisEngine.instance.createAnalysisContext();
context.sourceFactory = new SourceFactory(<UriResolver>[
new DartUriResolver(sdk),
new InSummaryPackageUriResolver(options.packageSummaryInputs),
new PackageMapUriResolver(resourceProvider, <String, List<Folder>>{
options.packageName: <Folder>[
resourceProvider.getFolder(packageLibPath)
],
}),
new FileUriResolver()
]);
// Set context options.
Driver.setAnalysisContextOptions(
context, options, (AnalysisOptionsImpl contextOptions) {});
// Configure using summaries.
sdk.useSummary = true;
context.typeProvider = sdk.context.typeProvider;
context.resultProvider =
new InputPackagesResultProvider(context, options.packageSummaryInputs);
}
/**
* Create and return a source representing the given [file].
*/
Source _createSourceInContext(File file) {
Source source = file.createSource();
if (context == null) {
return source;
}
Uri uri = context.sourceFactory.restoreUri(source);
return file.createSource(uri);
}
/**
* Print errors for all explicit sources.
*/
void _printErrors() {
StringSink sink = options.machineFormat ? errorSink : outSink;
ErrorFormatter formatter = new ErrorFormatter(
sink,
options,
(AnalysisError error) =>
AnalyzerImpl.processError(error, options, context));
for (Source source in explicitSources) {
AnalysisErrorInfo errorInfo = context.getErrors(source);
formatter.formatErrors([errorInfo]);
}
}
}