Proper error reporting when a package name redeclares something, wrt the package name occurring in multiple files
See MultiFilePackageRedeclaration.jet test
This commit is contained in:
-12
@@ -16,16 +16,8 @@
|
||||
|
||||
package org.jetbrains.jet.lang.diagnostics;
|
||||
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetNamedDeclaration;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -51,10 +43,6 @@ public class RedeclarationDiagnosticFactory extends AbstractDiagnosticFactory {
|
||||
return new RedeclarationDiagnostic.SimpleRedeclarationDiagnostic(duplicatingElement, name, this);
|
||||
}
|
||||
|
||||
public Diagnostic on(DeclarationDescriptor duplicatingDescriptor, BindingContext contextToResolveToDeclaration) {
|
||||
return new RedeclarationDiagnostic.RedeclarationDiagnosticWithDeferredResolution(duplicatingDescriptor, contextToResolveToDeclaration, this);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
|
||||
@@ -144,7 +144,6 @@ public interface BindingContext {
|
||||
return declarationDescriptor.getOriginal();
|
||||
}
|
||||
};
|
||||
WritableSlice<JetFile, NamespaceDescriptor> FILE_TO_NAMESPACE = Slices.createSimpleSlice();
|
||||
|
||||
ReadOnlySlice<DeclarationDescriptor, PsiElement> DESCRIPTOR_TO_DECLARATION = Slices.<DeclarationDescriptor, PsiElement>sliceBuilder().setKeyNormalizer(DECLARATION_DESCRIPTOR_NORMALIZER).build();
|
||||
|
||||
@@ -173,6 +172,8 @@ public interface BindingContext {
|
||||
|
||||
WritableSlice<FqName, ClassDescriptor> FQNAME_TO_CLASS_DESCRIPTOR = new BasicWritableSlice<FqName, ClassDescriptor>(DO_NOTHING, true);
|
||||
WritableSlice<FqName, NamespaceDescriptor> FQNAME_TO_NAMESPACE_DESCRIPTOR = new BasicWritableSlice<FqName, NamespaceDescriptor>(DO_NOTHING);
|
||||
WritableSlice<JetFile, NamespaceDescriptor> FILE_TO_NAMESPACE = Slices.createSimpleSlice();
|
||||
WritableSlice<NamespaceDescriptor, Collection<JetFile>> NAMESPACE_TO_FILES = Slices.createSimpleSlice();
|
||||
|
||||
/**
|
||||
* Each namespace found in src must be registered here.
|
||||
|
||||
@@ -16,17 +16,26 @@
|
||||
|
||||
package org.jetbrains.jet.lang.resolve;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Collections2;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.CONSTRUCTOR_IN_TRAIT;
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.REDECLARATION;
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.SECONDARY_CONSTRUCTORS_ARE_NOT_SUPPORTED;
|
||||
|
||||
/**
|
||||
@@ -77,8 +86,11 @@ public class DeclarationResolver {
|
||||
resolveAnnotationStubsOnClassesAndConstructors();
|
||||
resolveFunctionAndPropertyHeaders();
|
||||
importsResolver.processMembersImports();
|
||||
checkRedeclarationsInNamespaces();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void resolveConstructorHeaders() {
|
||||
for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
|
||||
JetClass jetClass = entry.getKey();
|
||||
@@ -233,4 +245,49 @@ public class DeclarationResolver {
|
||||
context.getDeclaringScopes().put(constructor, classDescriptor.getScopeForMemberLookup());
|
||||
}
|
||||
|
||||
private void checkRedeclarationsInNamespaces() {
|
||||
for (NamespaceDescriptorImpl descriptor : context.getNamespaceDescriptors().values()) {
|
||||
Multimap<String, DeclarationDescriptor> simpleNameDescriptors = descriptor.getMemberScope().getDeclaredDescriptorsAccessibleBySimpleName();
|
||||
for (String name : simpleNameDescriptors.keySet()) {
|
||||
// Keep only properties with no receiver
|
||||
Collection<DeclarationDescriptor> descriptors = Collections2.filter(simpleNameDescriptors.get(name), new Predicate<DeclarationDescriptor>() {
|
||||
@Override
|
||||
public boolean apply(@Nullable DeclarationDescriptor descriptor) {
|
||||
if (descriptor instanceof PropertyDescriptor) {
|
||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor)descriptor;
|
||||
return !propertyDescriptor.getReceiverParameter().exists();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (descriptors.size() > 1) {
|
||||
for (DeclarationDescriptor declarationDescriptor : descriptors) {
|
||||
for (PsiElement declaration : getDeclarationsByDescriptor(declarationDescriptor)) {
|
||||
assert declaration != null;
|
||||
trace.report(REDECLARATION.on(declaration, declarationDescriptor.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Collection<PsiElement> getDeclarationsByDescriptor(DeclarationDescriptor declarationDescriptor) {
|
||||
Collection<PsiElement> declarations;
|
||||
if (declarationDescriptor instanceof NamespaceDescriptor) {
|
||||
final NamespaceDescriptor namespace = (NamespaceDescriptor)declarationDescriptor;
|
||||
Collection<JetFile> files = trace.get(BindingContext.NAMESPACE_TO_FILES, namespace);
|
||||
declarations = Collections2.transform(files, new Function<JetFile, PsiElement>() {
|
||||
@Override
|
||||
public PsiElement apply(@Nullable JetFile file) {
|
||||
assert file != null : "File is null for namespace " + namespace;
|
||||
return file.getNamespaceHeader().getNameIdentifier();
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
declarations = Collections.singletonList(trace.get(BindingContext.DESCRIPTOR_TO_DECLARATION, declarationDescriptor));
|
||||
}
|
||||
return declarations;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.jet.lang.resolve;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.ModuleConfiguration;
|
||||
@@ -28,15 +29,15 @@ import org.jetbrains.jet.lang.psi.JetNamespaceHeader;
|
||||
import org.jetbrains.jet.lang.psi.JetPsiUtil;
|
||||
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.RedeclarationHandler;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLUTION_SCOPE;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
||||
|
||||
/**
|
||||
* @author Stepan Koltsov
|
||||
@@ -112,7 +113,6 @@ public class NamespaceFactoryImpl implements NamespaceFactory {
|
||||
|
||||
@NotNull
|
||||
public NamespaceDescriptorImpl createNamespaceDescriptorIfNeeded(@Nullable JetFile file, @NotNull NamespaceDescriptorParent owner, @NotNull String name, boolean root) {
|
||||
|
||||
FqName fqName;
|
||||
NamespaceDescriptorImpl namespaceDescriptor;
|
||||
if (root) {
|
||||
@@ -135,7 +135,7 @@ public class NamespaceFactoryImpl implements NamespaceFactory {
|
||||
name
|
||||
);
|
||||
trace.record(FQNAME_TO_NAMESPACE_DESCRIPTOR, fqName, namespaceDescriptor);
|
||||
WritableScopeImpl scope = new WritableScopeImpl(JetScope.EMPTY, namespaceDescriptor, new TraceBasedRedeclarationHandler(trace)).setDebugName("Namespace member scope");
|
||||
WritableScopeImpl scope = new WritableScopeImpl(JetScope.EMPTY, namespaceDescriptor, RedeclarationHandler.DO_NOTHING).setDebugName("Namespace member scope");
|
||||
scope.changeLockLevel(WritableScope.LockLevel.BOTH);
|
||||
namespaceDescriptor.initialize(scope);
|
||||
configuration.extendNamespaceScope(trace, namespaceDescriptor, scope);
|
||||
@@ -147,6 +147,15 @@ public class NamespaceFactoryImpl implements NamespaceFactory {
|
||||
|
||||
if (file != null) {
|
||||
trace.record(BindingContext.FILE_TO_NAMESPACE, file, namespaceDescriptor);
|
||||
|
||||
// Register files corresponding to this namespace
|
||||
// The trace currently does not support bi-di multimaps that would handle this task nicer
|
||||
Collection<JetFile> files = trace.get(NAMESPACE_TO_FILES, namespaceDescriptor);
|
||||
if (files == null) {
|
||||
files = Sets.newIdentityHashSet();
|
||||
}
|
||||
files.add(file);
|
||||
trace.record(BindingContext.NAMESPACE_TO_FILES, namespaceDescriptor, files);
|
||||
}
|
||||
|
||||
return namespaceDescriptor;
|
||||
|
||||
+4
-4
@@ -39,13 +39,13 @@ public class TraceBasedRedeclarationHandler implements RedeclarationHandler {
|
||||
report(second);
|
||||
}
|
||||
|
||||
private void report(DeclarationDescriptor first) {
|
||||
PsiElement firstElement = trace.get(BindingContext.DESCRIPTOR_TO_DECLARATION, first);
|
||||
private void report(DeclarationDescriptor descriptor) {
|
||||
PsiElement firstElement = trace.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor);
|
||||
if (firstElement != null) {
|
||||
trace.report(REDECLARATION.on(firstElement, first.getName()));
|
||||
trace.report(REDECLARATION.on(firstElement, descriptor.getName()));
|
||||
}
|
||||
else {
|
||||
trace.report(REDECLARATION.on(first, trace.getBindingContext()));
|
||||
throw new IllegalStateException("No declaration found found for " + descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.jet.lang.resolve.scopes;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
@@ -60,6 +61,9 @@ public interface WritableScope extends JetScope {
|
||||
@Nullable
|
||||
NamespaceDescriptor getDeclaredNamespace(@NotNull String name);
|
||||
|
||||
@NotNull
|
||||
Multimap<String, DeclarationDescriptor> getDeclaredDescriptorsAccessibleBySimpleName();
|
||||
|
||||
void importScope(@NotNull JetScope imported);
|
||||
|
||||
void setImplicitReceiver(@NotNull ReceiverDescriptor implicitReceiver);
|
||||
|
||||
@@ -16,10 +16,7 @@
|
||||
|
||||
package org.jetbrains.jet.lang.resolve.scopes;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.SetMultimap;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
@@ -36,6 +33,7 @@ import java.util.*;
|
||||
public class WritableScopeImpl extends WritableScopeWithImports {
|
||||
|
||||
private final Collection<DeclarationDescriptor> allDescriptors = Sets.newLinkedHashSet();
|
||||
private final Multimap<String, DeclarationDescriptor> declaredDescriptorsAccessibleBySimpleName = HashMultimap.create();
|
||||
private boolean allDescriptorsDone = false;
|
||||
|
||||
@NotNull
|
||||
@@ -226,6 +224,7 @@ public class WritableScopeImpl extends WritableScopeWithImports {
|
||||
getVariableClassOrNamespaceDescriptors().put(name, variableDescriptor);
|
||||
}
|
||||
allDescriptors.add(variableDescriptor);
|
||||
addToDeclared(variableDescriptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -334,6 +333,7 @@ public class WritableScopeImpl extends WritableScopeWithImports {
|
||||
checkForRedeclaration(name, classifierDescriptor);
|
||||
getVariableClassOrNamespaceDescriptors().put(name, classifierDescriptor);
|
||||
allDescriptors.add(classifierDescriptor);
|
||||
addToDeclared(classifierDescriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -343,6 +343,7 @@ public class WritableScopeImpl extends WritableScopeWithImports {
|
||||
checkForRedeclaration(name, namespaceDescriptor);
|
||||
getNamespaceAliases().put(name, namespaceDescriptor);
|
||||
allDescriptors.add(namespaceDescriptor);
|
||||
addToDeclared(namespaceDescriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -361,6 +362,7 @@ public class WritableScopeImpl extends WritableScopeWithImports {
|
||||
checkForRedeclaration(name, variableDescriptor);
|
||||
getVariableClassOrNamespaceDescriptors().put(name, variableDescriptor);
|
||||
allDescriptors.add(variableDescriptor);
|
||||
addToDeclared(variableDescriptor);
|
||||
}
|
||||
|
||||
private void checkForPropertyRedeclaration(String name, VariableDescriptor variableDescriptor) {
|
||||
@@ -417,6 +419,7 @@ public class WritableScopeImpl extends WritableScopeWithImports {
|
||||
redeclarationHandler.handleRedeclaration(oldValue, namespaceDescriptor);
|
||||
}
|
||||
allDescriptors.add(namespaceDescriptor);
|
||||
addToDeclared(namespaceDescriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -521,4 +524,14 @@ public class WritableScopeImpl extends WritableScopeWithImports {
|
||||
super.setDebugName(debugName);
|
||||
return this;
|
||||
}
|
||||
|
||||
private void addToDeclared(DeclarationDescriptor descriptor) {
|
||||
declaredDescriptorsAccessibleBySimpleName.put(descriptor.getName(), descriptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Multimap<String, DeclarationDescriptor> getDeclaredDescriptorsAccessibleBySimpleName() {
|
||||
return declaredDescriptorsAccessibleBySimpleName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.jet.lang.resolve.scopes;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -257,6 +258,12 @@ public class WriteThroughScope extends WritableScopeWithImports {
|
||||
return writableWorker.getDeclaredNamespace(name);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Multimap<String, DeclarationDescriptor> getDeclaredDescriptorsAccessibleBySimpleName() {
|
||||
return writableWorker.getDeclaredDescriptorsAccessibleBySimpleName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void importScope(@NotNull JetScope imported) {
|
||||
checkMayWrite();
|
||||
|
||||
+2
-1
@@ -270,7 +270,8 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
|
||||
VariableDescriptor olderVariable = context.scope.getLocalVariable(variableDescriptor.getName());
|
||||
if (olderVariable != null && DescriptorUtils.isLocal(context.scope.getContainingDeclaration(), olderVariable)) {
|
||||
context.trace.report(Errors.NAME_SHADOWING.on(variableDescriptor, context.trace.getBindingContext()));
|
||||
PsiElement declaration = context.trace.get(DESCRIPTOR_TO_DECLARATION, variableDescriptor);
|
||||
context.trace.report(Errors.NAME_SHADOWING.on(declaration, variableDescriptor.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.jet.lang.types.expressions;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -43,6 +44,7 @@ import java.util.Collection;
|
||||
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.AMBIGUOUS_REFERENCE_TARGET;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.DESCRIPTOR_TO_DECLARATION;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.VARIABLE_REASSIGNMENT;
|
||||
|
||||
/**
|
||||
@@ -116,7 +118,8 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
||||
{
|
||||
VariableDescriptor olderVariable = scope.getLocalVariable(propertyDescriptor.getName());
|
||||
if (olderVariable != null && DescriptorUtils.isLocal(propertyDescriptor.getContainingDeclaration(), olderVariable)) {
|
||||
context.trace.report(Errors.NAME_SHADOWING.on(propertyDescriptor, context.trace.getBindingContext()));
|
||||
PsiElement declaration = context.trace.get(DESCRIPTOR_TO_DECLARATION, propertyDescriptor);
|
||||
context.trace.report(Errors.NAME_SHADOWING.on(declaration, propertyDescriptor.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
// FILE: f.kt
|
||||
package a
|
||||
class <!REDECLARATION!>b<!> {}
|
||||
// FILE: f.kt
|
||||
package a.<!REDECLARATION!>b<!>
|
||||
// FILE: f.kt
|
||||
package a.<!REDECLARATION!>b<!>
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
// FILE: f.kt
|
||||
package redeclarations
|
||||
object <!REDECLARATION, REDECLARATION!>A<!> {
|
||||
object <!REDECLARATION!>A<!> {
|
||||
val x : Int = 0
|
||||
|
||||
val A = 1
|
||||
@@ -11,5 +11,5 @@ package redeclarations
|
||||
val <!REDECLARATION!>A<!> = 1
|
||||
|
||||
// FILE: f.kt
|
||||
package redeclarations.<!REDECLARATION, REDECLARATION!>A<!>
|
||||
package redeclarations.<!REDECLARATION!>A<!>
|
||||
class A {}
|
||||
Reference in New Issue
Block a user