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");
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");
ParameterizedDiagnosticFactory1<Collection<JetKeywordToken>> INCOMPATIBLE_MODIFIERS = new ParameterizedDiagnosticFactory1<Collection<JetKeywordToken>>(ERROR, "Incompatible modifiers: ''{0}''") {
@Override
@@ -15,8 +15,8 @@ import static org.jetbrains.jet.lang.diagnostics.Severity.ERROR;
public interface RedeclarationDiagnostic extends DiagnosticWithPsiElement<PsiElement> {
public class SimpleRedeclarationDiagnostic extends DiagnosticWithPsiElementImpl<PsiElement> implements RedeclarationDiagnostic {
public SimpleRedeclarationDiagnostic(@NotNull PsiElement psiElement, @NotNull String name) {
super(RedeclarationDiagnosticFactory.INSTANCE, ERROR, "Redeclaration: " + name, psiElement);
public SimpleRedeclarationDiagnostic(@NotNull PsiElement psiElement, @NotNull String name, RedeclarationDiagnosticFactory factory) {
super(factory, factory.severity, factory.makeMessage(name), psiElement);
}
}
@@ -24,11 +24,13 @@ public interface RedeclarationDiagnostic extends DiagnosticWithPsiElement<PsiEle
private final DeclarationDescriptor duplicatingDescriptor;
private final BindingContext contextToResolveToDeclaration;
private final RedeclarationDiagnosticFactory factory;
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.contextToResolveToDeclaration = contextToResolveToDeclaration;
this.factory = factory;
}
private PsiElement resolve() {
@@ -60,19 +62,19 @@ public interface RedeclarationDiagnostic extends DiagnosticWithPsiElement<PsiEle
@NotNull
@Override
public DiagnosticFactory getFactory() {
return Errors.REDECLARATION;
return factory;
}
@NotNull
@Override
public String getMessage() {
return "Redeclaration: " + duplicatingDescriptor.getName();
return factory.makeMessage(duplicatingDescriptor.getName());
}
@NotNull
@Override
public Severity getSeverity() {
return ERROR;
return factory.severity;
}
@Override
@@ -11,17 +11,28 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
* @author abreslav
*/
public class RedeclarationDiagnosticFactory extends AbstractDiagnosticFactory {
private final String name;
final Severity severity;
private final String messagePrefix;
public static final RedeclarationDiagnosticFactory INSTANCE = new 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() {}
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) {
return new RedeclarationDiagnostic.SimpleRedeclarationDiagnostic(duplicatingElement, name);
return new RedeclarationDiagnostic.SimpleRedeclarationDiagnostic(duplicatingElement, name, this);
}
public Diagnostic on(DeclarationDescriptor duplicatingDescriptor, BindingContext contextToResolveToDeclaration) {
return new RedeclarationDiagnostic.RedeclarationDiagnosticWithDeferredResolution(duplicatingDescriptor, contextToResolveToDeclaration);
return new RedeclarationDiagnostic.RedeclarationDiagnosticWithDeferredResolution(duplicatingDescriptor, contextToResolveToDeclaration, this);
}
@NotNull
@@ -40,7 +51,11 @@ public class RedeclarationDiagnosticFactory extends AbstractDiagnosticFactory {
@NotNull
@Override
public String getName() {
return "REDECLARATION";
return name;
}
public String makeMessage(String identifier) {
return messagePrefix + identifier;
}
@Override
@@ -6,9 +6,12 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
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.resolve.BindingContext;
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.OverloadResolutionResults;
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);
}
{
// 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);
}
@@ -7,6 +7,7 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*;
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.TopDownAnalyzer;
import org.jetbrains.jet.lang.resolve.calls.CallMaker;
@@ -89,6 +90,13 @@ public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingV
JetType outType = propertyDescriptor.getOutType();
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);
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
}