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

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

Issue 9296016: Issue 1251. Check for getter existence. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Test for chained invocation before field access Created 8 years, 11 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 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 9e4eac4771a8a9ce46700e0e7ec7999fc0d56d44..417ac1e075925967e6a33382614b8e70d63f622c 100644
--- a/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
+++ b/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
@@ -7,6 +7,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.ImmutableSet;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
@@ -124,6 +125,20 @@ import java.util.concurrent.ConcurrentHashMap;
* Analyzer of static type information.
*/
public class TypeAnalyzer implements DartCompilationPhase {
+ private static final ImmutableSet<Token> ASSIGN_OPERATORS =
+ Sets.immutableEnumSet(
+ Token.ASSIGN,
+ Token.ASSIGN_BIT_OR,
+ Token.ASSIGN_BIT_XOR,
+ Token.ASSIGN_BIT_AND,
+ Token.ASSIGN_SHL,
+ Token.ASSIGN_SAR,
+ Token.ASSIGN_ADD,
+ Token.ASSIGN_SUB,
+ Token.ASSIGN_MUL,
+ Token.ASSIGN_DIV,
+ Token.ASSIGN_MOD,
+ Token.ASSIGN_TRUNC);
private final ConcurrentHashMap<ClassElement, List<Element>> unimplementedElements =
new ConcurrentHashMap<ClassElement, List<Element>>();
private final Set<ClassElement> diagnosedAbstractClasses =
@@ -1298,7 +1313,36 @@ public class TypeAnalyzer implements DartCompilationPhase {
name, element.getName());
case METHOD:
+ return member.getType();
+
case FIELD:
+ FieldElement fieldElement = (FieldElement) element;
+ // Check for cases when property has no setter or getter.
+ if (fieldElement.getModifiers().isAbstractField()
+ && fieldElement.getEnclosingElement() instanceof ClassElement) {
+ ClassElement enclosingClass = (ClassElement) fieldElement.getEnclosingElement();
+ // Check for using field without getter in other operation that assignment.
+ if (fieldElement.getGetter() == null && !hasFieldElementGetter(enclosingClass, name)) {
+ if (!(node.getParent() instanceof DartBinaryExpression)
+ || ((DartBinaryExpression) node.getParent()).getOperator() != Token.ASSIGN
+ || ((DartBinaryExpression) node.getParent()).getArg1() != node) {
+ return typeError(node.getName(), TypeErrorCode.FIELD_HAS_NO_GETTER, node.getName());
+ }
+ }
+ // Check for using field without setter in some assignment variant.
+ if (fieldElement.getSetter() == null && !hasFieldElementSetter(enclosingClass, name)) {
+ if (node.getParent() instanceof DartBinaryExpression) {
+ DartBinaryExpression expr = (DartBinaryExpression) node.getParent();
+ if (ASSIGN_OPERATORS.contains(expr.getOperator()) && expr.getArg1() == node) {
+ return typeError(
+ node.getName(),
+ TypeErrorCode.FIELD_HAS_NO_SETTER,
+ node.getName());
+ }
+ }
+ }
+ }
+ // Return field type.
return member.getType();
default:
@@ -1306,6 +1350,52 @@ public class TypeAnalyzer implements DartCompilationPhase {
}
}
+ /**
+ * @return <code>true</code> if "holder", or one of its interfaces, or its superclass has
+ * {@link FieldElement} with getter.
+ */
+ private static boolean hasFieldElementGetter(ClassElement holder, String name) {
+ Element element = holder.lookupLocalElement(name);
+ if (element instanceof FieldElement) {
+ FieldElement fieldElement = (FieldElement) element;
+ if (fieldElement.getGetter() != null) {
+ return true;
+ }
+ }
+ for (InterfaceType interfaceType : holder.getInterfaces()) {
+ if (hasFieldElementGetter(interfaceType.getElement(), name)) {
+ return true;
+ }
+ }
+ if (holder.getSupertype() != null) {
+ return hasFieldElementGetter(holder.getSupertype().getElement(), name);
+ }
+ return false;
+ }
+
+ /**
+ * @return <code>true</code> if "holder", or one of its interfaces, or its superclass has
+ * {@link FieldElement} with setter.
+ */
+ private static boolean hasFieldElementSetter(ClassElement holder, String name) {
+ Element element = holder.lookupLocalElement(name);
+ if (element instanceof FieldElement) {
+ FieldElement fieldElement = (FieldElement) element;
+ if (fieldElement.getSetter() != null) {
+ return true;
+ }
+ }
+ for (InterfaceType interfaceType : holder.getInterfaces()) {
+ if (hasFieldElementSetter(interfaceType.getElement(), name)) {
+ return true;
+ }
+ }
+ if (holder.getSupertype() != null) {
+ return hasFieldElementSetter(holder.getSupertype().getElement(), name);
+ }
+ return false;
+ }
+
@Override
public Type visitReturnStatement(DartReturnStatement node) {
DartExpression value = node.getValue();

Powered by Google App Engine
This is Rietveld 408576698