blob: 74ca6091506ce87c623bb0ff3129ab60284741c1 [file] [log] [blame]
// 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.collect.ImmutableSet;
import com.google.dart.compiler.ast.DartBlock;
import com.google.dart.compiler.ast.DartClass;
import com.google.dart.compiler.ast.DartFunctionExpression;
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.DartObsoleteMetadata;
import com.google.dart.compiler.ast.Modifiers;
import com.google.dart.compiler.common.SourceInfo;
import com.google.dart.compiler.type.FunctionType;
import com.google.dart.compiler.type.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
class MethodElementImplementation extends AbstractNodeElement implements MethodNodeElement {
private final DartObsoleteMetadata metadata;
private final Modifiers modifiers;
private final EnclosingElement holder;
private final ElementKind kind;
private final List<VariableElement> parameters = new ArrayList<VariableElement>();
private FunctionType type;
private final SourceInfo nameLocation;
private final boolean hasBody;
private Set<Element> overridden = ImmutableSet.of();
// TODO(ngeoffray): name, return type, argument types.
@VisibleForTesting
MethodElementImplementation(DartFunctionExpression node, String name, Modifiers modifiers) {
super(node, name);
this.metadata = DartObsoleteMetadata.EMPTY;
this.modifiers = modifiers;
this.hasBody = true;
this.holder = findParentEnclosingElement(node);
this.kind = ElementKind.FUNCTION_OBJECT;
if (node != null && node.getName() != null) {
this.nameLocation = node.getName().getSourceInfo();
} else {
this.nameLocation = SourceInfo.UNKNOWN;
}
}
protected MethodElementImplementation(DartMethodDefinition node, String name,
EnclosingElement holder) {
super(node, name);
if (node != null) {
this.metadata = node.getObsoleteMetadata();
this.modifiers = node.getModifiers();
this.nameLocation = node.getName().getSourceInfo();
DartBlock body = node.getFunction().getBody();
this.hasBody = body != null && !(body instanceof DartNativeBlock);
} else {
this.metadata = DartObsoleteMetadata.EMPTY;
this.modifiers = Modifiers.NONE;
this.nameLocation = SourceInfo.UNKNOWN;
this.hasBody = false;
}
this.holder = holder;
this.kind = ElementKind.METHOD;
}
@Override
public DartObsoleteMetadata getMetadata() {
return metadata;
}
@Override
public Modifiers getModifiers() {
return modifiers;
}
@Override
public ElementKind getKind() {
return kind;
}
@Override
public EnclosingElement getEnclosingElement() {
return holder;
}
@Override
public boolean isConstructor() {
return false;
}
@Override
public boolean isStatic() {
return getModifiers().isStatic();
}
@Override
public List<VariableElement> getParameters() {
return parameters;
}
@Override
public boolean hasBody() {
return hasBody;
}
void addParameter(VariableElement parameter) {
parameters.add(parameter);
}
@Override
public Type getReturnType() {
return getType().getReturnType();
}
@Override
void setType(Type type) {
this.type = (FunctionType) type;
}
@Override
public FunctionType getType() {
return type;
}
@Override
public FunctionType getFunctionType() {
return getType();
}
@Override
public boolean isInterface() {
return false;
}
@Override
public Iterable<Element> getMembers() {
return Collections.emptyList();
}
@Override
public Element lookupLocalElement(String name) {
return null;
}
public static MethodElementImplementation fromMethodNode(DartMethodDefinition node,
EnclosingElement holder) {
String targetName;
if(node.getName() instanceof DartIdentifier) {
targetName = ((DartIdentifier) node.getName()).getName();
if (targetName.equals("-") && node.getFunction().getParameters().size() == 1) {
targetName += "binary";
}
} else {
// Visit the unknown node to generate a string for our use.
targetName = node.toSource();
}
return new MethodElementImplementation(node, targetName, holder);
}
public static MethodElementImplementation fromFunctionExpression(DartFunctionExpression node,
Modifiers modifiers) {
return new MethodElementImplementation(node, node.getFunctionName(), modifiers);
}
/**
* @return the innermost {@link EnclosingElement} for given {@link DartNode}, may be
* <code>null</code>.
*/
private static EnclosingElement findParentEnclosingElement(DartNode node) {
while (node != null && node.getParent() != null) {
node = node.getParent();
boolean isEnclosingNode = node instanceof DartClass || node instanceof DartMethodDefinition
|| node instanceof DartFunctionExpression;
if (isEnclosingNode && node.getElement() instanceof EnclosingElement) {
return (EnclosingElement) node.getElement();
}
}
return null;
}
@Override
public SourceInfo getNameLocation() {
return nameLocation;
}
public void setOverridden(Set<Element> overridden) {
this.overridden = overridden;
}
public Set<Element> getOverridden() {
return overridden;
}
}