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

Unified Diff: compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java

Issue 8728001: Support for 'abstract' modifier for class and spec recommended warnings, issue 375 (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Merge. Warning for factory constructor of abstract class. Created 9 years 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 side-by-side diff with in-line comments
Download patch
Index: compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
diff --git a/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java b/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
index 6ec0645eee0e00113015e07b0d74953b949fba3c..cb3b360b243223821d7f7ebe3d35926c89c213fe 100644
--- a/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
+++ b/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
@@ -6,6 +6,7 @@ package com.google.dart.compiler.type;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
+import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Multimap;
import com.google.dart.compiler.DartCompilationError;
@@ -165,7 +166,6 @@ public class TypeAnalyzer implements DartCompilationPhase {
private Type expected;
private InterfaceType currentClass;
private final ConcurrentHashMap<ClassElement, List<Element>> unimplementedElements;
- private final Set<ClassElement> diagnosedAbstractClasses;
private final InterfaceType boolType;
private final InterfaceType numType;
private final InterfaceType intType;
@@ -185,7 +185,6 @@ public class TypeAnalyzer implements DartCompilationPhase {
Set<ClassElement> diagnosedAbstractClasses) {
this.context = context;
this.unimplementedElements = unimplementedElements;
- this.diagnosedAbstractClasses = diagnosedAbstractClasses;
this.types = Types.getInstance(typeProvider);
this.dynamicType = typeProvider.getDynamicType();
this.stringType = typeProvider.getStringType();
@@ -729,6 +728,20 @@ public class TypeAnalyzer implements DartCompilationPhase {
}
visit(node.getMembers());
checkInterfaceConstructors(element);
+ // Report unimplemented members.
+ if (!node.isAbstract()) {
+ ClassElement cls = node.getSymbol();
+ List<Element> unimplementedMembers = findUnimplementedMembers(cls);
+ if (unimplementedMembers.size() > 0) {
+ StringBuilder sb = getUnimplementedMembersMessage(cls, unimplementedMembers);
+ typeError(
+ node.getName(),
+ TypeErrorCode.ABSTRACT_CLASS_WITHOUT_ABSTRACT_MODIFIER,
+ cls.getName(),
+ sb);
+ }
+ }
+ // Finish current class.
setCurrentClass(null);
return type;
}
@@ -1027,58 +1040,39 @@ public class TypeAnalyzer implements DartCompilationPhase {
@Override
public Type visitNewExpression(DartNewExpression node) {
- ConstructorElement element = node.getSymbol();
- node.setReferencedElement(element);
+ ConstructorElement constructorElement = node.getSymbol();
+ node.setReferencedElement(constructorElement);
DartTypeNode typeNode = Types.constructorTypeNode(node);
DartNode typeName = typeNode.getIdentifier();
Type type = validateTypeNode(typeNode, true);
- if (element == null) {
+ if (constructorElement == null) {
visit(node.getArgs());
} else {
- ClassElement cls = (ClassElement) element.getEnclosingElement();
-
- List<Element> unimplementedMembers = findUnimplementedMembers(cls);
- if (unimplementedMembers.size() > 0) {
- if (diagnosedAbstractClasses.add(cls)) {
- StringBuilder sb = new StringBuilder();
- for (Element member : unimplementedMembers) {
- sb.append("\n # From ");
- ClassElement enclosingElement = (ClassElement) member.getEnclosingElement();
- InterfaceType instance = types.asInstanceOf(cls.getType(), enclosingElement);
- Type memberType = member.getType().subst(instance.getArguments(),
- enclosingElement.getTypeParameters());
- sb.append(enclosingElement.getName());
- sb.append(":\n ");
- if (memberType.getKind().equals(TypeKind.FUNCTION)) {
- FunctionType ftype = (FunctionType) memberType;
- sb.append(ftype.getReturnType());
- sb.append(" ");
- sb.append(member.getName());
- String string = ftype.toString();
- sb.append(string, 0, string.lastIndexOf(" -> "));
- } else {
- sb.append(memberType);
- sb.append(" ");
- sb.append(member.getName());
- }
- }
- DartNode clsNode = cls.getNode();
- if (clsNode != null) {
- typeError(typeName, TypeErrorCode.CANNOT_INSTATIATE_ABSTRACT_CLASS, cls.getName());
- typeError(clsNode, TypeErrorCode.ABSTRACT_CLASS, cls.getName(), sb);
- } else {
- typeError(typeName, TypeErrorCode.ABSTRACT_CLASS, cls.getName(), sb);
- }
- } else {
- typeError(typeName, TypeErrorCode.CANNOT_INSTATIATE_ABSTRACT_CLASS, cls.getName());
+ ClassElement cls = (ClassElement) constructorElement.getEnclosingElement();
+ // Add warning for instantiating abstract class.
+ if (cls.isAbstract()) {
+ ErrorCode errorCode =
+ constructorElement.getModifiers().isFactory()
+ ? TypeErrorCode.INSTANTIATION_OF_ABSTRACT_CLASS_USING_FACTORY
+ : TypeErrorCode.INSTANTIATION_OF_ABSTRACT_CLASS;
+ typeError(typeName, errorCode, cls.getName());
+ } else {
+ List<Element> unimplementedMembers = findUnimplementedMembers(cls);
+ if (unimplementedMembers.size() > 0) {
+ StringBuilder sb = getUnimplementedMembersMessage(cls, unimplementedMembers);
+ typeError(
+ typeName,
+ TypeErrorCode.INSTANTIATION_OF_CLASS_WITH_UNIMPLEMENTED_MEMBERS,
+ cls.getName(),
+ sb);
}
}
- FunctionType ftype = (FunctionType) element.getType();
- if (TypeKind.of(type).equals(TypeKind.INTERFACE)) {
- InterfaceType ifaceType = (InterfaceType)type;
+ // Check type arguments.
+ FunctionType ftype = (FunctionType) constructorElement.getType();
+ if (ftype != null && TypeKind.of(type).equals(TypeKind.INTERFACE)) {
+ InterfaceType ifaceType = (InterfaceType) type;
List<? extends Type> arguments = ifaceType.getArguments();
- ftype = (FunctionType) ftype.subst(arguments,
- ifaceType.getElement().getTypeParameters());
+ ftype = (FunctionType) ftype.subst(arguments, ifaceType.getElement().getTypeParameters());
List<TypeVariable> typeVariables = ftype.getTypeVariables();
if (arguments.size() == typeVariables.size()) {
ftype = (FunctionType) ftype.subst(arguments, typeVariables);
@@ -1089,6 +1083,51 @@ public class TypeAnalyzer implements DartCompilationPhase {
return type;
}
+ /**
+ * @param cls the {@link ClassElement} which has unimplemented members.
+ * @param unimplementedMembers the unimplemented members {@link Element}s.
+ * @return the {@link StringBuilder} with message about unimplemented members.
+ */
+ private StringBuilder getUnimplementedMembersMessage(ClassElement cls,
+ List<Element> unimplementedMembers) {
+ // Prepare groups of unimplemented members for each type.
+ Multimap<String, String> membersByTypes = ArrayListMultimap.create();
+ for (Element member : unimplementedMembers) {
+ ClassElement enclosingElement = (ClassElement) member.getEnclosingElement();
+ InterfaceType instance = types.asInstanceOf(cls.getType(), enclosingElement);
+ Type memberType = member.getType().subst(instance.getArguments(),
+ enclosingElement.getTypeParameters());
+ if (memberType.getKind().equals(TypeKind.FUNCTION)) {
+ FunctionType ftype = (FunctionType) memberType;
+ StringBuilder sb = new StringBuilder();
+ sb.append(ftype.getReturnType());
+ sb.append(" ");
+ sb.append(member.getName());
+ String string = ftype.toString();
+ sb.append(string, 0, string.lastIndexOf(" -> "));
+ membersByTypes.put(enclosingElement.getName(), sb.toString());
+ } else {
+ StringBuilder sb = new StringBuilder();
+ sb.append(memberType);
+ sb.append(" ");
+ sb.append(member.getName());
+ membersByTypes.put(enclosingElement.getName(), sb.toString());
+ }
+ }
+ // Output unimplemented members with grouping by class.
+ StringBuilder sb = new StringBuilder();
+ for (String typeName : membersByTypes.keySet()) {
+ sb.append("\n # From ");
+ sb.append(typeName);
+ sb.append(":");
+ for (String memberString : membersByTypes.get(typeName)) {
+ sb.append("\n ");
+ sb.append(memberString);
+ }
+ }
+ return sb;
+ }
+
@Override
public Type visitNullLiteral(DartNullLiteral node) {
return nullType;
@@ -1555,7 +1594,9 @@ public class TypeAnalyzer implements DartCompilationPhase {
while (supertype != null) {
ClassElement superclass = supertype.getElement();
for (Element member : superclass.getMembers()) {
- superMembers.removeAll(member.getName());
+ if (!member.getModifiers().isAbstract()) {
+ superMembers.removeAll(member.getName());
+ }
}
supertype = supertype.getElement().getSupertype();
}

Powered by Google App Engine
This is Rietveld 408576698