sometimes it not permitted to redeclare variable in nested scope (KT-527)

This commit is contained in:
Stepan Koltsov
2011-11-28 17:54:50 +04:00
parent 709e4b3561
commit a9a07857de
14 changed files with 112 additions and 12 deletions
@@ -44,7 +44,10 @@ public interface Errors {
} }
}; };
UnresolvedReferenceDiagnosticFactory UNRESOLVED_REFERENCE = new UnresolvedReferenceDiagnosticFactory("Unresolved reference"); UnresolvedReferenceDiagnosticFactory UNRESOLVED_REFERENCE = new UnresolvedReferenceDiagnosticFactory("Unresolved reference");
RedeclarationDiagnosticFactory REDECLARATION = RedeclarationDiagnosticFactory.INSTANCE;
RedeclarationDiagnosticFactory REDECLARATION = RedeclarationDiagnosticFactory.REDECLARATION;
RedeclarationDiagnosticFactory NAME_SHADOWING = RedeclarationDiagnosticFactory.NAME_SHADOWING;
PsiElementOnlyDiagnosticFactory2<PsiElement, JetType, JetType> TYPE_MISMATCH = PsiElementOnlyDiagnosticFactory2.create(ERROR, "Type mismatch: inferred type is {1} but {0} was expected"); PsiElementOnlyDiagnosticFactory2<PsiElement, JetType, JetType> TYPE_MISMATCH = PsiElementOnlyDiagnosticFactory2.create(ERROR, "Type mismatch: inferred type is {1} but {0} was expected");
ParameterizedDiagnosticFactory1<Collection<JetKeywordToken>> INCOMPATIBLE_MODIFIERS = new ParameterizedDiagnosticFactory1<Collection<JetKeywordToken>>(ERROR, "Incompatible modifiers: ''{0}''") { ParameterizedDiagnosticFactory1<Collection<JetKeywordToken>> INCOMPATIBLE_MODIFIERS = new ParameterizedDiagnosticFactory1<Collection<JetKeywordToken>>(ERROR, "Incompatible modifiers: ''{0}''") {
@Override @Override
@@ -15,8 +15,8 @@ import static org.jetbrains.jet.lang.diagnostics.Severity.ERROR;
public interface RedeclarationDiagnostic extends DiagnosticWithPsiElement<PsiElement> { public interface RedeclarationDiagnostic extends DiagnosticWithPsiElement<PsiElement> {
public class SimpleRedeclarationDiagnostic extends DiagnosticWithPsiElementImpl<PsiElement> implements RedeclarationDiagnostic { public class SimpleRedeclarationDiagnostic extends DiagnosticWithPsiElementImpl<PsiElement> implements RedeclarationDiagnostic {
public SimpleRedeclarationDiagnostic(@NotNull PsiElement psiElement, @NotNull String name) { public SimpleRedeclarationDiagnostic(@NotNull PsiElement psiElement, @NotNull String name, RedeclarationDiagnosticFactory factory) {
super(RedeclarationDiagnosticFactory.INSTANCE, ERROR, "Redeclaration: " + name, psiElement); super(factory, factory.severity, factory.makeMessage(name), psiElement);
} }
} }
@@ -24,11 +24,13 @@ public interface RedeclarationDiagnostic extends DiagnosticWithPsiElement<PsiEle
private final DeclarationDescriptor duplicatingDescriptor; private final DeclarationDescriptor duplicatingDescriptor;
private final BindingContext contextToResolveToDeclaration; private final BindingContext contextToResolveToDeclaration;
private final RedeclarationDiagnosticFactory factory;
private PsiElement element; private PsiElement element;
public RedeclarationDiagnosticWithDeferredResolution(@NotNull DeclarationDescriptor duplicatingDescriptor, @NotNull BindingContext contextToResolveToDeclaration) { public RedeclarationDiagnosticWithDeferredResolution(@NotNull DeclarationDescriptor duplicatingDescriptor, @NotNull BindingContext contextToResolveToDeclaration, RedeclarationDiagnosticFactory factory) {
this.duplicatingDescriptor = duplicatingDescriptor; this.duplicatingDescriptor = duplicatingDescriptor;
this.contextToResolveToDeclaration = contextToResolveToDeclaration; this.contextToResolveToDeclaration = contextToResolveToDeclaration;
this.factory = factory;
} }
private PsiElement resolve() { private PsiElement resolve() {
@@ -60,19 +62,19 @@ public interface RedeclarationDiagnostic extends DiagnosticWithPsiElement<PsiEle
@NotNull @NotNull
@Override @Override
public DiagnosticFactory getFactory() { public DiagnosticFactory getFactory() {
return Errors.REDECLARATION; return factory;
} }
@NotNull @NotNull
@Override @Override
public String getMessage() { public String getMessage() {
return "Redeclaration: " + duplicatingDescriptor.getName(); return factory.makeMessage(duplicatingDescriptor.getName());
} }
@NotNull @NotNull
@Override @Override
public Severity getSeverity() { public Severity getSeverity() {
return ERROR; return factory.severity;
} }
@Override @Override
@@ -12,16 +12,27 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
*/ */
public class RedeclarationDiagnosticFactory extends AbstractDiagnosticFactory { public class RedeclarationDiagnosticFactory extends AbstractDiagnosticFactory {
public static final RedeclarationDiagnosticFactory INSTANCE = new RedeclarationDiagnosticFactory(); private final String name;
final Severity severity;
private final String messagePrefix;
public RedeclarationDiagnosticFactory() {} public static final RedeclarationDiagnosticFactory REDECLARATION = new RedeclarationDiagnosticFactory(
"REDECLARATION", Severity.ERROR, "Redeclaration: ");
public static final RedeclarationDiagnosticFactory NAME_SHADOWING = new RedeclarationDiagnosticFactory(
"NAME_SHADOWING", Severity.WARNING, "Name shadowed: ");
public RedeclarationDiagnosticFactory(String name, Severity severity, String messagePrefix) {
this.name = name;
this.severity = severity;
this.messagePrefix = messagePrefix;
}
public RedeclarationDiagnostic on(@NotNull PsiElement duplicatingElement, @NotNull String name) { public RedeclarationDiagnostic on(@NotNull PsiElement duplicatingElement, @NotNull String name) {
return new RedeclarationDiagnostic.SimpleRedeclarationDiagnostic(duplicatingElement, name); return new RedeclarationDiagnostic.SimpleRedeclarationDiagnostic(duplicatingElement, name, this);
} }
public Diagnostic on(DeclarationDescriptor duplicatingDescriptor, BindingContext contextToResolveToDeclaration) { public Diagnostic on(DeclarationDescriptor duplicatingDescriptor, BindingContext contextToResolveToDeclaration) {
return new RedeclarationDiagnostic.RedeclarationDiagnosticWithDeferredResolution(duplicatingDescriptor, contextToResolveToDeclaration); return new RedeclarationDiagnostic.RedeclarationDiagnosticWithDeferredResolution(duplicatingDescriptor, contextToResolveToDeclaration, this);
} }
@NotNull @NotNull
@@ -40,7 +51,11 @@ public class RedeclarationDiagnosticFactory extends AbstractDiagnosticFactory {
@NotNull @NotNull
@Override @Override
public String getName() { public String getName() {
return "REDECLARATION"; return name;
}
public String makeMessage(String identifier) {
return messagePrefix + identifier;
} }
@Override @Override
@@ -6,9 +6,12 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.calls.TaskPrioritizers;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults; import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
@@ -211,6 +214,16 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
} }
variableDescriptor = context.getDescriptorResolver().resolveLocalVariableDescriptor(context.scope.getContainingDeclaration(), loopParameter, expectedParameterType); variableDescriptor = context.getDescriptorResolver().resolveLocalVariableDescriptor(context.scope.getContainingDeclaration(), loopParameter, expectedParameterType);
} }
{
// http://youtrack.jetbrains.net/issue/KT-527
VariableDescriptor olderVariable = context.scope.getVariable(variableDescriptor.getName());
if (olderVariable != null && DescriptorUtils.isLocal(context.scope.getContainingDeclaration(), olderVariable)) {
context.trace.report(Errors.NAME_SHADOWING.on(variableDescriptor, context.trace.getBindingContext()));
}
}
loopScope.addVariableDescriptor(variableDescriptor); loopScope.addVariableDescriptor(variableDescriptor);
} }
@@ -7,6 +7,7 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.diagnostics.Errors; import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace; import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
import org.jetbrains.jet.lang.resolve.TopDownAnalyzer; import org.jetbrains.jet.lang.resolve.TopDownAnalyzer;
import org.jetbrains.jet.lang.resolve.calls.CallMaker; import org.jetbrains.jet.lang.resolve.calls.CallMaker;
@@ -90,6 +91,13 @@ public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingV
JetType initializerType = facade.getType(initializer, context.replaceExpectedType(outType).replaceScope(scope)); JetType initializerType = facade.getType(initializer, context.replaceExpectedType(outType).replaceScope(scope));
} }
{
VariableDescriptor olderVariable = scope.getVariable(propertyDescriptor.getName());
if (olderVariable != null && DescriptorUtils.isLocal(propertyDescriptor.getContainingDeclaration(), olderVariable)) {
context.trace.report(Errors.NAME_SHADOWING.on(propertyDescriptor, context.trace.getBindingContext()));
}
}
scope.addVariableDescriptor(propertyDescriptor); scope.addVariableDescriptor(propertyDescriptor);
return checkExpectedType(property, context); return checkExpectedType(property, context);
} }
@@ -0,0 +1,5 @@
fun f(p: Int): Int {
val <!NAME_SHADOWING!>p<!> = 2
return p
}
@@ -0,0 +1,7 @@
fun f(i: Int) {
for (j in 1..100) {
{
var <!NAME_SHADOWING!>i<!> = 12
}
}
}
@@ -0,0 +1,3 @@
val i = 17
val f = { (): Int => var i = 17; i }
@@ -0,0 +1,11 @@
class RedefinePropertyInFor() {
var i = 1
fun ff() {
for (i in 0..10) {
}
}
}
@@ -0,0 +1,10 @@
class RedefinePropertyInFunction() {
var i = 17
fun f(): Int {
var i = 18
return i
}
}
@@ -0,0 +1,6 @@
fun ff(): Int {
var i = 1
for (<!NAME_SHADOWING!>i<!> in 0..10) {
}
return i
}
@@ -0,0 +1,7 @@
fun ff(): Int {
var i = 1
{
val <!NAME_SHADOWING!>i<!> = 2
}
return i
}
@@ -0,0 +1,5 @@
fun f(): Int {
var i = 17
{ (): Unit => var <!NAME_SHADOWING!>i<!> = 18 }
return i
}
@@ -0,0 +1,5 @@
fun ff(): Int {
var i = 1
{ (i: Int) => i }
return i
}