| Index: dart/compiler/java/com/google/dart/compiler/resolver/MemberBuilder.java
|
| diff --git a/dart/compiler/java/com/google/dart/compiler/resolver/MemberBuilder.java b/dart/compiler/java/com/google/dart/compiler/resolver/MemberBuilder.java
|
| deleted file mode 100644
|
| index a46aa61d2adf7ecc38df285d5f3c834c8a4def46..0000000000000000000000000000000000000000
|
| --- a/dart/compiler/java/com/google/dart/compiler/resolver/MemberBuilder.java
|
| +++ /dev/null
|
| @@ -1,736 +0,0 @@
|
| -// Copyright (c) 2012, 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.
|
| -
|
| -package com.google.dart.compiler.resolver;
|
| -
|
| -import com.google.common.annotations.VisibleForTesting;
|
| -import com.google.common.base.Objects;
|
| -import com.google.dart.compiler.DartCompilerContext;
|
| -import com.google.dart.compiler.ErrorCode;
|
| -import com.google.dart.compiler.ast.ASTVisitor;
|
| -import com.google.dart.compiler.ast.DartBlock;
|
| -import com.google.dart.compiler.ast.DartClass;
|
| -import com.google.dart.compiler.ast.DartExpression;
|
| -import com.google.dart.compiler.ast.DartField;
|
| -import com.google.dart.compiler.ast.DartFieldDefinition;
|
| -import com.google.dart.compiler.ast.DartFunction;
|
| -import com.google.dart.compiler.ast.DartFunctionTypeAlias;
|
| -import com.google.dart.compiler.ast.DartIdentifier;
|
| -import com.google.dart.compiler.ast.DartMethodDefinition;
|
| -import com.google.dart.compiler.ast.DartNativeBlock;
|
| -import com.google.dart.compiler.ast.DartNode;
|
| -import com.google.dart.compiler.ast.DartParameter;
|
| -import com.google.dart.compiler.ast.DartParameterizedTypeNode;
|
| -import com.google.dart.compiler.ast.DartPropertyAccess;
|
| -import com.google.dart.compiler.ast.DartThisExpression;
|
| -import com.google.dart.compiler.ast.DartUnit;
|
| -import com.google.dart.compiler.ast.Modifiers;
|
| -import com.google.dart.compiler.common.HasSourceInfo;
|
| -import com.google.dart.compiler.common.SourceInfo;
|
| -import com.google.dart.compiler.type.Type;
|
| -import com.google.dart.compiler.type.Types;
|
| -import com.google.dart.compiler.util.apache.StringUtils;
|
| -
|
| -import java.util.ArrayList;
|
| -import java.util.List;
|
| -
|
| -/**
|
| - * Builds the method, field and constructor elements of classes and the library in a DartUnit.
|
| - */
|
| -public class MemberBuilder {
|
| - private ResolutionContext topLevelContext;
|
| - private LibraryElement libraryElement;
|
| -
|
| - public void exec(DartUnit unit, DartCompilerContext context, CoreTypeProvider typeProvider) {
|
| - Scope scope = unit.getLibrary().getElement().getScope();
|
| - exec(unit, context, scope, typeProvider);
|
| - }
|
| -
|
| - @VisibleForTesting
|
| - public void exec(DartUnit unit, DartCompilerContext compilerContext, Scope scope,
|
| - CoreTypeProvider typeProvider) {
|
| - libraryElement = unit.getLibrary().getElement();
|
| - topLevelContext = new ResolutionContext(scope, compilerContext, typeProvider);
|
| - unit.accept(new MemberElementBuilder(typeProvider));
|
| - }
|
| -
|
| - /**
|
| - * Creates elements for the fields, methods and constructors of a class. The
|
| - * elements are added to the ClassElement.
|
| - *
|
| - * TODO(ngeoffray): Errors reported:
|
| - * - Duplicate member names in the same class.
|
| - * - Unresolved types.
|
| - */
|
| - private class MemberElementBuilder extends ResolveVisitor {
|
| - EnclosingElement currentHolder;
|
| - private EnclosingElement enclosingElement;
|
| - private ResolutionContext context;
|
| - private boolean isStatic;
|
| - private boolean isFactory;
|
| -
|
| - MemberElementBuilder(CoreTypeProvider typeProvider) {
|
| - super(typeProvider);
|
| - context = topLevelContext;
|
| - currentHolder = libraryElement;
|
| - }
|
| -
|
| - @Override
|
| - ResolutionContext getContext() {
|
| - return context;
|
| - }
|
| -
|
| - @Override
|
| - protected EnclosingElement getEnclosingElement() {
|
| - return enclosingElement;
|
| - }
|
| -
|
| - @Override
|
| - public Element visitClass(DartClass node) {
|
| - assert !ElementKind.of(currentHolder).equals(ElementKind.CLASS) : "nested class?";
|
| - beginClassContext(node);
|
| - ClassElement classElement = node.getElement();
|
| - EnclosingElement previousEnclosingElement = enclosingElement;
|
| - enclosingElement = classElement;
|
| - // visit fields, to make their Elements ready for constructor parameters
|
| - for (DartNode member : node.getMembers()) {
|
| - if (member instanceof DartFieldDefinition) {
|
| - member.accept(this);
|
| - }
|
| - }
|
| - // visit all other members
|
| - for (DartNode member : node.getMembers()) {
|
| - if (!(member instanceof DartFieldDefinition)) {
|
| - member.accept(this);
|
| - }
|
| - }
|
| - // check constructor names
|
| - for (ConstructorElement constructor : classElement.getConstructors()) {
|
| - String name = constructor.getName();
|
| - SourceInfo nameLocation = constructor.getNameLocation();
|
| - // should be name of immediately enclosing class
|
| - if (constructor.getModifiers().isFactory()) {
|
| - String rawName = constructor.getRawName();
|
| - String consClassName = StringUtils.substringBefore(rawName, ".");
|
| - String consUserName = StringUtils.substringAfter(rawName, ".");
|
| - if (!StringUtils.equals(consClassName, classElement.getName())) {
|
| - // report error for for M part of M.id or pure M
|
| - SourceInfo consClassLocation = new SourceInfo(nameLocation.getSource(),
|
| - nameLocation.getOffset(), consClassName.length());
|
| - resolutionError(consClassLocation,
|
| - ResolverErrorCode.CONSTRUCTOR_NAME_NOT_ENCLOSING_CLASS);
|
| - // in addition also report warning for whole constructor name
|
| - if (!StringUtils.isEmpty(consUserName)) {
|
| - resolutionError(nameLocation,
|
| - ResolverErrorCode.CONSTRUCTOR_NAME_NOT_ENCLOSING_CLASS_ID);
|
| - }
|
| - }
|
| - }
|
| - // should not conflict with member names
|
| - {
|
| - Element member = classElement.lookupLocalElement(name);
|
| - if (member != null) {
|
| - resolutionError(nameLocation,
|
| - ResolverErrorCode.CONSTRUCTOR_WITH_NAME_OF_MEMBER);
|
| - }
|
| - }
|
| - }
|
| - // done with this class
|
| - enclosingElement = previousEnclosingElement;
|
| - endClassContext();
|
| - return null;
|
| - }
|
| -
|
| - private void checkParameterInitializer(DartMethodDefinition method, DartParameter parameter) {
|
| - if (Elements.isNonFactoryConstructor(method.getElement())) {
|
| - if (method.getModifiers().isRedirectedConstructor()) {
|
| - resolutionError(parameter.getName(),
|
| - ResolverErrorCode.PARAMETER_INIT_WITH_REDIR_CONSTRUCTOR);
|
| - }
|
| -
|
| - FieldElement element =
|
| - Elements.lookupLocalField((ClassElement) currentHolder, parameter.getParameterName());
|
| - if (element == null) {
|
| - resolutionError(parameter, ResolverErrorCode.PARAMETER_NOT_MATCH_FIELD,
|
| - parameter.getName());
|
| - } else if (element.isStatic()) {
|
| - resolutionError(parameter,
|
| - ResolverErrorCode.PARAMETER_INIT_STATIC_FIELD,
|
| - parameter.getName());
|
| - }
|
| -
|
| - // Field parameters are not visible as parameters, so we do not declare them
|
| - // in the context. Instead we record the resolved field element.
|
| - Elements.setParameterInitializerElement(parameter.getElement(), element);
|
| -
|
| - // The editor expects the referenced elements to be non-null
|
| - DartPropertyAccess prop = (DartPropertyAccess)parameter.getName();
|
| - prop.setElement(element);
|
| - prop.getName().setElement(element);
|
| -
|
| - // If no type specified, use type of field.
|
| - if (parameter.getTypeNode() == null && element != null) {
|
| - Elements.setType(parameter.getElement(), element.getType());
|
| - }
|
| - } else {
|
| - resolutionError(parameter.getName(),
|
| - ResolverErrorCode.PARAMETER_INIT_OUTSIDE_CONSTRUCTOR);
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public Element visitFunctionTypeAlias(DartFunctionTypeAlias node) {
|
| - isStatic = false;
|
| - isFactory = false;
|
| - assert !ElementKind.of(currentHolder).equals(ElementKind.CLASS) : "nested class?";
|
| - FunctionAliasElement element = node.getElement();
|
| - currentHolder = element;
|
| - context = context.extend((ClassElement) currentHolder); // Put type variables in scope.
|
| - visit(node.getTypeParameters());
|
| - List<VariableElement> parameters = new ArrayList<VariableElement>();
|
| - for (DartParameter parameter : node.getParameters()) {
|
| - parameters.add((VariableElement) parameter.accept(this));
|
| - }
|
| - Type returnType = resolveType(node.getReturnTypeNode(), false, false, true,
|
| - TypeErrorCode.NO_SUCH_TYPE, TypeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS);
|
| - ClassElement functionElement = getTypeProvider().getFunctionType().getElement();
|
| - element.setFunctionType(Types.makeFunctionType(getContext(), functionElement,
|
| - parameters, returnType));
|
| - currentHolder = libraryElement;
|
| - context = topLevelContext;
|
| - return null;
|
| - }
|
| -
|
| - @Override
|
| - public Element visitMethodDefinition(final DartMethodDefinition method) {
|
| - isFactory = method.getModifiers().isFactory();
|
| - isStatic = method.getModifiers().isStatic() || isFactory;
|
| - MethodNodeElement element = method.getElement();
|
| - if (element == null) {
|
| - switch (getMethodKind(method)) {
|
| - case NONE:
|
| - case CONSTRUCTOR:
|
| - element = buildConstructor(method);
|
| - checkConstructor(element, method);
|
| - addConstructor((ClassElement) currentHolder, (ConstructorNodeElement) element);
|
| - break;
|
| -
|
| - case METHOD:
|
| - element = Elements.methodFromMethodNode(method, currentHolder);
|
| - addMethod(currentHolder, element);
|
| - break;
|
| - }
|
| - } else {
|
| - // This is a top-level element, and an element was already created in
|
| - // TopLevelElementBuilder.
|
| - Elements.addMethod(currentHolder, element);
|
| - assertTopLevel(method);
|
| - }
|
| - if (element != null) {
|
| - checkTopLevelMainFunction(method);
|
| - checkModifiers(element, method);
|
| - recordElement(method, element);
|
| - recordElement(method.getName(), element);
|
| - ResolutionContext previous = context;
|
| - context = context.extend(element.getName());
|
| - EnclosingElement previousEnclosingElement = enclosingElement;
|
| - enclosingElement = element;
|
| - resolveFunction(method.getFunction(), element);
|
| - enclosingElement = previousEnclosingElement;
|
| - context = previous;
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - @Override
|
| - protected void resolveFunctionWithParameters(DartFunction node, MethodElement element) {
|
| - super.resolveFunctionWithParameters(node, element);
|
| - // Bind "formal initializers" to fields.
|
| - if (node.getParent() instanceof DartMethodDefinition) {
|
| - DartMethodDefinition method = (DartMethodDefinition) node.getParent();
|
| - for (DartParameter parameter : node.getParameters()) {
|
| - if (parameter.getQualifier() instanceof DartThisExpression) {
|
| - checkParameterInitializer(method, parameter);
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public Element visitFieldDefinition(DartFieldDefinition node) {
|
| - isStatic = false;
|
| - isFactory = false;
|
| - for (DartField fieldNode : node.getFields()) {
|
| - if (fieldNode.getModifiers().isStatic()) {
|
| - isStatic = true;
|
| - }
|
| - }
|
| - Type type = resolveType(node.getTypeNode(), isStatic, false, true, TypeErrorCode.NO_SUCH_TYPE,
|
| - TypeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS);
|
| - for (DartField fieldNode : node.getFields()) {
|
| - if (fieldNode.getModifiers().isAbstractField()) {
|
| - buildAbstractField(fieldNode);
|
| - } else {
|
| - buildField(fieldNode, type);
|
| - }
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - private void beginClassContext(final DartClass node) {
|
| - assert !ElementKind.of(currentHolder).equals(ElementKind.CLASS) : "nested class?";
|
| - currentHolder = node.getElement();
|
| - context = context.extend((ClassElement) currentHolder);
|
| - }
|
| -
|
| - private void endClassContext() {
|
| - currentHolder = libraryElement;
|
| - context = topLevelContext;
|
| - }
|
| -
|
| - private Element resolveConstructorName(final DartMethodDefinition method) {
|
| - return method.getName().accept(new ASTVisitor<Element>() {
|
| - @Override
|
| - public Element visitPropertyAccess(DartPropertyAccess node) {
|
| - Element element = context.resolveName(node);
|
| - if (ElementKind.of(element) == ElementKind.CLASS) {
|
| - return resolveType(node);
|
| - } else {
|
| - element = node.getQualifier().accept(this);
|
| - recordElement(node.getQualifier(), element);
|
| - }
|
| - if (ElementKind.of(element) == ElementKind.CLASS) {
|
| - return Elements.constructorFromMethodNode(
|
| - method, node.getPropertyName(), (ClassElement) currentHolder, (ClassElement) element);
|
| - } else {
|
| - // Nothing else is valid. Already warned in getMethodKind().
|
| - return getTypeProvider().getDynamicType().getElement();
|
| - }
|
| - }
|
| - @Override
|
| - public Element visitIdentifier(DartIdentifier node) {
|
| - return resolveType(node);
|
| - }
|
| - private Element resolveType(DartNode node) {
|
| - return context.resolveType(
|
| - node,
|
| - node,
|
| - null,
|
| - true,
|
| - false,
|
| - false,
|
| - ResolverErrorCode.NO_SUCH_TYPE_CONSTRUCTOR,
|
| - ResolverErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS).getElement();
|
| - }
|
| - @Override
|
| - public Element visitParameterizedTypeNode(DartParameterizedTypeNode node) {
|
| - Element element = node.getExpression().accept(this);
|
| - if (ElementKind.of(element).equals(ElementKind.CONSTRUCTOR)) {
|
| - recordElement(node.getExpression(), currentHolder);
|
| - } else {
|
| - recordElement(node.getExpression(), element);
|
| - }
|
| - return element;
|
| - }
|
| - @Override
|
| - public Element visitNode(DartNode node) {
|
| - throw new RuntimeException("Unexpected node " + node);
|
| - }
|
| - });
|
| - }
|
| -
|
| - private MethodNodeElement buildConstructor(final DartMethodDefinition method) {
|
| - // Resolve the constructor's name and class name.
|
| - Element e = resolveConstructorName(method);
|
| -
|
| - switch (ElementKind.of(e)) {
|
| - default:
|
| - // Report an error and create a fake constructor element below.
|
| - resolutionError(method.getName(), ResolverErrorCode.INVALID_TYPE_NAME_IN_CONSTRUCTOR);
|
| - break;
|
| -
|
| - case DYNAMIC:
|
| - case CLASS:
|
| - break;
|
| -
|
| - case CONSTRUCTOR:
|
| - return (ConstructorNodeElement) e;
|
| - }
|
| -
|
| - // If the constructor name resolves to a class or there was an error,
|
| - // create the unnamed constructor.
|
| - return Elements.constructorFromMethodNode(method, "", (ClassElement) currentHolder,
|
| - (ClassElement) e);
|
| - }
|
| -
|
| - private FieldElement buildField(DartField fieldNode, Type type) {
|
| - assert !fieldNode.getModifiers().isAbstractField();
|
| - Modifiers modifiers = fieldNode.getModifiers();
|
| - // top-level fields are implicitly static.
|
| - if (context == topLevelContext) {
|
| - modifiers = modifiers.makeStatic();
|
| - }
|
| - if (fieldNode.getValue() != null) {
|
| - modifiers = modifiers.makeInitialized();
|
| - }
|
| - FieldNodeElement fieldElement = fieldNode.getElement();
|
| - if (fieldElement == null) {
|
| - fieldElement = Elements.fieldFromNode(fieldNode, currentHolder, fieldNode.getObsoleteMetadata(),
|
| - modifiers);
|
| - addField(currentHolder, fieldElement);
|
| - } else {
|
| - // This is a top-level element, and an element was already created in
|
| - // TopLevelElementBuilder.
|
| - Elements.addField(currentHolder, fieldElement);
|
| - assertTopLevel(fieldNode);
|
| - }
|
| - fieldElement.setType(type);
|
| - recordElement(fieldNode.getName(), fieldElement);
|
| - return recordElement(fieldNode, fieldElement);
|
| - }
|
| -
|
| - private void assertTopLevel(DartNode node) throws AssertionError {
|
| - if (!currentHolder.getKind().equals(ElementKind.LIBRARY)) {
|
| - throw topLevelContext.internalError(node, "expected top-level node");
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Creates FieldElement for AST getters and setters.
|
| - *
|
| - * class A {
|
| - * int get foo() { ... }
|
| - * set foo(x) { ... }
|
| - * }
|
| - *
|
| - * The AST will have the shape (simplified):
|
| - * DartClass
|
| - * members
|
| - * DartFieldDefinition
|
| - * DartField
|
| - * + name: foo
|
| - * + modifiers: abstractfield
|
| - * + accessor: int get foo() { ... }
|
| - * DartFieldDefinition
|
| - * DartField
|
| - * + name: foo
|
| - * + modifiers: abstractfield
|
| - * + accessor: set foo(x) { ... }
|
| - *
|
| - * MemberBuilder will reduce to one class element as below (simplified):
|
| - * ClassElement
|
| - * members:
|
| - * FieldElement
|
| - * + name: foo
|
| - * + getter:
|
| - * MethodElement
|
| - * + name: foo
|
| - * + function: int get foo() { ... }
|
| - * + setter:
|
| - * MethodElement
|
| - * + name: foo
|
| - * + function: set foo(x) { ... }
|
| - *
|
| - */
|
| - private FieldElement buildAbstractField(DartField fieldNode) {
|
| - assert fieldNode.getModifiers().isAbstractField();
|
| - boolean topLevelDefinition = fieldNode.getParent().getParent() instanceof DartUnit;
|
| - DartMethodDefinition accessorNode = fieldNode.getAccessor();
|
| - MethodNodeElement accessorElement = Elements.methodFromMethodNode(accessorNode, currentHolder);
|
| - EnclosingElement previousEnclosingElement = enclosingElement;
|
| - enclosingElement = accessorElement;
|
| - recordElement(accessorNode, accessorElement);
|
| - resolveFunction(accessorNode.getFunction(), accessorElement);
|
| - enclosingElement = previousEnclosingElement;
|
| -
|
| - String name = fieldNode.getName().getName();
|
| - Element element = null;
|
| - if (currentHolder != null) {
|
| - element = currentHolder.lookupLocalElement(name);
|
| - if (element == null) {
|
| - element = currentHolder.lookupLocalElement("setter " + name);
|
| - }
|
| - } else {
|
| - // Top level nodes are not handled gracefully
|
| - Scope scope = topLevelContext.getScope();
|
| - LibraryElement library = context.getScope().getLibrary();
|
| - element = scope.findElement(library, name);
|
| - if (element == null) {
|
| - element = scope.findElement(library, "setter " + name);
|
| - }
|
| - }
|
| -
|
| - FieldElementImplementation fieldElement = null;
|
| - if (element == null || element.getKind().equals(ElementKind.FIELD)
|
| - && element.getModifiers().isAbstractField()) {
|
| - fieldElement = (FieldElementImplementation) element;
|
| - }
|
| -
|
| - if (accessorNode.getModifiers().isGetter() && fieldElement != null && fieldElement.getSetter() != null) {
|
| - MethodNodeElement oldSetter = fieldElement.getSetter();
|
| - fieldElement = Elements.fieldFromNode(fieldNode, currentHolder, fieldNode.getObsoleteMetadata(),
|
| - fieldNode.getModifiers());
|
| - fieldElement.setSetter(oldSetter);
|
| - addField(currentHolder, fieldElement);
|
| - }
|
| -
|
| - if (fieldElement == null) {
|
| - fieldElement = Elements.fieldFromNode(fieldNode, currentHolder, fieldNode.getObsoleteMetadata(),
|
| - fieldNode.getModifiers());
|
| - addField(currentHolder, fieldElement);
|
| - }
|
| -
|
| - if (accessorNode.getModifiers().isGetter()) {
|
| - if (fieldElement.getGetter() != null) {
|
| - if (!topLevelDefinition) {
|
| - reportDuplicateDeclaration(ResolverErrorCode.DUPLICATE_MEMBER, fieldElement.getGetter());
|
| - reportDuplicateDeclaration(ResolverErrorCode.DUPLICATE_MEMBER, accessorElement);
|
| - }
|
| - } else {
|
| - fieldElement.setGetter(accessorElement);
|
| - fieldElement.setType(accessorElement.getReturnType());
|
| - }
|
| - } else if (accessorNode.getModifiers().isSetter()) {
|
| - if (fieldElement.getSetter() != null) {
|
| - if (!topLevelDefinition) {
|
| - reportDuplicateDeclaration(ResolverErrorCode.DUPLICATE_MEMBER, fieldElement.getSetter());
|
| - reportDuplicateDeclaration(ResolverErrorCode.DUPLICATE_MEMBER, accessorElement);
|
| - }
|
| - } else {
|
| - fieldElement.setSetter(accessorElement);
|
| - List<VariableElement> parameters = accessorElement.getParameters();
|
| - Type type;
|
| - if (parameters.size() == 0) {
|
| - // Error flagged in parser
|
| - type = getTypeProvider().getDynamicType();
|
| - } else {
|
| - type = parameters.get(0).getType();
|
| - }
|
| - fieldElement.setType(type);
|
| - }
|
| - }
|
| - recordElement(fieldNode.getName(), accessorElement);
|
| - return recordElement(fieldNode, fieldElement);
|
| - }
|
| -
|
| - private void addField(EnclosingElement holder, FieldNodeElement element) {
|
| - if (holder != null) {
|
| - checkUniqueName(holder, element);
|
| - checkMemberNameNotSameAsEnclosingClassName(holder, element);
|
| - Elements.addField(holder, element);
|
| - }
|
| - }
|
| -
|
| - private void addMethod(EnclosingElement holder, MethodNodeElement element) {
|
| - checkUniqueName(holder, element);
|
| - checkMemberNameNotSameAsEnclosingClassName(holder, element);
|
| - Elements.addMethod(holder, element);
|
| - }
|
| -
|
| - private void addConstructor(ClassElement cls, ConstructorNodeElement element) {
|
| - checkUniqueName(cls, element);
|
| - Elements.addConstructor(cls, element);
|
| - }
|
| -
|
| - private ElementKind getMethodKind(DartMethodDefinition method) {
|
| - if (!ElementKind.of(currentHolder).equals(ElementKind.CLASS)) {
|
| - return ElementKind.METHOD;
|
| - }
|
| -
|
| - if (method.getModifiers().isFactory()) {
|
| - return ElementKind.CONSTRUCTOR;
|
| - }
|
| -
|
| - DartExpression name = method.getName();
|
| - if (name instanceof DartIdentifier) {
|
| - if (((DartIdentifier) name).getName().equals(currentHolder.getName())) {
|
| - return ElementKind.CONSTRUCTOR;
|
| - } else {
|
| - return ElementKind.METHOD;
|
| - }
|
| - } else {
|
| - DartPropertyAccess property = (DartPropertyAccess) name;
|
| - if (property.getQualifier() instanceof DartIdentifier) {
|
| - DartIdentifier qualifier = (DartIdentifier) property.getQualifier();
|
| - if (qualifier.getName().equals(currentHolder.getName())) {
|
| - return ElementKind.CONSTRUCTOR;
|
| - }
|
| - resolutionError(method.getName(),
|
| - ResolverErrorCode.CANNOT_DECLARE_NON_FACTORY_CONSTRUCTOR);
|
| - } else if (property.getQualifier() instanceof DartParameterizedTypeNode) {
|
| - DartParameterizedTypeNode paramNode = (DartParameterizedTypeNode)property.getQualifier();
|
| - if (paramNode.getExpression() instanceof DartIdentifier) {
|
| - return ElementKind.CONSTRUCTOR;
|
| - }
|
| - resolutionError(method.getName(),
|
| - ResolverErrorCode.TOO_MANY_QUALIFIERS_FOR_METHOD);
|
| - } else {
|
| - // Multiple qualifiers (Foo.bar.baz)
|
| - resolutionError(method.getName(),
|
| - ResolverErrorCode.TOO_MANY_QUALIFIERS_FOR_METHOD);
|
| - }
|
| - }
|
| -
|
| - return ElementKind.NONE;
|
| - }
|
| -
|
| - /**
|
| - * Checks that top-level "main()" has no parameters.
|
| - */
|
| - private void checkTopLevelMainFunction(DartMethodDefinition method) {
|
| - if (!method.getFunction().getParameters().isEmpty()
|
| - && currentHolder instanceof LibraryElement
|
| - && Objects.equal(method.getName().toString(), "main")) {
|
| - resolutionError(method.getName(), ResolverErrorCode.MAIN_FUNCTION_PARAMETERS);
|
| - }
|
| - }
|
| -
|
| - private void checkModifiers(MethodElement element, DartMethodDefinition method) {
|
| - Modifiers modifiers = method.getModifiers();
|
| - boolean isNonFactoryConstructor = Elements.isNonFactoryConstructor(element);
|
| - // TODO(ngeoffray): The errors should report the position of the modifier.
|
| - if (isNonFactoryConstructor) {
|
| - if (modifiers.isStatic()) {
|
| - resolutionError(method.getName(), ResolverErrorCode.CONSTRUCTOR_CANNOT_BE_STATIC);
|
| - }
|
| - if (modifiers.isAbstract()) {
|
| - resolutionError(method.getName(), ResolverErrorCode.CONSTRUCTOR_CANNOT_BE_ABSTRACT);
|
| - }
|
| - if (modifiers.isConstant()) {
|
| - // Allow const ... native ... ; type of constructors. Used in core libraries.
|
| - DartBlock dartBlock = method.getFunction().getBody();
|
| - if (dartBlock != null && !(dartBlock instanceof DartNativeBlock)) {
|
| - resolutionError(method.getName(),
|
| - ResolverErrorCode.CONST_CONSTRUCTOR_CANNOT_HAVE_BODY);
|
| - }
|
| - }
|
| - }
|
| -
|
| - if (modifiers.isFactory()) {
|
| - if (modifiers.isConstant()) {
|
| - // Allow const factory ... native ... ; type of constructors, used in core libraries.
|
| - // Allow const factory redirecting.
|
| - DartBlock dartBlock = method.getFunction().getBody();
|
| - if (!(dartBlock instanceof DartNativeBlock || method.getRedirectedTypeName() != null)) {
|
| - resolutionError(method.getName(), ResolverErrorCode.FACTORY_CANNOT_BE_CONST);
|
| - }
|
| - }
|
| - }
|
| - // TODO(ngeoffray): Add more checks on the modifiers. For
|
| - // example const and missing body.
|
| - }
|
| -
|
| - private void checkConstructor(MethodElement element, DartMethodDefinition method) {
|
| - if (Elements.isNonFactoryConstructor(element) && method.getFunction() != null
|
| - && method.getFunction().getReturnTypeNode() != null) {
|
| - resolutionError(method.getFunction().getReturnTypeNode(),
|
| - ResolverErrorCode.CONSTRUCTOR_CANNOT_HAVE_RETURN_TYPE);
|
| - }
|
| - }
|
| -
|
| - private void checkMemberNameNotSameAsEnclosingClassName(EnclosingElement holder, Element e) {
|
| - if (ElementKind.of(holder) == ElementKind.CLASS) {
|
| - if (Objects.equal(holder.getName(), e.getName())) {
|
| - resolutionError(e.getNameLocation(), ResolverErrorCode.MEMBER_WITH_NAME_OF_CLASS);
|
| - }
|
| - }
|
| - }
|
| -
|
| - private void checkUniqueName(EnclosingElement holder, Element e) {
|
| - if (ElementKind.of(holder) == ElementKind.LIBRARY) {
|
| - return;
|
| - }
|
| - Element other = lookupElementByName(holder, e.getName(), e.getModifiers());
|
| - assert e != other : "forgot to call checkUniqueName() before adding to the class?";
|
| -
|
| - if (other == null && e instanceof FieldElement) {
|
| - FieldElement eField = (FieldElement) e;
|
| - if (!eField.getModifiers().isAbstractField()) {
|
| - other = lookupElementByName(holder, "setter " + e.getName(), e.getModifiers());
|
| - }
|
| - if (eField.getModifiers().isAbstractField()
|
| - && StringUtils.startsWith(e.getName(), "setter ")) {
|
| - Element other2 = lookupElementByName(holder,
|
| - StringUtils.removeStart(e.getName(), "setter "), e.getModifiers());
|
| - if (other2 instanceof FieldElement) {
|
| - FieldElement otherField = (FieldElement) other2;
|
| - if (!otherField.getModifiers().isAbstractField()) {
|
| - other = otherField;
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - if (other != null) {
|
| - ElementKind eKind = ElementKind.of(e);
|
| - ElementKind oKind = ElementKind.of(other);
|
| -
|
| - // Constructors have a separate namespace.
|
| - boolean oIsConstructor = oKind.equals(ElementKind.CONSTRUCTOR);
|
| - boolean eIsConstructor = eKind.equals(ElementKind.CONSTRUCTOR);
|
| - if (oIsConstructor != eIsConstructor) {
|
| - return;
|
| - }
|
| -
|
| - // Both can be constructors, as long as they're for different classes.
|
| - if (oIsConstructor && eIsConstructor) {
|
| - if (((ConstructorElement) e).getConstructorType() !=
|
| - ((ConstructorElement) other).getConstructorType()) {
|
| - return;
|
| - }
|
| - }
|
| -
|
| - boolean eIsOperator = e.getModifiers().isOperator();
|
| - boolean oIsOperator = other.getModifiers().isOperator();
|
| - if (oIsOperator != eIsOperator) {
|
| - return;
|
| - }
|
| -
|
| - // Operators and methods can share the same name.
|
| - boolean oIsMethod = oKind.equals(ElementKind.METHOD);
|
| - boolean eIsMethod = eKind.equals(ElementKind.METHOD);
|
| - if ((oIsOperator && eIsMethod) || (oIsMethod && eIsOperator)) {
|
| - return;
|
| - }
|
| -
|
| - // Report initial declaration and current declaration.
|
| - reportDuplicateDeclaration(ResolverErrorCode.DUPLICATE_MEMBER, other);
|
| - reportDuplicateDeclaration(ResolverErrorCode.DUPLICATE_MEMBER, e);
|
| - }
|
| - }
|
| -
|
| - private Element lookupElementByName(EnclosingElement holder, String name, Modifiers modifiers) {
|
| - Element element = holder.lookupLocalElement(name);
|
| - if (element == null && ElementKind.of(holder).equals(ElementKind.CLASS)) {
|
| - ClassElement cls = (ClassElement) holder;
|
| - String ctorName = name.equals(holder.getName()) ? "" : name;
|
| - for (Element e : cls.getConstructors()) {
|
| - if (e.getName().equals(ctorName)) {
|
| - return e;
|
| - }
|
| - }
|
| - }
|
| - return element;
|
| - }
|
| -
|
| - void resolutionError(HasSourceInfo node, ErrorCode errorCode, Object... arguments) {
|
| - resolutionError(node.getSourceInfo(), errorCode, arguments);
|
| - }
|
| -
|
| - void resolutionError(SourceInfo sourceInfo, ErrorCode errorCode, Object... arguments) {
|
| - topLevelContext.onError(sourceInfo, errorCode, arguments);
|
| - }
|
| -
|
| - /**
|
| - * Reports duplicate declaration for given named element.
|
| - */
|
| - private void reportDuplicateDeclaration(ErrorCode errorCode, Element element) {
|
| - String name =
|
| - element instanceof MethodElement
|
| - ? Elements.getRawMethodName((MethodElement) element)
|
| - : element.getName();
|
| - resolutionError(element.getNameLocation(), errorCode, name);
|
| - }
|
| - }
|
| -}
|
|
|