Chromium Code Reviews| Index: pkg/analyzer/lib/src/dart/element/element.dart |
| diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart |
| index ddcad2b56b95a91ea758a0ac9d5815a293f76a9c..e3306e997ccfdae97f548ae180b12e414c976583 100644 |
| --- a/pkg/analyzer/lib/src/dart/element/element.dart |
| +++ b/pkg/analyzer/lib/src/dart/element/element.dart |
| @@ -1085,7 +1085,7 @@ class CompilationUnitElementImpl extends UriReferencedElementImpl |
| * A list containing all of the top-level accessors (getters and setters) |
| * contained in this compilation unit. |
| */ |
| - List<PropertyAccessorElement> _accessors = PropertyAccessorElement.EMPTY_LIST; |
| + List<PropertyAccessorElement> _accessors; |
| /** |
| * A list containing all of the enums contained in this compilation unit. |
| @@ -1113,7 +1113,7 @@ class CompilationUnitElementImpl extends UriReferencedElementImpl |
| /** |
| * A list containing all of the variables contained in this compilation unit. |
| */ |
| - List<TopLevelVariableElement> _variables = TopLevelVariableElement.EMPTY_LIST; |
| + List<TopLevelVariableElement> _variables; |
| /** |
| * A map from offsets to elements of this unit at these offsets. |
| @@ -1121,6 +1121,24 @@ class CompilationUnitElementImpl extends UriReferencedElementImpl |
| final Map<int, Element> _offsetToElementMap = new HashMap<int, Element>(); |
| /** |
| + * Resynthesized explicit top-level property accessors. |
| + */ |
| + UnitExplicitTopLevelAccessors _explicitTopLevelAccessors; |
| + |
| + /** |
| + * Resynthesized explicit top-level variables. |
| + */ |
| + UnitExplicitTopLevelVariables _explicitTopLevelVariables; |
| + |
| + /** |
| + * Description of top-level variable replacements that should be applied |
| + * to implicit top-level variables because of re-linking top-level property |
| + * accessors between different unit of the same library. |
| + */ |
| + Map<TopLevelVariableElement, TopLevelVariableElement> |
| + _topLevelVariableReplaceMap; |
| + |
| + /** |
| * Initialize a newly created compilation unit element to have the given |
| * [name]. |
| */ |
| @@ -1146,7 +1164,30 @@ class CompilationUnitElementImpl extends UriReferencedElementImpl |
| } |
| @override |
| - List<PropertyAccessorElement> get accessors => _accessors; |
| + List<PropertyAccessorElement> get accessors { |
| + if (_unlinkedUnit != null) { |
| + if (_accessors == null) { |
| + _explicitTopLevelAccessors ??= |
| + resynthesizerContext.buildTopLevelAccessors(); |
| + _explicitTopLevelVariables ??= |
| + resynthesizerContext.buildTopLevelVariables(); |
| + List<PropertyAccessorElementImpl> accessors = |
| + <PropertyAccessorElementImpl>[]; |
| + accessors.addAll(_explicitTopLevelAccessors.accessors); |
| + for (TopLevelVariableElementImpl implicitVariable |
| + in _explicitTopLevelAccessors.implicitVariables) { |
| + implicitVariable.enclosingElement = this; |
| + } |
| + for (PropertyAccessorElementImpl implicitAccessors |
| + in _explicitTopLevelVariables.implicitAccessors) { |
| + implicitAccessors.enclosingElement = this; |
| + accessors.add(implicitAccessors); |
| + } |
| + _accessors = accessors; |
| + } |
| + } |
| + return _accessors ?? PropertyAccessorElement.EMPTY_LIST; |
| + } |
| /** |
| * Set the top-level accessors (getters and setters) contained in this |
| @@ -1229,7 +1270,6 @@ class CompilationUnitElementImpl extends UriReferencedElementImpl |
| @override |
| String get identifier => source.encoding; |
| - |
|
Paul Berry
2016/05/19 11:27:29
Nit: restore this blank line.
|
| @override |
| ElementKind get kind => ElementKind.COMPILATION_UNIT; |
| @@ -1246,13 +1286,45 @@ class CompilationUnitElementImpl extends UriReferencedElementImpl |
| } |
| @override |
| - List<TopLevelVariableElement> get topLevelVariables => _variables; |
| + List<TopLevelVariableElement> get topLevelVariables { |
| + if (_unlinkedUnit != null) { |
| + if (_variables == null) { |
| + _explicitTopLevelAccessors ??= |
| + resynthesizerContext.buildTopLevelAccessors(); |
| + _explicitTopLevelVariables ??= |
| + resynthesizerContext.buildTopLevelVariables(); |
| + List<TopLevelVariableElementImpl> variables = |
| + <TopLevelVariableElementImpl>[]; |
| + variables.addAll(_explicitTopLevelVariables.variables); |
| + for (PropertyAccessorElementImpl implicitAccessor |
| + in _explicitTopLevelVariables.implicitAccessors) { |
| + implicitAccessor.enclosingElement = this; |
|
Paul Berry
2016/05/19 11:27:30
If `.accessors` is called and then `.topLevelVaria
scheglov
2016/05/19 16:54:57
Done.
|
| + } |
| + for (TopLevelVariableElementImpl implicitVariable |
| + in _explicitTopLevelAccessors.implicitVariables) { |
| + implicitVariable.enclosingElement = this; |
| + variables.add(implicitVariable); |
| + } |
| + _variables = variables; |
| + } |
| + (enclosingElement as LibraryElementImpl) |
| + .resynthesizerContext |
| + .patchTopLevelAccessors(); |
| + _topLevelVariableReplaceMap?.forEach((from, to) { |
| + int index = _variables.indexOf(from); |
| + _variables[index] = to; |
| + }); |
| + _topLevelVariableReplaceMap = null; |
| + } |
| + return _variables ?? TopLevelVariableElement.EMPTY_LIST; |
| + } |
| /** |
| * Set the top-level variables contained in this compilation unit to the given |
| * [variables]. |
| */ |
| void set topLevelVariables(List<TopLevelVariableElement> variables) { |
| + assert(!isResynthesized); |
| for (TopLevelVariableElement field in variables) { |
| (field as TopLevelVariableElementImpl).enclosingElement = this; |
| } |
| @@ -1334,13 +1406,13 @@ class CompilationUnitElementImpl extends UriReferencedElementImpl |
| // thrown a CCE if any of the elements in the arrays were not of the |
| // expected types. |
| // |
| - for (PropertyAccessorElement accessor in _accessors) { |
| + for (PropertyAccessorElement accessor in accessors) { |
| PropertyAccessorElementImpl accessorImpl = accessor; |
| if (accessorImpl.identifier == identifier) { |
| return accessorImpl; |
| } |
| } |
| - for (TopLevelVariableElement variable in _variables) { |
| + for (TopLevelVariableElement variable in topLevelVariables) { |
| TopLevelVariableElementImpl variableImpl = variable; |
| if (variableImpl.identifier == identifier) { |
| return variableImpl; |
| @@ -1360,10 +1432,58 @@ class CompilationUnitElementImpl extends UriReferencedElementImpl |
| } |
| for (ClassElement type in _types) { |
| ClassElementImpl typeImpl = type; |
| + if (typeImpl.name == identifier) { |
| + return typeImpl; |
| + } |
| + } |
| + for (ClassElement type in _enums) { |
| + ClassElementImpl typeImpl = type; |
| if (typeImpl.identifier == identifier) { |
| return typeImpl; |
| } |
| } |
| + return null; |
| + } |
| + |
| + /** |
| + * TODO(scheglov) When `_DeferredClassElement` is replaced with |
|
Paul Berry
2016/05/19 11:27:30
In addition to the TODO, I would appreciate a long
scheglov
2016/05/19 16:54:57
Done.
|
| + * [ClassElementImpl] remove this method. |
| + */ |
| + Element getChildNotImpl(String identifier) { |
| + // |
| + // The casts in this method are safe because the set methods would have |
| + // thrown a CCE if any of the elements in the arrays were not of the |
| + // expected types. |
| + // |
| + for (PropertyAccessorElement accessor in accessors) { |
| + PropertyAccessorElementImpl accessorImpl = accessor; |
| + if (accessorImpl.identifier == identifier) { |
| + return accessorImpl; |
| + } |
| + } |
| + for (TopLevelVariableElement variable in topLevelVariables) { |
| + TopLevelVariableElementImpl variableImpl = variable; |
| + if (variableImpl.identifier == identifier) { |
| + return variableImpl; |
| + } |
| + } |
| + for (FunctionElement function in _functions) { |
| + FunctionElementImpl functionImpl = function; |
| + if (functionImpl.identifier == identifier) { |
| + return functionImpl; |
| + } |
| + } |
| + for (FunctionTypeAliasElement typeAlias in _typeAliases) { |
| + FunctionTypeAliasElementImpl typeAliasImpl = typeAlias; |
| + if (typeAliasImpl.identifier == identifier) { |
| + return typeAliasImpl; |
| + } |
| + } |
| + for (ClassElement type in _types) { |
| + if (type.name == identifier) { |
| + return type; |
| + } |
| + } |
| for (ClassElement type in _enums) { |
| ClassElementImpl typeImpl = type; |
| if (typeImpl.identifier == identifier) { |
| @@ -1406,8 +1526,14 @@ class CompilationUnitElementImpl extends UriReferencedElementImpl |
| */ |
| void replaceTopLevelVariable( |
| TopLevelVariableElement from, TopLevelVariableElement to) { |
| - int index = _variables.indexOf(from); |
| - _variables[index] = to; |
| + if (_unlinkedUnit != null) { |
| + _topLevelVariableReplaceMap ??= |
|
Paul Berry
2016/05/19 11:27:29
This will only have the desired effect if the `top
scheglov
2016/05/19 16:54:57
Done.
|
| + <TopLevelVariableElement, TopLevelVariableElement>{}; |
| + _topLevelVariableReplaceMap[from] = to; |
| + } else { |
| + int index = _variables.indexOf(from); |
| + _variables[index] = to; |
| + } |
| } |
| /** |
| @@ -1422,12 +1548,12 @@ class CompilationUnitElementImpl extends UriReferencedElementImpl |
| @override |
| void visitChildren(ElementVisitor visitor) { |
| super.visitChildren(visitor); |
| - safelyVisitChildren(_accessors, visitor); |
| + safelyVisitChildren(accessors, visitor); |
| safelyVisitChildren(_enums, visitor); |
| safelyVisitChildren(_functions, visitor); |
| safelyVisitChildren(_typeAliases, visitor); |
| safelyVisitChildren(_types, visitor); |
| - safelyVisitChildren(_variables, visitor); |
| + safelyVisitChildren(topLevelVariables, visitor); |
| } |
| } |
| @@ -1639,6 +1765,13 @@ class ConstTopLevelVariableElementImpl extends TopLevelVariableElementImpl |
| */ |
| ConstTopLevelVariableElementImpl.forNode(Identifier name) |
| : super.forNode(name); |
| + |
| + /** |
| + * Initialize using the given serialized information. |
| + */ |
| + ConstTopLevelVariableElementImpl.forSerialized( |
| + UnlinkedVariable unlinkedVariable, ElementImpl enclosingElement) |
| + : super.forSerialized(unlinkedVariable, enclosingElement); |
| } |
| /** |
| @@ -3644,6 +3777,10 @@ class LibraryElementImpl extends ElementImpl implements LibraryElement { |
| */ |
| final AnalysisContext context; |
| + final LibraryResynthesizerContext resynthesizerContext; |
| + |
| + final UnlinkedUnit _unlinkedDefiningUnit; |
| + |
| /** |
| * The compilation unit that defines this library. |
| */ |
| @@ -3653,7 +3790,7 @@ class LibraryElementImpl extends ElementImpl implements LibraryElement { |
| * The entry point for this library, or `null` if this library does not have |
| * an entry point. |
| */ |
| - FunctionElement entryPoint; |
| + FunctionElement _entryPoint; |
| /** |
| * A list containing specifications of all of the imports defined in this |
| @@ -3695,22 +3832,22 @@ class LibraryElementImpl extends ElementImpl implements LibraryElement { |
| * The export [Namespace] of this library, `null` if it has not been |
| * computed yet. |
| */ |
| - @override |
| - Namespace exportNamespace; |
| + Namespace _exportNamespace; |
| /** |
| * The public [Namespace] of this library, `null` if it has not been |
| * computed yet. |
| */ |
| - @override |
| - Namespace publicNamespace; |
| + Namespace _publicNamespace; |
| /** |
| * Initialize a newly created library element in the given [context] to have |
| * the given [name] and [offset]. |
| */ |
| LibraryElementImpl(this.context, String name, int offset, this.nameLength) |
| - : super(name, offset); |
| + : resynthesizerContext = null, |
| + _unlinkedDefiningUnit = null, |
| + super(name, offset); |
| /** |
| * Initialize a newly created library element in the given [context] to have |
| @@ -3718,8 +3855,20 @@ class LibraryElementImpl extends ElementImpl implements LibraryElement { |
| */ |
| LibraryElementImpl.forNode(this.context, LibraryIdentifier name) |
| : nameLength = name != null ? name.length : 0, |
| + resynthesizerContext = null, |
| + _unlinkedDefiningUnit = null, |
| super.forNode(name); |
| + /** |
| + * Initialize using the given serialized information. |
| + */ |
| + LibraryElementImpl.forSerialized(this.context, String name, int offset, |
| + this.nameLength, this.resynthesizerContext, this._unlinkedDefiningUnit) |
| + : super.forSerialized(null) { |
| + _name = name; |
| + _nameOffset = offset; |
| + } |
| + |
| @override |
| int get codeLength { |
| CompilationUnitElement unit = _definingCompilationUnit; |
| @@ -3753,6 +3902,37 @@ class LibraryElementImpl extends ElementImpl implements LibraryElement { |
| } |
| @override |
| + SourceRange get docRange { |
| + if (_unlinkedDefiningUnit != null) { |
| + UnlinkedDocumentationComment comment = |
| + _unlinkedDefiningUnit.libraryDocumentationComment; |
| + return comment != null |
| + ? new SourceRange(comment.offset, comment.length) |
| + : null; |
| + } |
| + return super.docRange; |
| + } |
| + |
| + @override |
| + String get documentationComment { |
| + if (_unlinkedDefiningUnit != null) { |
| + return _unlinkedDefiningUnit?.libraryDocumentationComment?.text; |
| + } |
| + return super.documentationComment; |
| + } |
| + |
| + FunctionElement get entryPoint { |
| + if (resynthesizerContext != null) { |
| + _entryPoint ??= resynthesizerContext.findEntryPoint(); |
| + } |
| + return _entryPoint; |
| + } |
| + |
| + void set entryPoint(FunctionElement entryPoint) { |
| + _entryPoint = entryPoint; |
| + } |
| + |
| + @override |
| List<LibraryElement> get exportedLibraries { |
| HashSet<LibraryElement> libraries = new HashSet<LibraryElement>(); |
| for (ExportElement element in _exports) { |
| @@ -3765,6 +3945,18 @@ class LibraryElementImpl extends ElementImpl implements LibraryElement { |
| } |
| @override |
| + Namespace get exportNamespace { |
| + if (resynthesizerContext != null) { |
| + _exportNamespace ??= resynthesizerContext.buildExportNamespace(); |
| + } |
| + return _exportNamespace; |
| + } |
| + |
| + void set exportNamespace(Namespace exportNamespace) { |
| + _exportNamespace = exportNamespace; |
| + } |
| + |
| + @override |
| List<ExportElement> get exports => _exports; |
| /** |
| @@ -3878,9 +4070,7 @@ class LibraryElementImpl extends ElementImpl implements LibraryElement { |
| @override |
| bool get isResynthesized { |
| - CompilationUnitElement definingUnit = _definingCompilationUnit; |
| - return definingUnit is CompilationUnitElementImpl && |
| - definingUnit.resynthesizerContext != null; |
| + return resynthesizerContext != null; |
| } |
| @override |
| @@ -3973,6 +4163,21 @@ class LibraryElementImpl extends ElementImpl implements LibraryElement { |
| } |
| @override |
| + List<ElementAnnotation> get metadata { |
| + if (_unlinkedDefiningUnit != null) { |
| + if (_metadata == null) { |
| + CompilationUnitElementImpl definingUnit = |
| + _definingCompilationUnit as CompilationUnitElementImpl; |
| + _metadata ??= _unlinkedDefiningUnit.libraryAnnotations |
| + .map(definingUnit.resynthesizerContext.buildAnnotation) |
| + .toList(); |
| + } |
| + return _metadata; |
| + } |
| + return super.metadata; |
| + } |
| + |
| + @override |
| List<CompilationUnitElement> get parts => _parts; |
| /** |
| @@ -4001,6 +4206,18 @@ class LibraryElementImpl extends ElementImpl implements LibraryElement { |
| } |
| @override |
| + Namespace get publicNamespace { |
| + if (resynthesizerContext != null) { |
| + _publicNamespace ??= resynthesizerContext.buildPublicNamespace(); |
| + } |
| + return _publicNamespace; |
| + } |
| + |
| + void set publicNamespace(Namespace publicNamespace) { |
| + _publicNamespace = publicNamespace; |
| + } |
| + |
| + @override |
| Source get source { |
| if (_definingCompilationUnit == null) { |
| return null; |
| @@ -4233,6 +4450,16 @@ class LibraryElementImpl extends ElementImpl implements LibraryElement { |
| } |
| /** |
| + * TODO(scheglov) document |
|
Paul Berry
2016/05/19 11:27:29
Did you intend to address this before sending out
scheglov
2016/05/19 16:54:57
Done.
|
| + */ |
| +abstract class LibraryResynthesizerContext { |
| + Namespace buildExportNamespace(); |
| + Namespace buildPublicNamespace(); |
| + FunctionElement findEntryPoint(); |
| + void patchTopLevelAccessors(); |
| +} |
| + |
| +/** |
| * A concrete implementation of a [LocalVariableElement]. |
| */ |
| class LocalVariableElementImpl extends NonParameterVariableElementImpl |
| @@ -4856,6 +5083,26 @@ abstract class NonParameterVariableElementImpl extends VariableElementImpl { |
| } |
| @override |
| + SourceRange get docRange { |
| + if (_unlinkedVariable != null) { |
| + UnlinkedDocumentationComment comment = |
| + _unlinkedVariable.documentationComment; |
| + return comment != null |
| + ? new SourceRange(comment.offset, comment.length) |
| + : null; |
| + } |
| + return super.docRange; |
| + } |
| + |
| + @override |
| + String get documentationComment { |
| + if (_unlinkedVariable != null) { |
| + return _unlinkedVariable?.documentationComment?.text; |
| + } |
| + return super.documentationComment; |
| + } |
| + |
| + @override |
| void set final2(bool isFinal) { |
| assert(_unlinkedVariable == null); |
| super.final2 = isFinal; |
| @@ -5490,6 +5737,13 @@ abstract class PropertyInducingElementImpl |
| * Initialize a newly created element to have the given [name]. |
| */ |
| PropertyInducingElementImpl.forNode(Identifier name) : super.forNode(name); |
| + |
| + /** |
| + * Initialize using the given serialized information. |
| + */ |
| + PropertyInducingElementImpl.forSerialized( |
| + UnlinkedVariable unlinkedVariable, ElementImpl enclosingElement) |
| + : super.forSerialized(unlinkedVariable, enclosingElement); |
| } |
| /** |
| @@ -5507,6 +5761,16 @@ abstract class ResynthesizerContext { |
| Expression buildExpression(UnlinkedConst uc); |
| /** |
| + * Build explicit top-level property accessors. |
| + */ |
| + UnitExplicitTopLevelAccessors buildTopLevelAccessors(); |
| + |
| + /** |
| + * Build explicit top-level variables. |
| + */ |
| + UnitExplicitTopLevelVariables buildTopLevelVariables(); |
| + |
| + /** |
| * Resolve an [EntityRef] into a type. If the reference is |
| * unresolved, return [DynamicTypeImpl.instance]. |
| * |
| @@ -5571,6 +5835,13 @@ class TopLevelVariableElementImpl extends PropertyInducingElementImpl |
| */ |
| TopLevelVariableElementImpl.forNode(Identifier name) : super.forNode(name); |
| + /** |
| + * Initialize using the given serialized information. |
| + */ |
| + TopLevelVariableElementImpl.forSerialized( |
| + UnlinkedVariable unlinkedVariable, ElementImpl enclosingElement) |
| + : super.forSerialized(unlinkedVariable, enclosingElement); |
| + |
| @override |
| bool get isStatic => true; |
| @@ -5851,6 +6122,28 @@ abstract class TypeParameterizedElementMixin |
| } |
| /** |
| + * Container with information about explicit top-level property accessors and |
| + * corresponding implicit top-level variables. |
| + */ |
| +class UnitExplicitTopLevelAccessors { |
| + final List<PropertyAccessorElementImpl> accessors = |
| + <PropertyAccessorElementImpl>[]; |
| + final List<TopLevelVariableElementImpl> implicitVariables = |
| + <TopLevelVariableElementImpl>[]; |
| +} |
| + |
| +/** |
| + * Container with information about explicit top-level variables and |
| + * corresponding implicit top-level property accessors. |
| + */ |
| +class UnitExplicitTopLevelVariables { |
| + final List<TopLevelVariableElementImpl> variables = |
| + <TopLevelVariableElementImpl>[]; |
| + final List<PropertyAccessorElementImpl> implicitAccessors = |
| + <PropertyAccessorElementImpl>[]; |
| +} |
| + |
| +/** |
| * A concrete implementation of a [UriReferencedElement]. |
| */ |
| abstract class UriReferencedElementImpl extends ElementImpl |