From fb71f83964a31152abe46e404a6b9d1d6143deb5 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Wed, 16 Mar 2011 16:01:39 +0300 Subject: [PATCH] Redeclarations reported in the editor --- .../org/jetbrains/jet/lang/ErrorHandler.java | 9 ++++++ .../jet/lang/JetSemanticServices.java | 12 ++++--- .../jet/lang/annotations/JetPsiChecker.java | 32 ++++++++++--------- .../jet/lang/resolve/AnalyzingUtils.java | 2 +- .../lang/resolve/ClassDescriptorResolver.java | 6 ++-- .../jet/lang/resolve/JetScopeAdapter.java | 3 +- .../lang/resolve/MutableClassDescriptor.java | 5 +-- .../jet/lang/resolve/TopDownAnalyzer.java | 8 ++--- .../jet/lang/resolve/WritableScope.java | 15 ++++++--- .../jet/lang/types/JetStandardClasses.java | 3 +- .../jet/lang/types/JetTypeChecker.java | 3 +- .../jet/lang/types/JetTypeInferrer.java | 12 +++---- 12 files changed, 67 insertions(+), 43 deletions(-) diff --git a/idea/src/org/jetbrains/jet/lang/ErrorHandler.java b/idea/src/org/jetbrains/jet/lang/ErrorHandler.java index 5b9041b3ae6..02bac1d8126 100644 --- a/idea/src/org/jetbrains/jet/lang/ErrorHandler.java +++ b/idea/src/org/jetbrains/jet/lang/ErrorHandler.java @@ -3,6 +3,7 @@ package org.jetbrains.jet.lang; import com.intellij.lang.ASTNode; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetReferenceExpression; +import org.jetbrains.jet.lang.types.DeclarationDescriptor; import org.jetbrains.jet.lang.types.JetType; /** @@ -25,6 +26,11 @@ public class ErrorHandler { public void typeMismatch(JetExpression expression, JetType expectedType, JetType actualType) { throw new IllegalStateException("Type mismatch: inferred type is " + actualType + " but " + expectedType + " was expected"); } + + @Override + public void redeclaration(DeclarationDescriptor existingDescriptor, DeclarationDescriptor redeclaredDescriptor) { + throw new IllegalStateException("Redeclaration: " + existingDescriptor.getName()); + } }; public void unresolvedReference(JetReferenceExpression referenceExpression) { @@ -35,4 +41,7 @@ public class ErrorHandler { public void typeMismatch(JetExpression expression, JetType expectedType, JetType actualType) { } + + public void redeclaration(DeclarationDescriptor existingDescriptor, DeclarationDescriptor redeclaredDescriptor) { + } } diff --git a/idea/src/org/jetbrains/jet/lang/JetSemanticServices.java b/idea/src/org/jetbrains/jet/lang/JetSemanticServices.java index 27d06c2a0da..91a88bbc399 100644 --- a/idea/src/org/jetbrains/jet/lang/JetSemanticServices.java +++ b/idea/src/org/jetbrains/jet/lang/JetSemanticServices.java @@ -3,11 +3,10 @@ package org.jetbrains.jet.lang; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.resolve.ClassDescriptorResolver; +import org.jetbrains.jet.lang.resolve.JetScope; import org.jetbrains.jet.lang.resolve.OverloadResolver; -import org.jetbrains.jet.lang.types.BindingTrace; -import org.jetbrains.jet.lang.types.JetStandardLibrary; -import org.jetbrains.jet.lang.types.JetTypeChecker; -import org.jetbrains.jet.lang.types.JetTypeInferrer; +import org.jetbrains.jet.lang.resolve.WritableScope; +import org.jetbrains.jet.lang.types.*; /** * @author abreslav @@ -63,4 +62,9 @@ public class JetSemanticServices { public OverloadResolver getOverloadResolver() { return overloadResolver; } + + @NotNull + public WritableScope createWritableScope(@NotNull JetScope scope, @NotNull DeclarationDescriptor owner) { + return new WritableScope(scope, owner, errorHandler); + } } diff --git a/idea/src/org/jetbrains/jet/lang/annotations/JetPsiChecker.java b/idea/src/org/jetbrains/jet/lang/annotations/JetPsiChecker.java index e57f0bd43fd..cd31e59b3f0 100644 --- a/idea/src/org/jetbrains/jet/lang/annotations/JetPsiChecker.java +++ b/idea/src/org/jetbrains/jet/lang/annotations/JetPsiChecker.java @@ -12,11 +12,17 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReference; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.ErrorHandler; -import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.psi.JetExpression; +import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.psi.JetReferenceExpression; import org.jetbrains.jet.lang.resolve.AnalyzingUtils; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.types.DeclarationDescriptor; import org.jetbrains.jet.lang.types.JetType; +import java.util.Collection; +import java.util.HashSet; + /** * @author abreslav */ @@ -29,6 +35,7 @@ public class JetPsiChecker implements Annotator { JetFile file = (JetFile) element; try { + final Collection redeclarations = new HashSet(); final BindingContext bindingContext = AnalyzingUtils.analyzeFile(file, new ErrorHandler() { @Override public void unresolvedReference(JetReferenceExpression referenceExpression) { @@ -52,24 +59,19 @@ public class JetPsiChecker implements Annotator { public void typeMismatch(JetExpression expression, JetType expectedType, JetType actualType) { holder.createErrorAnnotation(expression, "Type mismatch: inferred type is " + actualType + " but " + expectedType + " was expected"); } - }); - file.getRootNamespace().accept(new JetVisitor() { - @Override - public void visitClass(JetClass klass) { - for (JetDelegationSpecifier specifier : klass.getDelegationSpecifiers()) { - JetTypeReference typeReference = specifier.getTypeReference(); - JetType type = bindingContext.resolveTypeReference(typeReference); - holder.createWeakWarningAnnotation(typeReference, type.toString()); - } - } @Override - public void visitNamespace(JetNamespace namespace) { - for (JetDeclaration declaration : namespace.getDeclarations()) { - declaration.accept(this); - } + public void redeclaration(DeclarationDescriptor existingDescriptor, DeclarationDescriptor redeclaredDescriptor) { + redeclarations.add(existingDescriptor); + redeclarations.add(redeclaredDescriptor); } }); + for (DeclarationDescriptor redeclaration : redeclarations) { + PsiElement declarationPsiElement = bindingContext.getDeclarationPsiElement(redeclaration); + if (declarationPsiElement != null) { + holder.createErrorAnnotation(declarationPsiElement, "Redeclaration"); + } + } } catch (ProcessCanceledException e) { throw e; diff --git a/idea/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java b/idea/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java index 6fc53030677..24064d58ce8 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java @@ -27,7 +27,7 @@ public class AnalyzingUtils { JavaSemanticServices javaSemanticServices = new JavaSemanticServices(project, semanticServices, bindingTraceContext); JetScope libraryScope = semanticServices.getStandardLibrary().getLibraryScope(); - WritableScope scope = new WritableScope(libraryScope, new ModuleDescriptor("")); + WritableScope scope = semanticServices.createWritableScope(libraryScope, new ModuleDescriptor("")); // scope.importScope(javaSemanticServices.getDescriptorResolver().resolveNamespace("").getMemberScope()); // scope.importScope(javaSemanticServices.getDescriptorResolver().resolveNamespace("java.lang").getMemberScope()); scope.importScope(new JavaPackageScope("", null, javaSemanticServices)); diff --git a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java index 2f81285e463..8ca4fd6cc08 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java @@ -30,7 +30,7 @@ public class ClassDescriptorResolver { scope.getContainingDeclaration(), AttributeResolver.INSTANCE.resolveAttributes(classElement.getModifierList()), classElement.getName()); - WritableScope parameterScope = new WritableScope(scope, classDescriptor); + WritableScope parameterScope = semanticServices.createWritableScope(scope, classDescriptor); // This call has side-effects on the parameterScope (fills it in) List typeParameters @@ -100,7 +100,7 @@ public class ClassDescriptorResolver { final JetScope typeParameterScope, final Collection supertypes) { - final WritableScope memberDeclarations = new WritableScope(typeParameterScope, classDescriptor); + final WritableScope memberDeclarations = semanticServices.createWritableScope(typeParameterScope, classDescriptor); List declarations = classElement.getDeclarations(); for (JetDeclaration declaration : declarations) { @@ -142,7 +142,7 @@ public class ClassDescriptorResolver { AttributeResolver.INSTANCE.resolveAttributes(function.getModifierList()), function.getName() ); - WritableScope parameterScope = new WritableScope(scope, functionDescriptor); + WritableScope parameterScope = semanticServices.createWritableScope(scope, functionDescriptor); // The two calls below have side-effects on parameterScope List typeParameterDescriptors = resolveTypeParameters(functionDescriptor, parameterScope, function.getTypeParameters()); diff --git a/idea/src/org/jetbrains/jet/lang/resolve/JetScopeAdapter.java b/idea/src/org/jetbrains/jet/lang/resolve/JetScopeAdapter.java index a15ba19313b..8d8b827b4c8 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/JetScopeAdapter.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/JetScopeAdapter.java @@ -7,9 +7,10 @@ import org.jetbrains.jet.lang.types.*; * @author abreslav */ public class JetScopeAdapter implements JetScope { + @NotNull private final JetScope scope; - public JetScopeAdapter(JetScope scope) { + public JetScopeAdapter(@NotNull JetScope scope) { this.scope = scope; } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/MutableClassDescriptor.java b/idea/src/org/jetbrains/jet/lang/resolve/MutableClassDescriptor.java index debec6593d0..9660325cce7 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/MutableClassDescriptor.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/MutableClassDescriptor.java @@ -1,6 +1,7 @@ package org.jetbrains.jet.lang.resolve; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.types.*; import java.util.List; @@ -13,9 +14,9 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme private final WritableScope unsubstitutedMemberScope; private TypeConstructor typeConstructor; - public MutableClassDescriptor(@NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope outerScope) { + public MutableClassDescriptor(@NotNull JetSemanticServices semanticServices, @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope outerScope) { super(containingDeclaration); - this.unsubstitutedMemberScope = new WritableScope(outerScope, this); + this.unsubstitutedMemberScope = semanticServices.createWritableScope(outerScope, this); } @NotNull diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index 9d39dbae2ff..d5caba0ad39 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -32,7 +32,7 @@ public class TopDownAnalyzer { } public void process(@NotNull JetScope outerScope, @NotNull List declarations) { - final WritableScope toplevelScope = new WritableScope(outerScope, outerScope.getContainingDeclaration()); // TODO ?! + final WritableScope toplevelScope = semanticServices.createWritableScope(outerScope, outerScope.getContainingDeclaration()); // TODO ?! trace.setToplevelScope(toplevelScope); // TODO : this is a hack collectTypeDeclarators(toplevelScope, declarations); resolveTypeDeclarations(); @@ -69,7 +69,7 @@ public class TopDownAnalyzer { trace.recordDeclarationResolution(namespace, namespaceDescriptor); } - WritableScope namespaceScope = new WritableScope(declaringScope, namespaceDescriptor); + WritableScope namespaceScope = semanticServices.createWritableScope(declaringScope, namespaceDescriptor); namespaceScopes.put(namespace, namespaceScope); for (JetImportDirective importDirective : importDirectives) { @@ -104,7 +104,7 @@ public class TopDownAnalyzer { } private WritableScope processClass(@NotNull WritableScope declaringScope, JetClass klass) { - MutableClassDescriptor mutableClassDescriptor = new MutableClassDescriptor(declaringScope.getContainingDeclaration(), declaringScope); + MutableClassDescriptor mutableClassDescriptor = new MutableClassDescriptor(semanticServices, declaringScope.getContainingDeclaration(), declaringScope); mutableClassDescriptor.setName(klass.getName()); declaringScope.addClassDescriptor(mutableClassDescriptor); @@ -204,7 +204,7 @@ public class TopDownAnalyzer { WritableScope declaringScope = declaringScopes.get(function); assert declaringScope != null; - WritableScope parameterScope = new WritableScope(declaringScope, descriptor); + WritableScope parameterScope = semanticServices.createWritableScope(declaringScope, descriptor); for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) { parameterScope.addTypeParameterDescriptor(typeParameter); } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/WritableScope.java b/idea/src/org/jetbrains/jet/lang/resolve/WritableScope.java index 24ca04d7c2f..7e55657bcf5 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/WritableScope.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/WritableScope.java @@ -2,6 +2,7 @@ package org.jetbrains.jet.lang.resolve; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.ErrorHandler; import org.jetbrains.jet.lang.types.*; import java.util.ArrayList; @@ -13,6 +14,9 @@ import java.util.Map; * @author abreslav */ public class WritableScope extends JetScopeAdapter { + @NotNull + private final ErrorHandler errorHandler; + @Nullable private Map propertyDescriptors; @Nullable @@ -31,9 +35,10 @@ public class WritableScope extends JetScopeAdapter { @NotNull private final DeclarationDescriptor ownerDeclarationDescriptor; - public WritableScope(JetScope scope, @NotNull DeclarationDescriptor owner) { + public WritableScope(@NotNull JetScope scope, @NotNull DeclarationDescriptor owner, @NotNull ErrorHandler errorHandler) { super(scope); this.ownerDeclarationDescriptor = owner; + this.errorHandler = errorHandler; } @NotNull @@ -42,7 +47,7 @@ public class WritableScope extends JetScopeAdapter { return ownerDeclarationDescriptor; } - public void importScope(JetScope imported) { + public void importScope(@NotNull JetScope imported) { getImports().add(0, imported); } @@ -64,9 +69,11 @@ public class WritableScope extends JetScopeAdapter { public void addPropertyDescriptor(PropertyDescriptor propertyDescriptor) { Map propertyDescriptors = getPropertyDescriptors(); - if (propertyDescriptors.containsKey(propertyDescriptor.getName())) { - throw new UnsupportedOperationException("Property redeclared: " + propertyDescriptor.getName()); + PropertyDescriptor existingDescriptor = propertyDescriptors.get(propertyDescriptor.getName()); + if (existingDescriptor != null) { + errorHandler.redeclaration(existingDescriptor, propertyDescriptor); } + // TODO : Should this always happen? propertyDescriptors.put(propertyDescriptor.getName(), propertyDescriptor); } diff --git a/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java b/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java index d62838843ce..ff4fac927e6 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java @@ -2,6 +2,7 @@ package org.jetbrains.jet.lang.types; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.ErrorHandler; import org.jetbrains.jet.lang.resolve.JetScope; import org.jetbrains.jet.lang.resolve.WritableScope; @@ -160,7 +161,7 @@ public class JetStandardClasses { /*package*/ static final JetScope STANDARD_CLASSES; static { - WritableScope writableScope = new WritableScope(JetScope.EMPTY, STANDARD_CLASSES_NAMESPACE); + WritableScope writableScope = new WritableScope(JetScope.EMPTY, STANDARD_CLASSES_NAMESPACE, ErrorHandler.DO_NOTHING); STANDARD_CLASSES = writableScope; writableScope.addClassAlias("Unit", getTuple(0)); diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java index d3ceea6aa68..4e9d892fa0d 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java @@ -2,7 +2,6 @@ package org.jetbrains.jet.lang.types; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.psi.JetExpression; import java.util.*; @@ -274,7 +273,7 @@ public class JetTypeChecker { handler.afterChildren(current); } - public boolean isConvertibleTo(JetType actual, JetType expected) { + public boolean isConvertibleTo(@NotNull JetType actual, @NotNull JetType expected) { if (isSubtypeOf(actual, expected)) return true; if (expected.getConstructor().equals(JetStandardClasses.getTuple(0).getTypeConstructor())) { return true; diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index ef8e5da8095..b53d9345025 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -25,7 +25,7 @@ public class JetTypeInferrer { this.trace = trace; this.semanticServices = semanticServices; this.typeResolver = new TypeResolver(trace, semanticServices); - this.classDescriptorResolver = new ClassDescriptorResolver(semanticServices, trace); + this.classDescriptorResolver = semanticServices.getClassDescriptorResolver(trace); } @NotNull @@ -168,7 +168,7 @@ public class JetTypeInferrer { return JetStandardClasses.getUnitType(); } else { DeclarationDescriptor containingDescriptor = outerScope.getContainingDeclaration(); - WritableScope scope = new WritableScope(outerScope, containingDescriptor); + WritableScope scope = semanticServices.createWritableScope(outerScope, containingDescriptor); for (JetElement statement : block) { // TODO: consider other declarations if (statement instanceof JetProperty) { @@ -181,7 +181,7 @@ public class JetTypeInferrer { getType(scope, (JetExpression) statement, true); } else { - throw new UnsupportedOperationException(); // TODO + throw new UnsupportedOperationException(statement.getClass().getCanonicalName()); // TODO } } JetElement lastElement = block.get(block.size() - 1); @@ -278,7 +278,7 @@ public class JetTypeInferrer { if (returnTypeRef != null) { returnType = typeResolver.resolveType(scope, returnTypeRef); } else { - WritableScope writableScope = new WritableScope(scope, functionDescriptor); + WritableScope writableScope = semanticServices.createWritableScope(scope, functionDescriptor); for (PropertyDescriptor propertyDescriptor : parameterDescriptors.values()) { writableScope.addPropertyDescriptor(propertyDescriptor); } @@ -689,8 +689,8 @@ public class JetTypeInferrer { } private JetType getTypeForBinaryCall(JetScope scope, JetExpression left, JetSimpleNameExpression operationSign, @NotNull JetExpression right, String name, boolean reportUnresolved) { - JetType leftType = getType(scope, left, false); - JetType rightType = getType(scope, right, false); + JetType leftType = safeGetType(scope, left, false); + JetType rightType = safeGetType(scope, right, false); FunctionDescriptor functionDescriptor = lookupFunction(scope, operationSign, name, leftType, Collections.singletonList(rightType), reportUnresolved); if (functionDescriptor != null) { return functionDescriptor.getUnsubstitutedReturnType();