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

Side by Side Diff: pkg/analyzer/lib/src/task/dart.dart

Issue 887433002: Add simple Dart tasks (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Add base class and general implementation of description Created 5 years, 10 months 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
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/task/general.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 analyzer.src.task.dart;
6
7 import 'dart:collection';
8
9 import 'package:analyzer/src/generated/ast.dart';
10 import 'package:analyzer/src/generated/element.dart';
11 import 'package:analyzer/src/generated/engine.dart' hide AnalysisTask;
12 import 'package:analyzer/src/generated/error.dart';
13 import 'package:analyzer/src/generated/java_engine.dart';
14 import 'package:analyzer/src/generated/parser.dart';
15 import 'package:analyzer/src/generated/resolver.dart';
16 import 'package:analyzer/src/generated/scanner.dart';
17 import 'package:analyzer/src/generated/source.dart';
18 import 'package:analyzer/src/task/general.dart';
19 import 'package:analyzer/task/dart.dart';
20 import 'package:analyzer/task/general.dart';
21 import 'package:analyzer/task/model.dart';
22
23 /**
24 * A task that builds a compilation unit element for a single compilation unit.
25 */
26 class BuildCompilationUnitElementTask extends SourceBasedAnalysisTask {
27 /**
28 * The name of the input whose value is the line information for the
29 * compilation unit.
30 */
31 static const String LINE_INFO_INPUT_NAME = "lineInfo";
32
33 /**
34 * The name of the input whose value is the AST for the compilation unit.
35 */
36 static const String PARSED_UNIT_INPUT_NAME = "parsedUnit";
37
38 /**
39 * The task descriptor describing this kind of task.
40 */
41 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
42 'BUILD_COMPILATION_UNIT_ELEMENT',
43 createTask,
44 buildInputs,
45 <ResultDescriptor>[COMPILATION_UNIT_ELEMENT, BUILT_UNIT]);
46
47 /**
48 * Initialize a newly created task to build a compilation unit element for
49 * the given [target] in the given [context].
50 */
51 BuildCompilationUnitElementTask(InternalAnalysisContext context,
52 AnalysisTarget target)
53 : super(context, target);
54
55 @override
56 TaskDescriptor get descriptor => DESCRIPTOR;
57
58 @override
59 void internalPerform() {
60 Source source = getRequiredSource();
61 CompilationUnit unit = getRequiredInput(PARSED_UNIT_INPUT_NAME);
62
63 CompilationUnitBuilder builder = new CompilationUnitBuilder();
64 CompilationUnitElement element = builder.buildCompilationUnit(source, unit);
65
66 outputs[COMPILATION_UNIT_ELEMENT] = element;
67 outputs[BUILT_UNIT] = unit;
68 }
69
70 /**
71 * Return a map from the names of the inputs of this kind of task to the task
72 * input descriptors describing those inputs for a task with the given [target ].
73 */
74 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
75 return <String, TaskInput>{
76 PARSED_UNIT_INPUT_NAME: PARSED_UNIT.inputFor(target)
77 };
78 }
79
80 /**
81 * Create a [BuildCompilationUnitElementTask] based on the given [target] in
82 * the given [context].
83 */
84 static BuildCompilationUnitElementTask createTask(AnalysisContext context,
85 AnalysisTarget target) {
86 return new BuildCompilationUnitElementTask(context, target);
87 }
88 }
89
90 /**
91 * A task that parses the content of a Dart file, producing an AST structure.
92 */
93 class ParseDartTask extends SourceBasedAnalysisTask {
94 /**
95 * The name of the input whose value is the line information produced for the
96 * file.
97 */
98 static const String LINE_INFO_INPUT_NAME = "lineInfo";
99
100 /**
101 * The name of the input whose value is the token stream produced for the file .
102 */
103 static const String TOKEN_STREAM_INPUT_NAME = "tokenStream";
104
105 /**
106 * The task descriptor describing this kind of task.
107 */
108 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
109 'PARSE_DART',
110 createTask,
111 buildInputs,
112 <ResultDescriptor>[
113 EXPORTED_LIBRARIES,
114 IMPORTED_LIBRARIES,
115 INCLUDED_PARTS,
116 PARSE_ERRORS,
117 PARSED_UNIT,
118 SOURCE_KIND]);
119
120 /**
121 * Initialize a newly created task to parse the content of the Dart file
122 * associated with the given [target] in the given [context].
123 */
124 ParseDartTask(InternalAnalysisContext context, AnalysisTarget target)
125 : super(context, target);
126
127 @override
128 TaskDescriptor get descriptor => DESCRIPTOR;
129
130 @override
131 void internalPerform() {
132 Source source = getRequiredSource();
133 LineInfo lineInfo = getRequiredInput(LINE_INFO_INPUT_NAME);
134 Token tokenStream = getRequiredInput(TOKEN_STREAM_INPUT_NAME);
135
136 RecordingErrorListener errorListener = new RecordingErrorListener();
137 Parser parser = new Parser(source, errorListener);
138 AnalysisOptions options = context.analysisOptions;
139 parser.parseFunctionBodies = options.analyzeFunctionBodies;
140 CompilationUnit unit = parser.parseCompilationUnit(tokenStream);
141 unit.lineInfo = lineInfo;
142
143 bool hasNonPartOfDirective = false;
144 bool hasPartOfDirective = false;
145 HashSet<Source> exportedSources = new HashSet<Source>();
146 HashSet<Source> importedSources = new HashSet<Source>();
147 HashSet<Source> includedSources = new HashSet<Source>();
148 for (Directive directive in unit.directives) {
149 if (directive is PartOfDirective) {
150 hasPartOfDirective = true;
151 } else {
152 hasNonPartOfDirective = true;
153 if (directive is UriBasedDirective) {
154 Source referencedSource =
155 resolveDirective(context, source, directive, errorListener);
156 if (referencedSource != null) {
157 if (directive is ExportDirective) {
158 exportedSources.add(referencedSource);
159 } else if (directive is ImportDirective) {
160 importedSources.add(referencedSource);
161 } else if (directive is PartDirective) {
162 if (referencedSource != source) {
163 includedSources.add(referencedSource);
164 }
165 } else {
166 throw new AnalysisException(
167 "$runtimeType failed to handle a ${directive.runtimeType}");
168 }
169 }
170 }
171 }
172 }
173 SourceKind sourceKind = SourceKind.LIBRARY;
174 if (!hasNonPartOfDirective && hasPartOfDirective) {
175 sourceKind = SourceKind.PART;
176 }
177
178 outputs[EXPORTED_LIBRARIES] = exportedSources.toList();
179 outputs[IMPORTED_LIBRARIES] = importedSources.toList();
180 outputs[INCLUDED_PARTS] = includedSources.toList();
181 outputs[PARSE_ERRORS] = errorListener.getErrorsForSource(source);
182 outputs[PARSED_UNIT] = unit;
183 outputs[SOURCE_KIND] = sourceKind;
184 }
185
186 /**
187 * Return a map from the names of the inputs of this kind of task to the task
188 * input descriptors describing those inputs for a task with the given [target ].
189 */
190 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
191 return <String, TaskInput>{
192 LINE_INFO_INPUT_NAME: LINE_INFO.inputFor(target),
193 TOKEN_STREAM_INPUT_NAME: TOKEN_STREAM.inputFor(target)
194 };
195 }
196
197 /**
198 * Create a [ParseDartTask] based on the given [target] in the given
199 * [context].
200 */
201 static ParseDartTask createTask(AnalysisContext context,
202 AnalysisTarget target) {
203 return new ParseDartTask(context, target);
204 }
205
206 /**
207 * Return the result of resolving the URI of the given URI-based [directive]
208 * against the URI of the given library, or `null` if the URI is not valid.
209 *
210 * Resolution is to be performed in the given [context]. Errors should be
211 * reported to the [errorListener].
212 */
213 static Source resolveDirective(AnalysisContext context, Source librarySource,
214 UriBasedDirective directive, AnalysisErrorListener errorListener) {
215 StringLiteral uriLiteral = directive.uri;
216 String uriContent = uriLiteral.stringValue;
217 if (uriContent != null) {
218 uriContent = uriContent.trim();
219 directive.uriContent = uriContent;
220 }
221 UriValidationCode code = directive.validate();
222 if (code == null) {
223 String encodedUriContent = Uri.encodeFull(uriContent);
224 Source source =
225 context.sourceFactory.resolveUri(librarySource, encodedUriContent);
226 directive.source = source;
227 return source;
228 }
229 if (code == UriValidationCode.URI_WITH_DART_EXT_SCHEME) {
230 return null;
231 }
232 if (code == UriValidationCode.URI_WITH_INTERPOLATION) {
233 errorListener.onError(
234 new AnalysisError.con2(
235 librarySource,
236 uriLiteral.offset,
237 uriLiteral.length,
238 CompileTimeErrorCode.URI_WITH_INTERPOLATION));
239 return null;
240 }
241 if (code == UriValidationCode.INVALID_URI) {
242 errorListener.onError(
243 new AnalysisError.con2(
244 librarySource,
245 uriLiteral.offset,
246 uriLiteral.length,
247 CompileTimeErrorCode.INVALID_URI,
248 [uriContent]));
249 return null;
250 }
251 throw new AnalysisException('Failed to handle validation code: $code');
252 }
253 }
254
255 /**
256 * A task that scans the content of a file, producing a set of Dart tokens.
257 */
258 class ScanDartTask extends SourceBasedAnalysisTask {
259 /**
260 * The name of the input whose value is the content of the file.
261 */
262 static const String CONTENT_INPUT_NAME = "content";
263
264 /**
265 * The task descriptor describing this kind of task.
266 */
267 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
268 'SCAN_DART',
269 createTask,
270 buildInputs,
271 <ResultDescriptor>[LINE_INFO, SCAN_ERRORS, TOKEN_STREAM]);
272
273 /**
274 * Initialize a newly created task to access the content of the source
275 * associated with the given [target] in the given [context].
276 */
277 ScanDartTask(InternalAnalysisContext context, AnalysisTarget target)
278 : super(context, target);
279
280 @override
281 TaskDescriptor get descriptor => DESCRIPTOR;
282
283 @override
284 void internalPerform() {
285 Source source = getRequiredSource();
286 String content = getRequiredInput(CONTENT_INPUT_NAME);
287
288 RecordingErrorListener errorListener = new RecordingErrorListener();
289 Scanner scanner =
290 new Scanner(source, new CharSequenceReader(content), errorListener);
291 scanner.preserveComments = context.analysisOptions.preserveComments;
292 outputs[TOKEN_STREAM] = scanner.tokenize();
293 outputs[LINE_INFO] = new LineInfo(scanner.lineStarts);
294 outputs[SCAN_ERRORS] = errorListener.getErrorsForSource(source);
295 }
296
297 /**
298 * Return a map from the names of the inputs of this kind of task to the task
299 * input descriptors describing those inputs for a task with the given [target ].
300 */
301 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
302 return <String, TaskInput>{
303 CONTENT_INPUT_NAME: CONTENT.inputFor(target)
304 };
305 }
306
307 /**
308 * Create a [ScanDartTask] based on the given [target] in the given [context].
309 */
310 static ScanDartTask createTask(AnalysisContext context,
311 AnalysisTarget target) {
312 return new ScanDartTask(context, target);
313 }
314 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/task/general.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698