| Index: pkg/analyzer/lib/src/task/dart.dart
|
| diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..9c741a64b2d74c783b0c248d1e0ec085bab14d3c
|
| --- /dev/null
|
| +++ b/pkg/analyzer/lib/src/task/dart.dart
|
| @@ -0,0 +1,314 @@
|
| +// 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.src.task.dart;
|
| +
|
| +import 'dart:collection';
|
| +
|
| +import 'package:analyzer/src/generated/ast.dart';
|
| +import 'package:analyzer/src/generated/element.dart';
|
| +import 'package:analyzer/src/generated/engine.dart' hide AnalysisTask;
|
| +import 'package:analyzer/src/generated/error.dart';
|
| +import 'package:analyzer/src/generated/java_engine.dart';
|
| +import 'package:analyzer/src/generated/parser.dart';
|
| +import 'package:analyzer/src/generated/resolver.dart';
|
| +import 'package:analyzer/src/generated/scanner.dart';
|
| +import 'package:analyzer/src/generated/source.dart';
|
| +import 'package:analyzer/src/task/general.dart';
|
| +import 'package:analyzer/task/dart.dart';
|
| +import 'package:analyzer/task/general.dart';
|
| +import 'package:analyzer/task/model.dart';
|
| +
|
| +/**
|
| + * A task that builds a compilation unit element for a single compilation unit.
|
| + */
|
| +class BuildCompilationUnitElementTask extends SourceBasedAnalysisTask {
|
| + /**
|
| + * The name of the input whose value is the line information for the
|
| + * compilation unit.
|
| + */
|
| + static const String LINE_INFO_INPUT_NAME = "lineInfo";
|
| +
|
| + /**
|
| + * The name of the input whose value is the AST for the compilation unit.
|
| + */
|
| + static const String PARSED_UNIT_INPUT_NAME = "parsedUnit";
|
| +
|
| + /**
|
| + * The task descriptor describing this kind of task.
|
| + */
|
| + static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
|
| + 'BUILD_COMPILATION_UNIT_ELEMENT',
|
| + createTask,
|
| + buildInputs,
|
| + <ResultDescriptor>[COMPILATION_UNIT_ELEMENT, BUILT_UNIT]);
|
| +
|
| + /**
|
| + * Initialize a newly created task to build a compilation unit element for
|
| + * the given [target] in the given [context].
|
| + */
|
| + BuildCompilationUnitElementTask(InternalAnalysisContext context,
|
| + AnalysisTarget target)
|
| + : super(context, target);
|
| +
|
| + @override
|
| + TaskDescriptor get descriptor => DESCRIPTOR;
|
| +
|
| + @override
|
| + void internalPerform() {
|
| + Source source = getRequiredSource();
|
| + CompilationUnit unit = getRequiredInput(PARSED_UNIT_INPUT_NAME);
|
| +
|
| + CompilationUnitBuilder builder = new CompilationUnitBuilder();
|
| + CompilationUnitElement element = builder.buildCompilationUnit(source, unit);
|
| +
|
| + outputs[COMPILATION_UNIT_ELEMENT] = element;
|
| + outputs[BUILT_UNIT] = unit;
|
| + }
|
| +
|
| + /**
|
| + * Return a map from the names of the inputs of this kind of task to the task
|
| + * input descriptors describing those inputs for a task with the given [target].
|
| + */
|
| + static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
|
| + return <String, TaskInput>{
|
| + PARSED_UNIT_INPUT_NAME: PARSED_UNIT.inputFor(target)
|
| + };
|
| + }
|
| +
|
| + /**
|
| + * Create a [BuildCompilationUnitElementTask] based on the given [target] in
|
| + * the given [context].
|
| + */
|
| + static BuildCompilationUnitElementTask createTask(AnalysisContext context,
|
| + AnalysisTarget target) {
|
| + return new BuildCompilationUnitElementTask(context, target);
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * A task that parses the content of a Dart file, producing an AST structure.
|
| + */
|
| +class ParseDartTask extends SourceBasedAnalysisTask {
|
| + /**
|
| + * The name of the input whose value is the line information produced for the
|
| + * file.
|
| + */
|
| + static const String LINE_INFO_INPUT_NAME = "lineInfo";
|
| +
|
| + /**
|
| + * The name of the input whose value is the token stream produced for the file.
|
| + */
|
| + static const String TOKEN_STREAM_INPUT_NAME = "tokenStream";
|
| +
|
| + /**
|
| + * The task descriptor describing this kind of task.
|
| + */
|
| + static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
|
| + 'PARSE_DART',
|
| + createTask,
|
| + buildInputs,
|
| + <ResultDescriptor>[
|
| + EXPORTED_LIBRARIES,
|
| + IMPORTED_LIBRARIES,
|
| + INCLUDED_PARTS,
|
| + PARSE_ERRORS,
|
| + PARSED_UNIT,
|
| + SOURCE_KIND]);
|
| +
|
| + /**
|
| + * Initialize a newly created task to parse the content of the Dart file
|
| + * associated with the given [target] in the given [context].
|
| + */
|
| + ParseDartTask(InternalAnalysisContext context, AnalysisTarget target)
|
| + : super(context, target);
|
| +
|
| + @override
|
| + TaskDescriptor get descriptor => DESCRIPTOR;
|
| +
|
| + @override
|
| + void internalPerform() {
|
| + Source source = getRequiredSource();
|
| + LineInfo lineInfo = getRequiredInput(LINE_INFO_INPUT_NAME);
|
| + Token tokenStream = getRequiredInput(TOKEN_STREAM_INPUT_NAME);
|
| +
|
| + RecordingErrorListener errorListener = new RecordingErrorListener();
|
| + Parser parser = new Parser(source, errorListener);
|
| + AnalysisOptions options = context.analysisOptions;
|
| + parser.parseFunctionBodies = options.analyzeFunctionBodies;
|
| + CompilationUnit unit = parser.parseCompilationUnit(tokenStream);
|
| + unit.lineInfo = lineInfo;
|
| +
|
| + bool hasNonPartOfDirective = false;
|
| + bool hasPartOfDirective = false;
|
| + HashSet<Source> exportedSources = new HashSet<Source>();
|
| + HashSet<Source> importedSources = new HashSet<Source>();
|
| + HashSet<Source> includedSources = new HashSet<Source>();
|
| + for (Directive directive in unit.directives) {
|
| + if (directive is PartOfDirective) {
|
| + hasPartOfDirective = true;
|
| + } else {
|
| + hasNonPartOfDirective = true;
|
| + if (directive is UriBasedDirective) {
|
| + Source referencedSource =
|
| + resolveDirective(context, source, directive, errorListener);
|
| + if (referencedSource != null) {
|
| + if (directive is ExportDirective) {
|
| + exportedSources.add(referencedSource);
|
| + } else if (directive is ImportDirective) {
|
| + importedSources.add(referencedSource);
|
| + } else if (directive is PartDirective) {
|
| + if (referencedSource != source) {
|
| + includedSources.add(referencedSource);
|
| + }
|
| + } else {
|
| + throw new AnalysisException(
|
| + "$runtimeType failed to handle a ${directive.runtimeType}");
|
| + }
|
| + }
|
| + }
|
| + }
|
| + }
|
| + SourceKind sourceKind = SourceKind.LIBRARY;
|
| + if (!hasNonPartOfDirective && hasPartOfDirective) {
|
| + sourceKind = SourceKind.PART;
|
| + }
|
| +
|
| + outputs[EXPORTED_LIBRARIES] = exportedSources.toList();
|
| + outputs[IMPORTED_LIBRARIES] = importedSources.toList();
|
| + outputs[INCLUDED_PARTS] = includedSources.toList();
|
| + outputs[PARSE_ERRORS] = errorListener.getErrorsForSource(source);
|
| + outputs[PARSED_UNIT] = unit;
|
| + outputs[SOURCE_KIND] = sourceKind;
|
| + }
|
| +
|
| + /**
|
| + * Return a map from the names of the inputs of this kind of task to the task
|
| + * input descriptors describing those inputs for a task with the given [target].
|
| + */
|
| + static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
|
| + return <String, TaskInput>{
|
| + LINE_INFO_INPUT_NAME: LINE_INFO.inputFor(target),
|
| + TOKEN_STREAM_INPUT_NAME: TOKEN_STREAM.inputFor(target)
|
| + };
|
| + }
|
| +
|
| + /**
|
| + * Create a [ParseDartTask] based on the given [target] in the given
|
| + * [context].
|
| + */
|
| + static ParseDartTask createTask(AnalysisContext context,
|
| + AnalysisTarget target) {
|
| + return new ParseDartTask(context, target);
|
| + }
|
| +
|
| + /**
|
| + * Return the result of resolving the URI of the given URI-based [directive]
|
| + * against the URI of the given library, or `null` if the URI is not valid.
|
| + *
|
| + * Resolution is to be performed in the given [context]. Errors should be
|
| + * reported to the [errorListener].
|
| + */
|
| + static Source resolveDirective(AnalysisContext context, Source librarySource,
|
| + UriBasedDirective directive, AnalysisErrorListener errorListener) {
|
| + StringLiteral uriLiteral = directive.uri;
|
| + String uriContent = uriLiteral.stringValue;
|
| + if (uriContent != null) {
|
| + uriContent = uriContent.trim();
|
| + directive.uriContent = uriContent;
|
| + }
|
| + UriValidationCode code = directive.validate();
|
| + if (code == null) {
|
| + String encodedUriContent = Uri.encodeFull(uriContent);
|
| + Source source =
|
| + context.sourceFactory.resolveUri(librarySource, encodedUriContent);
|
| + directive.source = source;
|
| + return source;
|
| + }
|
| + if (code == UriValidationCode.URI_WITH_DART_EXT_SCHEME) {
|
| + return null;
|
| + }
|
| + if (code == UriValidationCode.URI_WITH_INTERPOLATION) {
|
| + errorListener.onError(
|
| + new AnalysisError.con2(
|
| + librarySource,
|
| + uriLiteral.offset,
|
| + uriLiteral.length,
|
| + CompileTimeErrorCode.URI_WITH_INTERPOLATION));
|
| + return null;
|
| + }
|
| + if (code == UriValidationCode.INVALID_URI) {
|
| + errorListener.onError(
|
| + new AnalysisError.con2(
|
| + librarySource,
|
| + uriLiteral.offset,
|
| + uriLiteral.length,
|
| + CompileTimeErrorCode.INVALID_URI,
|
| + [uriContent]));
|
| + return null;
|
| + }
|
| + throw new AnalysisException('Failed to handle validation code: $code');
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * A task that scans the content of a file, producing a set of Dart tokens.
|
| + */
|
| +class ScanDartTask extends SourceBasedAnalysisTask {
|
| + /**
|
| + * The name of the input whose value is the content of the file.
|
| + */
|
| + static const String CONTENT_INPUT_NAME = "content";
|
| +
|
| + /**
|
| + * The task descriptor describing this kind of task.
|
| + */
|
| + static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
|
| + 'SCAN_DART',
|
| + createTask,
|
| + buildInputs,
|
| + <ResultDescriptor>[LINE_INFO, SCAN_ERRORS, TOKEN_STREAM]);
|
| +
|
| + /**
|
| + * Initialize a newly created task to access the content of the source
|
| + * associated with the given [target] in the given [context].
|
| + */
|
| + ScanDartTask(InternalAnalysisContext context, AnalysisTarget target)
|
| + : super(context, target);
|
| +
|
| + @override
|
| + TaskDescriptor get descriptor => DESCRIPTOR;
|
| +
|
| + @override
|
| + void internalPerform() {
|
| + Source source = getRequiredSource();
|
| + String content = getRequiredInput(CONTENT_INPUT_NAME);
|
| +
|
| + RecordingErrorListener errorListener = new RecordingErrorListener();
|
| + Scanner scanner =
|
| + new Scanner(source, new CharSequenceReader(content), errorListener);
|
| + scanner.preserveComments = context.analysisOptions.preserveComments;
|
| + outputs[TOKEN_STREAM] = scanner.tokenize();
|
| + outputs[LINE_INFO] = new LineInfo(scanner.lineStarts);
|
| + outputs[SCAN_ERRORS] = errorListener.getErrorsForSource(source);
|
| + }
|
| +
|
| + /**
|
| + * Return a map from the names of the inputs of this kind of task to the task
|
| + * input descriptors describing those inputs for a task with the given [target].
|
| + */
|
| + static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
|
| + return <String, TaskInput>{
|
| + CONTENT_INPUT_NAME: CONTENT.inputFor(target)
|
| + };
|
| + }
|
| +
|
| + /**
|
| + * Create a [ScanDartTask] based on the given [target] in the given [context].
|
| + */
|
| + static ScanDartTask createTask(AnalysisContext context,
|
| + AnalysisTarget target) {
|
| + return new ScanDartTask(context, target);
|
| + }
|
| +}
|
|
|