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

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

Issue 994293002: Task: Build Library Element Model (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Updates for review comments. Created 5 years, 9 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 | « pkg/analyzer/lib/src/generated/element.dart ('k') | 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
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 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 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library analyzer.src.task.dart; 5 library analyzer.src.task.dart;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 8
9 import 'package:analyzer/src/generated/ast.dart'; 9 import 'package:analyzer/src/generated/ast.dart';
10 import 'package:analyzer/src/generated/element.dart'; 10 import 'package:analyzer/src/generated/element.dart';
11 import 'package:analyzer/src/generated/engine.dart' hide AnalysisTask; 11 import 'package:analyzer/src/generated/engine.dart' hide AnalysisTask;
12 import 'package:analyzer/src/generated/error.dart'; 12 import 'package:analyzer/src/generated/error.dart';
13 import 'package:analyzer/src/generated/java_engine.dart'; 13 import 'package:analyzer/src/generated/java_engine.dart';
14 import 'package:analyzer/src/generated/parser.dart'; 14 import 'package:analyzer/src/generated/parser.dart';
15 import 'package:analyzer/src/generated/resolver.dart'; 15 import 'package:analyzer/src/generated/resolver.dart';
16 import 'package:analyzer/src/generated/scanner.dart'; 16 import 'package:analyzer/src/generated/scanner.dart';
17 import 'package:analyzer/src/generated/sdk.dart';
17 import 'package:analyzer/src/generated/source.dart'; 18 import 'package:analyzer/src/generated/source.dart';
18 import 'package:analyzer/src/task/general.dart'; 19 import 'package:analyzer/src/task/general.dart';
20 import 'package:analyzer/src/task/inputs.dart';
19 import 'package:analyzer/task/dart.dart'; 21 import 'package:analyzer/task/dart.dart';
20 import 'package:analyzer/task/general.dart'; 22 import 'package:analyzer/task/general.dart';
21 import 'package:analyzer/task/model.dart'; 23 import 'package:analyzer/task/model.dart';
22 24
23 /** 25 /**
24 * A task that builds a compilation unit element for a single compilation unit. 26 * A task that builds a compilation unit element for a single compilation unit.
25 */ 27 */
26 class BuildCompilationUnitElementTask extends SourceBasedAnalysisTask { 28 class BuildCompilationUnitElementTask extends SourceBasedAnalysisTask {
27 /** 29 /**
28 * The name of the input whose value is the line information for the 30 * The name of the input whose value is the line information for the
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 * Create a [BuildCompilationUnitElementTask] based on the given [target] in 81 * Create a [BuildCompilationUnitElementTask] based on the given [target] in
80 * the given [context]. 82 * the given [context].
81 */ 83 */
82 static BuildCompilationUnitElementTask createTask( 84 static BuildCompilationUnitElementTask createTask(
83 AnalysisContext context, AnalysisTarget target) { 85 AnalysisContext context, AnalysisTarget target) {
84 return new BuildCompilationUnitElementTask(context, target); 86 return new BuildCompilationUnitElementTask(context, target);
85 } 87 }
86 } 88 }
87 89
88 /** 90 /**
91 * A task that builds a library element for a Dart library.
92 */
93 class BuildLibraryElementTask extends SourceBasedAnalysisTask {
94 /**
95 * The name of the input whose value is the built compilation unit of the
96 * defining compilation unit of a library.
97 */
98 static const String DEFINING_BUILT_UNIT_INPUT_NAME = 'definingBuiltUnit';
99
100 /**
101 * The name of the input whose value is a list of built compilation units
102 * of the parts sourced by a library.
103 */
104 static const String PART_BUILT_UNITS_INPUT_NAME = 'partBuiltUnits';
105
106 /**
107 * The name of the function used as an entry point.
108 */
109 static const String ENTRY_POINT_NAME = "main";
110
111 /**
112 * The task descriptor describing this kind of task.
113 */
114 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
115 'BUILD_LIBRARY_ELEMENT', createTask, buildInputs, <ResultDescriptor>[
116 BUILD_LIBRARY_ERRORS,
117 BUILT_LIBRARY_ELEMENT,
118 IS_LAUNCHABLE,
119 HAS_HTML_IMPORT
120 ]);
121
122 /**
123 * Initialize a newly created task to build a library element for the given
124 * [target] in the given [context].
125 */
126 BuildLibraryElementTask(
127 InternalAnalysisContext context, AnalysisTarget target)
128 : super(context, target);
129
130 @override
131 TaskDescriptor get descriptor => DESCRIPTOR;
132
133 @override
134 void internalPerform() {
135 List<AnalysisError> errors = <AnalysisError>[];
136 //
137 // Prepare inputs.
138 //
139 Source librarySource = getRequiredSource();
140 CompilationUnit definingCompilationUnit =
141 getRequiredInput(DEFINING_BUILT_UNIT_INPUT_NAME);
142 List<CompilationUnit> partUnits =
143 getRequiredInput(PART_BUILT_UNITS_INPUT_NAME);
144 //
145 // Process inputs.
146 //
147 CompilationUnitElementImpl definingCompilationUnitElement =
148 definingCompilationUnit.element;
149 Map<Source, CompilationUnit> partUnitMap =
150 new HashMap<Source, CompilationUnit>();
151 for (CompilationUnit partUnit in partUnits) {
152 Source partSource = partUnit.element.source;
153 partUnitMap[partSource] = partUnit;
154 }
155 Source htmlSource = context.sourceFactory.forUri(DartSdk.DART_HTML);
156 //
157 // Update "part" directives.
158 //
159 LibraryIdentifier libraryNameNode = null;
160 bool hasHtmlImport = false;
161 bool hasPartDirective = false;
162 FunctionElement entryPoint =
163 _findEntryPoint(definingCompilationUnitElement);
164 List<Directive> directivesToResolve = <Directive>[];
165 List<CompilationUnitElementImpl> sourcedCompilationUnits =
166 <CompilationUnitElementImpl>[];
167 for (Directive directive in definingCompilationUnit.directives) {
168 if (directive is ImportDirective) {
169 hasHtmlImport = hasHtmlImport || directive.source == htmlSource;
170 } else if (directive is LibraryDirective) {
171 if (libraryNameNode == null) {
172 libraryNameNode = directive.name;
173 directivesToResolve.add(directive);
174 }
175 } else if (directive is PartDirective) {
176 PartDirective partDirective = directive;
177 StringLiteral partUri = partDirective.uri;
178 Source partSource = partDirective.source;
179 if (context.exists(partSource)) {
180 hasPartDirective = true;
181 CompilationUnit partUnit = partUnitMap[partSource];
182 CompilationUnitElementImpl partElement = partUnit.element;
183 partElement.uriOffset = partUri.offset;
184 partElement.uriEnd = partUri.end;
185 partElement.uri = partDirective.uriContent;
186 //
187 // Validate that the part contains a part-of directive with the same
188 // name as the library.
189 //
190 String partLibraryName =
191 _getPartLibraryName(partSource, partUnit, directivesToResolve);
192 if (partLibraryName == null) {
193 errors.add(new AnalysisError.con2(librarySource, partUri.offset,
194 partUri.length, CompileTimeErrorCode.PART_OF_NON_PART, [
195 partUri.toSource()
196 ]));
197 } else if (libraryNameNode == null) {
198 // TODO(brianwilkerson) Collect the names declared by the part.
199 // If they are all the same then we can use that name as the
200 // inferred name of the library and present it in a quick-fix.
201 // partLibraryNames.add(partLibraryName);
202 } else if (libraryNameNode.name != partLibraryName) {
203 errors.add(new AnalysisError.con2(librarySource, partUri.offset,
204 partUri.length, StaticWarningCode.PART_OF_DIFFERENT_LIBRARY, [
205 libraryNameNode.name,
206 partLibraryName
207 ]));
208 }
209 if (entryPoint == null) {
210 entryPoint = _findEntryPoint(partElement);
211 }
212 directive.element = partElement;
213 sourcedCompilationUnits.add(partElement);
214 }
215 }
216 }
217 if (hasPartDirective && libraryNameNode == null) {
218 errors.add(new AnalysisError.con1(librarySource,
219 ResolverErrorCode.MISSING_LIBRARY_DIRECTIVE_WITH_PART));
220 }
221 //
222 // Create and populate the library element.
223 //
224 LibraryElementImpl libraryElement =
225 new LibraryElementImpl.forNode(context, libraryNameNode);
226 libraryElement.definingCompilationUnit = definingCompilationUnitElement;
227 libraryElement.entryPoint = entryPoint;
228 libraryElement.parts = sourcedCompilationUnits;
229 for (Directive directive in directivesToResolve) {
230 directive.element = libraryElement;
231 }
232 if (sourcedCompilationUnits.isNotEmpty) {
233 _patchTopLevelAccessors(libraryElement);
234 }
235 //
236 // Record outputs.
237 //
238 outputs[BUILD_LIBRARY_ERRORS] = errors;
239 outputs[BUILT_LIBRARY_ELEMENT] = libraryElement;
240 outputs[IS_LAUNCHABLE] = entryPoint != null;
241 outputs[HAS_HTML_IMPORT] = hasHtmlImport;
242 }
243
244 /**
245 * Add all of the non-synthetic [getters] and [setters] defined in the given
246 * [unit] that have no corresponding accessor to one of the given collections.
247 */
248 void _collectAccessors(Map<String, PropertyAccessorElement> getters,
249 List<PropertyAccessorElement> setters, CompilationUnitElement unit) {
250 for (PropertyAccessorElement accessor in unit.accessors) {
251 if (accessor.isGetter) {
252 if (!accessor.isSynthetic && accessor.correspondingSetter == null) {
253 getters[accessor.displayName] = accessor;
254 }
255 } else {
256 if (!accessor.isSynthetic && accessor.correspondingGetter == null) {
257 setters.add(accessor);
258 }
259 }
260 }
261 }
262
263 /**
264 * Return the top-level [FunctionElement] entry point, or `null` if the given
265 * [element] does not define an entry point.
266 */
267 FunctionElement _findEntryPoint(CompilationUnitElementImpl element) {
268 for (FunctionElement function in element.functions) {
269 if (function.name == ENTRY_POINT_NAME) {
270 return function;
271 }
272 }
273 return null;
274 }
275
276 /**
277 * Return the name of the library that the given part is declared to be a
278 * part of, or `null` if the part does not contain a part-of directive.
279 */
280 String _getPartLibraryName(Source partSource, CompilationUnit partUnit,
281 List<Directive> directivesToResolve) {
282 for (Directive directive in partUnit.directives) {
283 if (directive is PartOfDirective) {
284 directivesToResolve.add(directive);
285 LibraryIdentifier libraryName = directive.libraryName;
286 if (libraryName != null) {
287 return libraryName.name;
288 }
289 }
290 }
291 return null;
292 }
293
294 /**
295 * Look through all of the compilation units defined for the given [library],
296 * looking for getters and setters that are defined in different compilation
297 * units but that have the same names. If any are found, make sure that they
298 * have the same variable element.
299 */
300 void _patchTopLevelAccessors(LibraryElementImpl library) {
301 HashMap<String, PropertyAccessorElement> getters =
302 new HashMap<String, PropertyAccessorElement>();
303 List<PropertyAccessorElement> setters = <PropertyAccessorElement>[];
304 _collectAccessors(getters, setters, library.definingCompilationUnit);
305 for (CompilationUnitElement unit in library.parts) {
306 _collectAccessors(getters, setters, unit);
307 }
308 for (PropertyAccessorElementImpl setter in setters) {
309 PropertyAccessorElement getter = getters[setter.displayName];
310 if (getter != null) {
311 TopLevelVariableElementImpl variable = getter.variable;
312 TopLevelVariableElementImpl setterVariable = setter.variable;
313 CompilationUnitElementImpl setterUnit = setterVariable.enclosingElement;
314 setterUnit.replaceTopLevelVariable(setterVariable, variable);
315 variable.setter = setter;
316 setter.variable = variable;
317 }
318 }
319 }
320
321 /**
322 * Return a map from the names of the inputs of this kind of task to the task
323 * input descriptors describing those inputs for a task with the given
324 * [target].
325 */
326 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
327 return <String, TaskInput>{
328 DEFINING_BUILT_UNIT_INPUT_NAME: new SimpleTaskInput(target, BUILT_UNIT),
329 PART_BUILT_UNITS_INPUT_NAME:
330 new ListBasedTaskInput<List<Source>, CompilationUnit>(
331 new SimpleTaskInput<List<Source>>(target, INCLUDED_PARTS),
332 (Source includedSource) => new SimpleTaskInput<CompilationUnit>(
333 includedSource, BUILT_UNIT))
334 };
335 }
336
337 /**
338 * Create a [BuildLibraryElementTask] based on the given [target] in the
339 * given [context].
340 */
341 static BuildLibraryElementTask createTask(
342 AnalysisContext context, AnalysisTarget target) {
343 return new BuildLibraryElementTask(context, target);
344 }
345 }
346
347 /**
89 * A task that parses the content of a Dart file, producing an AST structure. 348 * A task that parses the content of a Dart file, producing an AST structure.
90 */ 349 */
91 class ParseDartTask extends SourceBasedAnalysisTask { 350 class ParseDartTask extends SourceBasedAnalysisTask {
92 /** 351 /**
93 * The name of the input whose value is the line information produced for the 352 * The name of the input whose value is the line information produced for the
94 * file. 353 * file.
95 */ 354 */
96 static const String LINE_INFO_INPUT_NAME = "lineInfo"; 355 static const String LINE_INFO_INPUT_NAME = "lineInfo";
97 356
98 /** 357 /**
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
293 } 552 }
294 553
295 /** 554 /**
296 * Create a [ScanDartTask] based on the given [target] in the given [context]. 555 * Create a [ScanDartTask] based on the given [target] in the given [context].
297 */ 556 */
298 static ScanDartTask createTask( 557 static ScanDartTask createTask(
299 AnalysisContext context, AnalysisTarget target) { 558 AnalysisContext context, AnalysisTarget target) {
300 return new ScanDartTask(context, target); 559 return new ScanDartTask(context, target);
301 } 560 }
302 } 561 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/generated/element.dart ('k') | pkg/analyzer/lib/src/task/general.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698