Redeclaration check supported in LAZY mode
This commit is contained in:
@@ -22,14 +22,19 @@ import com.google.common.collect.*;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import kotlin.Function1;
|
||||
import kotlin.KotlinPackage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptorLite;
|
||||
import org.jetbrains.jet.lang.descriptors.impl.MutablePackageFragmentDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.impl.PackageLikeBuilder;
|
||||
import org.jetbrains.jet.lang.diagnostics.Errors;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
|
||||
import org.jetbrains.jet.lang.resolve.lazy.descriptors.LazyPackageDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||
@@ -39,7 +44,7 @@ import org.jetbrains.jet.renderer.DescriptorRenderer;
|
||||
import javax.inject.Inject;
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.REDECLARATION;
|
||||
|
||||
public class DeclarationResolver {
|
||||
@NotNull
|
||||
@@ -328,17 +333,16 @@ public class DeclarationResolver {
|
||||
return declarations;
|
||||
}
|
||||
|
||||
private void checkRedeclarationsInInnerClassNames(@NotNull TopDownAnalysisContext c) {
|
||||
public void checkRedeclarationsInInnerClassNames(@NotNull TopDownAnalysisContext c) {
|
||||
for (ClassDescriptorWithResolutionScopes classDescriptor : c.getClasses().values()) {
|
||||
MutableClassDescriptor mutableClassDescriptor = (MutableClassDescriptor) classDescriptor;
|
||||
if (classDescriptor.getKind() == ClassKind.CLASS_OBJECT) {
|
||||
// Class objects should be considered during analysing redeclarations in classes
|
||||
continue;
|
||||
}
|
||||
|
||||
Collection<DeclarationDescriptor> allDescriptors = mutableClassDescriptor.getScopeForMemberLookup().getOwnDeclaredDescriptors();
|
||||
Collection<DeclarationDescriptor> allDescriptors = classDescriptor.getScopeForMemberLookup().getOwnDeclaredDescriptors();
|
||||
|
||||
MutableClassDescriptorLite classObj = mutableClassDescriptor.getClassObjectDescriptor();
|
||||
ClassDescriptorWithResolutionScopes classObj = classDescriptor.getClassObjectDescriptor();
|
||||
if (classObj != null) {
|
||||
Collection<DeclarationDescriptor> classObjDescriptors = classObj.getScopeForMemberLookup().getOwnDeclaredDescriptors();
|
||||
if (!classObjDescriptors.isEmpty()) {
|
||||
@@ -389,5 +393,53 @@ public class DeclarationResolver {
|
||||
}
|
||||
}
|
||||
|
||||
public void checkRedeclarationsInPackages(@NotNull ResolveSession resolveSession, @NotNull Multimap<FqName, JetElement> topLevelFqNames) {
|
||||
for (Map.Entry<FqName, Collection<JetElement>> entry : topLevelFqNames.asMap().entrySet()) {
|
||||
FqName fqName = entry.getKey();
|
||||
Collection<JetElement> declarationsOrPackageDirectives = entry.getValue();
|
||||
|
||||
if (fqName.isRoot()) continue;
|
||||
|
||||
Set<DeclarationDescriptor> descriptors = getTopLevelDescriptorsByFqName(resolveSession, fqName);
|
||||
|
||||
if (descriptors.size() > 1) {
|
||||
for (JetElement declarationOrPackageDirective : declarationsOrPackageDirectives) {
|
||||
PsiElement reportAt = declarationOrPackageDirective instanceof JetNamedDeclaration
|
||||
? declarationOrPackageDirective
|
||||
: ((JetPackageDirective) declarationOrPackageDirective).getNameIdentifier();
|
||||
trace.report(Errors.REDECLARATION.on(reportAt, fqName.shortName().asString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Set<DeclarationDescriptor> getTopLevelDescriptorsByFqName(@NotNull ResolveSession resolveSession, @NotNull FqName fqName) {
|
||||
FqName parentFqName = fqName.parent();
|
||||
|
||||
Set<DeclarationDescriptor> descriptors = new HashSet<DeclarationDescriptor>();
|
||||
|
||||
LazyPackageDescriptor parentFragment = resolveSession.getPackageFragment(parentFqName);
|
||||
if (parentFragment != null) {
|
||||
// Filter out extension properties
|
||||
descriptors.addAll(
|
||||
KotlinPackage.filter(
|
||||
parentFragment.getMemberScope().getProperties(fqName.shortName()),
|
||||
new Function1<VariableDescriptor, Boolean>() {
|
||||
@Override
|
||||
public Boolean invoke(VariableDescriptor descriptor) {
|
||||
return descriptor.getReceiverParameter() == null;
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
ContainerUtil.addIfNotNull(descriptors, resolveSession.getPackageFragment(fqName));
|
||||
|
||||
descriptors.addAll(resolveSession.getTopLevelClassDescriptors(fqName));
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
package org.jetbrains.jet.lang.resolve;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import kotlin.Function1;
|
||||
@@ -138,6 +140,8 @@ public class TopDownAnalyzer {
|
||||
trace
|
||||
).getResolveSession();
|
||||
|
||||
final Multimap<FqName, JetElement> topLevelFqNames = HashMultimap.create();
|
||||
|
||||
// fill in the context
|
||||
for (PsiElement declaration : declarations) {
|
||||
declaration.accept(
|
||||
@@ -148,6 +152,15 @@ public class TopDownAnalyzer {
|
||||
}
|
||||
}
|
||||
|
||||
private void registerTopLevelFqName(@NotNull JetNamedDeclaration declaration, @NotNull DeclarationDescriptor descriptor) {
|
||||
if (DescriptorUtils.isTopLevelDeclaration(descriptor)) {
|
||||
FqName fqName = JetPsiUtil.getFQName(declaration);
|
||||
if (fqName != null) {
|
||||
topLevelFqNames.put(fqName, declaration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void registerScope(@Nullable JetDeclaration declaration, @NotNull JetDeclaration anchorForScope) {
|
||||
if (declaration == null) return;
|
||||
c.registerDeclaringScope(
|
||||
@@ -176,6 +189,8 @@ public class TopDownAnalyzer {
|
||||
|
||||
DescriptorResolver.resolvePackageHeader(packageDirective, moduleDescriptor, trace);
|
||||
registerDeclarations(file.getDeclarations());
|
||||
|
||||
topLevelFqNames.put(JetPsiUtil.getFQName(file), packageDirective);
|
||||
}
|
||||
resolveAndCheckImports(file, resolveSession);
|
||||
}
|
||||
@@ -186,13 +201,13 @@ public class TopDownAnalyzer {
|
||||
}
|
||||
|
||||
private void visitClassOrObject(@NotNull JetClassOrObject classOrObject) {
|
||||
c.getClasses().put(
|
||||
classOrObject,
|
||||
ForceResolveUtil.forceResolveAllContents(
|
||||
(ClassDescriptorWithResolutionScopes) resolveSession.getClassDescriptor(classOrObject)
|
||||
)
|
||||
ClassDescriptorWithResolutionScopes descriptor = ForceResolveUtil.forceResolveAllContents(
|
||||
(ClassDescriptorWithResolutionScopes) resolveSession.getClassDescriptor(classOrObject)
|
||||
);
|
||||
|
||||
c.getClasses().put(classOrObject, descriptor);
|
||||
registerDeclarations(classOrObject.getDeclarations());
|
||||
registerTopLevelFqName(classOrObject, descriptor);
|
||||
|
||||
checkManyClassObjects(classOrObject);
|
||||
}
|
||||
@@ -249,12 +264,13 @@ public class TopDownAnalyzer {
|
||||
|
||||
@Override
|
||||
public void visitProperty(@NotNull JetProperty property) {
|
||||
c.getProperties().put(
|
||||
property,
|
||||
ForceResolveUtil.forceResolveAllContents(
|
||||
(PropertyDescriptor) resolveSession.resolveToDescriptor(property)
|
||||
)
|
||||
PropertyDescriptor descriptor = ForceResolveUtil.forceResolveAllContents(
|
||||
(PropertyDescriptor) resolveSession.resolveToDescriptor(property)
|
||||
);
|
||||
|
||||
c.getProperties().put(property, descriptor);
|
||||
registerTopLevelFqName(property, descriptor);
|
||||
|
||||
registerScope(property, property);
|
||||
registerScope(property.getGetter(), property);
|
||||
registerScope(property.getSetter(), property);
|
||||
@@ -262,6 +278,9 @@ public class TopDownAnalyzer {
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
declarationResolver.checkRedeclarationsInPackages(resolveSession, topLevelFqNames);
|
||||
declarationResolver.checkRedeclarationsInInnerClassNames(c);
|
||||
overrideResolver.check(c);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -23,8 +23,11 @@ import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import kotlin.Function0;
|
||||
import kotlin.Function1;
|
||||
import kotlin.KotlinPackage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.ReadOnly;
|
||||
import org.jetbrains.jet.context.GlobalContextImpl;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
@@ -199,6 +202,24 @@ public class ResolveSession implements KotlinCodeAnalyzer {
|
||||
return exceptionTracker;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@ReadOnly
|
||||
public Collection<ClassDescriptor> getTopLevelClassDescriptors(@NotNull FqName fqName) {
|
||||
if (fqName.isRoot()) return Collections.emptyList();
|
||||
|
||||
PackageMemberDeclarationProvider provider = declarationProviderFactory.getPackageMemberDeclarationProvider(fqName.parent());
|
||||
if (provider == null) return Collections.emptyList();
|
||||
|
||||
return KotlinPackage.map(
|
||||
provider.getClassOrObjectDeclarations(fqName.shortName()),
|
||||
new Function1<JetClassOrObject, ClassDescriptor>() {
|
||||
@Override
|
||||
public ClassDescriptor invoke(JetClassOrObject classOrObject) {
|
||||
return getClassDescriptor(classOrObject);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public ClassDescriptor getClassDescriptor(@NotNull JetClassOrObject classOrObject) {
|
||||
@@ -451,4 +472,4 @@ public class ResolveSession implements KotlinCodeAnalyzer {
|
||||
public QualifiedExpressionResolver getQualifiedExpressionResolver() {
|
||||
return qualifiedExpressionResolver;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -165,7 +165,7 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements LazyEnti
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected JetScope getScopeForMemberLookup() {
|
||||
public JetScope getScopeForMemberLookup() {
|
||||
return unsubstitutedMemberScope;
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -33,6 +33,9 @@ public interface ClassDescriptorWithResolutionScopes extends ClassDescriptor {
|
||||
@NotNull
|
||||
JetScope getScopeForInitializerResolution();
|
||||
|
||||
@NotNull
|
||||
JetScope getScopeForMemberLookup();
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
ClassDescriptorWithResolutionScopes getClassObjectDescriptor();
|
||||
|
||||
Reference in New Issue
Block a user