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

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

Powered by Google App Engine
This is Rietveld 408576698