Resolve invisible references and mark them 'invisible' instead of mark them 'unresolved'

This commit is contained in:
Svetlana Isakova
2012-04-05 18:36:36 +04:00
parent aa568a3ceb
commit 7863b1398e
13 changed files with 139 additions and 84 deletions
@@ -53,7 +53,10 @@ public interface Errors {
}); });
UnresolvedReferenceDiagnosticFactory UNRESOLVED_REFERENCE = UnresolvedReferenceDiagnosticFactory.create("Unresolved reference"); UnresolvedReferenceDiagnosticFactory UNRESOLVED_REFERENCE = UnresolvedReferenceDiagnosticFactory.create("Unresolved reference");
DiagnosticFactory2<JetSimpleNameExpression, DeclarationDescriptor, DeclarationDescriptor> INVISIBLE_MEMBER = DiagnosticFactory2.create(ERROR, "''{0}'' has private access in ''{1}''", NAME, NAME);
//Elements with "INVISIBLE_REFERENCE" error are marked as unresolved, unlike elements with "INVISIBLE_MEMBER" error
DiagnosticFactory2<JetSimpleNameExpression, DeclarationDescriptor, DeclarationDescriptor> INVISIBLE_REFERENCE = DiagnosticFactory2.create(ERROR, "Cannot access ''{0}'' in ''{1}''", NAME, NAME);
DiagnosticFactory2<PsiElement, DeclarationDescriptor, DeclarationDescriptor> INVISIBLE_MEMBER = DiagnosticFactory2.create(ERROR, "Cannot access ''{0}'' in ''{1}''", NAME, NAME);
RedeclarationDiagnosticFactory REDECLARATION = RedeclarationDiagnosticFactory.REDECLARATION; RedeclarationDiagnosticFactory REDECLARATION = RedeclarationDiagnosticFactory.REDECLARATION;
RedeclarationDiagnosticFactory NAME_SHADOWING = RedeclarationDiagnosticFactory.NAME_SHADOWING; RedeclarationDiagnosticFactory NAME_SHADOWING = RedeclarationDiagnosticFactory.NAME_SHADOWING;
@@ -20,10 +20,7 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.ModuleConfiguration; import org.jetbrains.jet.lang.ModuleConfiguration;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
@@ -91,13 +88,13 @@ public class ImportsResolver {
Collection<JetImportDirective> defaultImportDirectives = Lists.newArrayList(); Collection<JetImportDirective> defaultImportDirectives = Lists.newArrayList();
configuration.addDefaultImports(defaultImportDirectives); configuration.addDefaultImports(defaultImportDirectives);
for (JetImportDirective defaultImportDirective : defaultImportDirectives) { for (JetImportDirective defaultImportDirective : defaultImportDirectives) {
qualifiedExpressionResolver.processImportReference(defaultImportDirective, rootScope, delayedImporter, temporaryTrace, onlyClasses); qualifiedExpressionResolver.processImportReference(defaultImportDirective, rootScope, namespaceScope, delayedImporter, temporaryTrace, onlyClasses);
} }
List<JetImportDirective> importDirectives = file.getImportDirectives(); List<JetImportDirective> importDirectives = file.getImportDirectives();
for (JetImportDirective importDirective : importDirectives) { for (JetImportDirective importDirective : importDirectives) {
Collection<? extends DeclarationDescriptor> descriptors = Collection<? extends DeclarationDescriptor> descriptors =
qualifiedExpressionResolver.processImportReference(importDirective, rootScope, delayedImporter, trace, onlyClasses); qualifiedExpressionResolver.processImportReference(importDirective, rootScope, namespaceScope, delayedImporter, trace, onlyClasses);
if (descriptors.size() == 1) { if (descriptors.size() == 1) {
resolvedDirectives.put(importDirective, descriptors.iterator().next()); resolvedDirectives.put(importDirective, descriptors.iterator().next());
} }
@@ -42,12 +42,12 @@ public class QualifiedExpressionResolver {
public Collection<? extends DeclarationDescriptor> analyseImportReference(@NotNull JetImportDirective importDirective, public Collection<? extends DeclarationDescriptor> analyseImportReference(@NotNull JetImportDirective importDirective,
@NotNull JetScope scope, @NotNull BindingTrace trace) { @NotNull JetScope scope, @NotNull BindingTrace trace) {
return processImportReference(importDirective, scope, Importer.DO_NOTHING, trace, false); return processImportReference(importDirective, scope, scope, Importer.DO_NOTHING, trace, false);
} }
@NotNull @NotNull
public Collection<? extends DeclarationDescriptor> processImportReference(@NotNull JetImportDirective importDirective, public Collection<? extends DeclarationDescriptor> processImportReference(@NotNull JetImportDirective importDirective,
@NotNull JetScope scope, @NotNull Importer importer, @NotNull BindingTrace trace, boolean onlyClasses) { @NotNull JetScope scope, @NotNull JetScope scopeToCheckVisibility, @NotNull Importer importer, @NotNull BindingTrace trace, boolean onlyClasses) {
if (importDirective.isAbsoluteInRootNamespace()) { if (importDirective.isAbsoluteInRootNamespace()) {
trace.report(UNSUPPORTED.on(importDirective, "TypeHierarchyResolver")); // TODO trace.report(UNSUPPORTED.on(importDirective, "TypeHierarchyResolver")); // TODO
@@ -61,11 +61,11 @@ public class QualifiedExpressionResolver {
Collection<? extends DeclarationDescriptor> descriptors; Collection<? extends DeclarationDescriptor> descriptors;
if (importedReference instanceof JetQualifiedExpression) { if (importedReference instanceof JetQualifiedExpression) {
//store result only when we find all descriptors, not only classes on the second phase //store result only when we find all descriptors, not only classes on the second phase
descriptors = lookupDescriptorsForQualifiedExpression((JetQualifiedExpression)importedReference, scope, trace, onlyClasses, !onlyClasses); descriptors = lookupDescriptorsForQualifiedExpression((JetQualifiedExpression)importedReference, scope, scopeToCheckVisibility, trace, onlyClasses, !onlyClasses);
} }
else { else {
assert importedReference instanceof JetSimpleNameExpression; assert importedReference instanceof JetSimpleNameExpression;
descriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression)importedReference, scope, trace, onlyClasses, true, !onlyClasses); descriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression)importedReference, scope, scopeToCheckVisibility, trace, onlyClasses, true, !onlyClasses);
} }
JetSimpleNameExpression referenceExpression = JetPsiUtil.getLastReference(importedReference); JetSimpleNameExpression referenceExpression = JetPsiUtil.getLastReference(importedReference);
@@ -140,24 +140,24 @@ public class QualifiedExpressionResolver {
} }
JetUserType qualifier = userType.getQualifier(); JetUserType qualifier = userType.getQualifier();
if (qualifier == null) { if (qualifier == null) {
return lookupDescriptorsForSimpleNameReference(referenceExpression, outerScope, trace, true, false, true); return lookupDescriptorsForSimpleNameReference(referenceExpression, outerScope, outerScope, trace, true, false, true);
} }
Collection<? extends DeclarationDescriptor> declarationDescriptors = lookupDescriptorsForUserType(qualifier, outerScope, trace); Collection<? extends DeclarationDescriptor> declarationDescriptors = lookupDescriptorsForUserType(qualifier, outerScope, trace);
return lookupSelectorDescriptors(referenceExpression, declarationDescriptors, trace, true, true); return lookupSelectorDescriptors(referenceExpression, declarationDescriptors, trace, outerScope, true, true);
} }
@NotNull @NotNull
public Collection<? extends DeclarationDescriptor> lookupDescriptorsForQualifiedExpression(@NotNull JetQualifiedExpression importedReference, public Collection<? extends DeclarationDescriptor> lookupDescriptorsForQualifiedExpression(@NotNull JetQualifiedExpression importedReference,
@NotNull JetScope outerScope, @NotNull BindingTrace trace, boolean onlyClasses, boolean storeResult) { @NotNull JetScope outerScope, @NotNull JetScope scopeToCheckVisibility, @NotNull BindingTrace trace, boolean onlyClasses, boolean storeResult) {
JetExpression receiverExpression = importedReference.getReceiverExpression(); JetExpression receiverExpression = importedReference.getReceiverExpression();
Collection<? extends DeclarationDescriptor> declarationDescriptors; Collection<? extends DeclarationDescriptor> declarationDescriptors;
if (receiverExpression instanceof JetQualifiedExpression) { if (receiverExpression instanceof JetQualifiedExpression) {
declarationDescriptors = lookupDescriptorsForQualifiedExpression((JetQualifiedExpression)receiverExpression, outerScope, trace, onlyClasses, storeResult); declarationDescriptors = lookupDescriptorsForQualifiedExpression((JetQualifiedExpression)receiverExpression, outerScope, scopeToCheckVisibility, trace, onlyClasses, storeResult);
} }
else { else {
assert receiverExpression instanceof JetSimpleNameExpression; assert receiverExpression instanceof JetSimpleNameExpression;
declarationDescriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression)receiverExpression, outerScope, trace, onlyClasses, true, storeResult); declarationDescriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression)receiverExpression, outerScope, scopeToCheckVisibility, trace, onlyClasses, true, storeResult);
} }
JetExpression selectorExpression = importedReference.getSelectorExpression(); JetExpression selectorExpression = importedReference.getSelectorExpression();
@@ -171,12 +171,13 @@ public class QualifiedExpressionResolver {
return Collections.emptyList(); return Collections.emptyList();
} }
return lookupSelectorDescriptors(selector, declarationDescriptors, trace, onlyClasses, storeResult); return lookupSelectorDescriptors(selector, declarationDescriptors, trace, scopeToCheckVisibility, onlyClasses, storeResult);
} }
@NotNull @NotNull
private Collection<? extends DeclarationDescriptor> lookupSelectorDescriptors(@NotNull JetSimpleNameExpression selector, private Collection<? extends DeclarationDescriptor> lookupSelectorDescriptors(@NotNull JetSimpleNameExpression selector,
@NotNull Collection<? extends DeclarationDescriptor> declarationDescriptors, @NotNull BindingTrace trace, boolean onlyClasses, boolean storeResult) { @NotNull Collection<? extends DeclarationDescriptor> declarationDescriptors, @NotNull BindingTrace trace,
@NotNull JetScope scopeToCheckVisibility, boolean onlyClasses, boolean storeResult) {
Set<SuccessfulLookupResult> results = Sets.newHashSet(); Set<SuccessfulLookupResult> results = Sets.newHashSet();
for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) { for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) {
@@ -191,7 +192,7 @@ public class QualifiedExpressionResolver {
} }
} }
} }
return filterAndStoreResolutionResult(results, selector, trace, onlyClasses, storeResult); return filterAndStoreResolutionResult(results, selector, trace, scopeToCheckVisibility, onlyClasses, storeResult);
} }
@NotNull @NotNull
@@ -207,11 +208,11 @@ public class QualifiedExpressionResolver {
@NotNull @NotNull
public Collection<? extends DeclarationDescriptor> lookupDescriptorsForSimpleNameReference(@NotNull JetSimpleNameExpression referenceExpression, public Collection<? extends DeclarationDescriptor> lookupDescriptorsForSimpleNameReference(@NotNull JetSimpleNameExpression referenceExpression,
@NotNull JetScope outerScope, @NotNull BindingTrace trace, boolean onlyClasses, boolean namespaceLevel, boolean storeResult) { @NotNull JetScope outerScope, @NotNull JetScope scopeToCheckVisibility, @NotNull BindingTrace trace, boolean onlyClasses, boolean namespaceLevel, boolean storeResult) {
LookupResult lookupResult = lookupSimpleNameReference(referenceExpression, outerScope, onlyClasses, namespaceLevel); LookupResult lookupResult = lookupSimpleNameReference(referenceExpression, outerScope, onlyClasses, namespaceLevel);
if (lookupResult == LookupResult.EMPTY) return Collections.emptyList(); if (lookupResult == LookupResult.EMPTY) return Collections.emptyList();
return filterAndStoreResolutionResult(Collections.singletonList((SuccessfulLookupResult)lookupResult), referenceExpression, trace, return filterAndStoreResolutionResult(Collections.singletonList((SuccessfulLookupResult)lookupResult), referenceExpression, trace, scopeToCheckVisibility,
onlyClasses, storeResult); onlyClasses, storeResult);
} }
@@ -256,7 +257,8 @@ public class QualifiedExpressionResolver {
@NotNull @NotNull
private Collection<? extends DeclarationDescriptor> filterAndStoreResolutionResult(@NotNull Collection<SuccessfulLookupResult> lookupResults, private Collection<? extends DeclarationDescriptor> filterAndStoreResolutionResult(@NotNull Collection<SuccessfulLookupResult> lookupResults,
@NotNull JetSimpleNameExpression referenceExpression, @NotNull BindingTrace trace, boolean onlyClasses, boolean storeResult) { @NotNull JetSimpleNameExpression referenceExpression, @NotNull BindingTrace trace, @NotNull JetScope scopeToCheckVisibility,
boolean onlyClasses, boolean storeResult) {
if (lookupResults.isEmpty()) { if (lookupResults.isEmpty()) {
return Collections.emptyList(); return Collections.emptyList();
@@ -307,7 +309,7 @@ public class QualifiedExpressionResolver {
} }
} }
if (storeResult) { if (storeResult) {
storeResolutionResult(descriptors, filteredDescriptors, referenceExpression, possibleResolutionScopes, trace); storeResolutionResult(descriptors, filteredDescriptors, referenceExpression, possibleResolutionScopes, trace, scopeToCheckVisibility);
} }
return filteredDescriptors; return filteredDescriptors;
} }
@@ -316,7 +318,8 @@ public class QualifiedExpressionResolver {
@NotNull Collection<? extends DeclarationDescriptor> canBeImportedDescriptors, @NotNull Collection<? extends DeclarationDescriptor> canBeImportedDescriptors,
@NotNull JetSimpleNameExpression referenceExpression, @NotNull JetSimpleNameExpression referenceExpression,
@NotNull Collection<JetScope> possibleResolutionScopes, @NotNull Collection<JetScope> possibleResolutionScopes,
@NotNull BindingTrace trace) { @NotNull BindingTrace trace,
@NotNull JetScope scopeToCheckVisibility) {
assert canBeImportedDescriptors.size() <= descriptors.size(); assert canBeImportedDescriptors.size() <= descriptors.size();
assert !possibleResolutionScopes.isEmpty(); assert !possibleResolutionScopes.isEmpty();
@@ -324,7 +327,7 @@ public class QualifiedExpressionResolver {
JetScope resolutionScope = possibleResolutionScopes.iterator().next(); JetScope resolutionScope = possibleResolutionScopes.iterator().next();
// A special case - will fill all trace information // A special case - will fill all trace information
if (resolveClassNamespaceAmbiguity(canBeImportedDescriptors, referenceExpression, resolutionScope, trace)) { if (resolveClassNamespaceAmbiguity(canBeImportedDescriptors, referenceExpression, resolutionScope, trace, scopeToCheckVisibility)) {
return; return;
} }
@@ -336,22 +339,30 @@ public class QualifiedExpressionResolver {
} }
// Decide if expression has resolved reference // Decide if expression has resolved reference
DeclarationDescriptor descriptor = null;
if (descriptors.size() == 1) { if (descriptors.size() == 1) {
descriptor = descriptors.iterator().next();
assert canBeImportedDescriptors.size() <= 1; assert canBeImportedDescriptors.size() <= 1;
trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, descriptors.iterator().next());
trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope);
} }
else if (canBeImportedDescriptors.size() == 1) { else if (canBeImportedDescriptors.size() == 1) {
trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, canBeImportedDescriptors.iterator().next()); descriptor = canBeImportedDescriptors.iterator().next();
}
if (descriptor != null) {
trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, descriptors.iterator().next());
trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope); trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope);
if (descriptor instanceof DeclarationDescriptorWithVisibility) {
checkVisibility((DeclarationDescriptorWithVisibility)descriptor, trace, referenceExpression, scopeToCheckVisibility);
}
} }
// Check for more information and additional errors // Check for more information and additional errors
if (canBeImportedDescriptors.isEmpty()) { if (canBeImportedDescriptors.isEmpty()) {
assert descriptors.size() >= 1; assert descriptors.size() >= 1;
trace.report(CANNOT_BE_IMPORTED.on(referenceExpression, descriptors.iterator().next())); trace.report(CANNOT_BE_IMPORTED.on(referenceExpression, descriptors.iterator().next()));
return;
} }
else if (canBeImportedDescriptors.size() > 1) { if (canBeImportedDescriptors.size() > 1) {
trace.record(BindingContext.AMBIGUOUS_REFERENCE_TARGET, referenceExpression, descriptors); trace.record(BindingContext.AMBIGUOUS_REFERENCE_TARGET, referenceExpression, descriptors);
} }
} }
@@ -363,7 +374,8 @@ public class QualifiedExpressionResolver {
* @return <code>true</code> if method has successfully resolved ambiguity * @return <code>true</code> if method has successfully resolved ambiguity
*/ */
private boolean resolveClassNamespaceAmbiguity(@NotNull Collection<? extends DeclarationDescriptor> filteredDescriptors, private boolean resolveClassNamespaceAmbiguity(@NotNull Collection<? extends DeclarationDescriptor> filteredDescriptors,
@NotNull JetSimpleNameExpression referenceExpression, @NotNull JetScope resolutionScope, @NotNull BindingTrace trace) { @NotNull JetSimpleNameExpression referenceExpression, @NotNull JetScope resolutionScope, @NotNull BindingTrace trace,
@NotNull JetScope scopeToCheckVisibility) {
if (filteredDescriptors.size() == 2) { if (filteredDescriptors.size() == 2) {
NamespaceDescriptor namespaceDescriptor = null; NamespaceDescriptor namespaceDescriptor = null;
@@ -382,6 +394,7 @@ public class QualifiedExpressionResolver {
if (DescriptorUtils.getFQName(namespaceDescriptor).equals(DescriptorUtils.getFQName(classDescriptor))) { if (DescriptorUtils.getFQName(namespaceDescriptor).equals(DescriptorUtils.getFQName(classDescriptor))) {
trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, classDescriptor); trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, classDescriptor);
trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope); trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope);
checkVisibility(classDescriptor, trace, referenceExpression, scopeToCheckVisibility);
return true; return true;
} }
} }
@@ -390,6 +403,14 @@ public class QualifiedExpressionResolver {
return false; return false;
} }
private void checkVisibility(@NotNull DeclarationDescriptorWithVisibility descriptor, @NotNull BindingTrace trace,
@NotNull JetSimpleNameExpression referenceExpression, @NotNull JetScope scopeToCheckVisibility) {
if (!Visibilities.isVisible(descriptor, scopeToCheckVisibility.getContainingDeclaration())) {
trace.report(INVISIBLE_REFERENCE.on(referenceExpression, descriptor, descriptor.getContainingDeclaration()));
}
}
private interface LookupResult { private interface LookupResult {
LookupResult EMPTY = new LookupResult() { LookupResult EMPTY = new LookupResult() {
}; };
@@ -270,15 +270,9 @@ public class TypeResolver {
@Nullable @Nullable
public ClassifierDescriptor resolveClass(JetScope scope, JetUserType userType, BindingTrace trace) { public ClassifierDescriptor resolveClass(JetScope scope, JetUserType userType, BindingTrace trace) {
Collection<? extends DeclarationDescriptor> descriptors = qualifiedExpressionResolver Collection<? extends DeclarationDescriptor> descriptors = qualifiedExpressionResolver.lookupDescriptorsForUserType(userType, scope, trace);
.lookupDescriptorsForUserType(userType, scope, trace);
for (DeclarationDescriptor descriptor : descriptors) { for (DeclarationDescriptor descriptor : descriptors) {
if (descriptor instanceof ClassifierDescriptor) { if (descriptor instanceof ClassifierDescriptor) {
if (descriptor instanceof ClassDescriptor && !Visibilities.isVisible((ClassDescriptor)descriptor, scope.getContainingDeclaration())) {
JetSimpleNameExpression referenceExpression = userType.getReferenceExpression();
assert referenceExpression != null;
trace.report(INVISIBLE_MEMBER.on(referenceExpression, descriptor, ((ClassDescriptor)descriptor).getContainingDeclaration()));
}
return (ClassifierDescriptor) descriptor; return (ClassifierDescriptor) descriptor;
} }
} }
@@ -352,6 +352,12 @@ public class CallResolver {
continue; continue;
} }
if (!Visibilities.isVisible(candidate, context.scope.getContainingDeclaration())) {
candidateCall.setStatus(OTHER_ERROR);
context.tracing.invisibleMember(context.trace, candidate);
continue;
}
boolean errorInArgumentMapping = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(context.call, context.tracing, candidateCall); boolean errorInArgumentMapping = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(context.call, context.tracing, candidateCall);
if (errorInArgumentMapping) { if (errorInArgumentMapping) {
candidateCall.setStatus(OTHER_ERROR); candidateCall.setStatus(OTHER_ERROR);
@@ -21,6 +21,7 @@ import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BindingTrace;
@@ -224,5 +225,11 @@ public class ResolutionTask<D extends CallableDescriptor> extends ResolutionCont
trace.report(DANGLING_FUNCTION_LITERAL_ARGUMENT_SUSPECTED.on(functionLiteralArgument)); trace.report(DANGLING_FUNCTION_LITERAL_ARGUMENT_SUSPECTED.on(functionLiteralArgument));
} }
} }
@Override
public void invisibleMember(@NotNull BindingTrace trace, @NotNull DeclarationDescriptor descriptor) {
JetExpression expression = call.getCalleeExpression();
trace.report(INVISIBLE_MEMBER.on(expression != null ? expression : call.getCallElement(), descriptor, descriptor.getContainingDeclaration()));
}
}; };
} }
@@ -82,18 +82,40 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
List<ResolutionTask<D>> result = Lists.newArrayList(); List<ResolutionTask<D>> result = Lists.newArrayList();
ReceiverDescriptor explicitReceiver = context.call.getExplicitReceiver(); ReceiverDescriptor explicitReceiver = context.call.getExplicitReceiver();
JetScope scope = context.scope; final JetScope scope;
if (explicitReceiver.exists() && explicitReceiver.getType() instanceof NamespaceType) { if (explicitReceiver.exists() && explicitReceiver.getType() instanceof NamespaceType) {
// Receiver is a namespace // Receiver is a namespace
scope = explicitReceiver.getType().getMemberScope(); scope = explicitReceiver.getType().getMemberScope();
explicitReceiver = NO_RECEIVER; explicitReceiver = NO_RECEIVER;
} }
doComputeTasks(scope, explicitReceiver, name, result, context, functionReference); else {
scope = context.scope;
}
final Predicate<ResolvedCallImpl<D>> visibleStrategy = new Predicate<ResolvedCallImpl<D>>() {
@Override
public boolean apply(@Nullable ResolvedCallImpl<D> call) {
if (call == null) return false;
D candidateDescriptor = call.getCandidateDescriptor();
if (ErrorUtils.isError(candidateDescriptor)) return true;
return Visibilities.isVisible(candidateDescriptor, scope.getContainingDeclaration());
}
};
Predicate<ResolvedCallImpl<D>> invisibleStrategy = new Predicate<ResolvedCallImpl<D>>() {
@Override
public boolean apply(@Nullable ResolvedCallImpl<D> call) {
return !visibleStrategy.apply(call);
}
};
doComputeTasks(scope, explicitReceiver, name, result, context, functionReference, visibleStrategy);
doComputeTasks(scope, explicitReceiver, name, result, context, functionReference, invisibleStrategy);
return result; return result;
} }
private void doComputeTasks(JetScope scope, ReceiverDescriptor receiver, String name, List<ResolutionTask<D>> result, @NotNull BasicResolutionContext context, @NotNull JetReferenceExpression functionReference) { private void doComputeTasks(@NotNull JetScope scope, @NotNull ReceiverDescriptor receiver,
@NotNull String name, @NotNull List<ResolutionTask<D>> result,
@NotNull BasicResolutionContext context, @NotNull JetReferenceExpression functionReference,
@NotNull Predicate<ResolvedCallImpl<D>> filterStrategy) {
AutoCastServiceImpl autoCastService = new AutoCastServiceImpl(context.dataFlowInfo, context.trace.getBindingContext()); AutoCastServiceImpl autoCastService = new AutoCastServiceImpl(context.dataFlowInfo, context.trace.getBindingContext());
DataFlowInfo dataFlowInfo = autoCastService.getDataFlowInfo(); DataFlowInfo dataFlowInfo = autoCastService.getDataFlowInfo();
List<ReceiverDescriptor> implicitReceivers = Lists.newArrayList(); List<ReceiverDescriptor> implicitReceivers = Lists.newArrayList();
@@ -117,21 +139,21 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
// If the call is of the form super.foo(), it can actually be only a member // If the call is of the form super.foo(), it can actually be only a member
// But if there's no appropriate member, we would like to report that super cannot be a receiver for an extension // But if there's no appropriate member, we would like to report that super cannot be a receiver for an extension
// Thus, put members first // Thus, put members first
addTask(result, members, context, functionReference); addTask(result, members, context, functionReference, filterStrategy);
addTask(result, locals, context, functionReference); addTask(result, locals, context, functionReference, filterStrategy);
} }
else { else {
addTask(result, locals, context, functionReference); addTask(result, locals, context, functionReference, filterStrategy);
addTask(result, members, context, functionReference); addTask(result, members, context, functionReference, filterStrategy);
} }
for (ReceiverDescriptor implicitReceiver : implicitReceivers) { for (ReceiverDescriptor implicitReceiver : implicitReceivers) {
Collection<D> memberExtensions = getExtensionsByName(implicitReceiver.getType().getMemberScope(), name); Collection<D> memberExtensions = getExtensionsByName(implicitReceiver.getType().getMemberScope(), name);
List<ReceiverDescriptor> variantsForImplicitReceiver = autoCastService.getVariantsForReceiver(implicitReceiver); List<ReceiverDescriptor> variantsForImplicitReceiver = autoCastService.getVariantsForReceiver(implicitReceiver);
addTask(result, convertWithReceivers(memberExtensions, variantsForImplicitReceiver, variantsForExplicitReceiver), context, functionReference); addTask(result, convertWithReceivers(memberExtensions, variantsForImplicitReceiver, variantsForExplicitReceiver), context, functionReference, filterStrategy);
} }
addTask(result, nonlocals, context, functionReference); addTask(result, nonlocals, context, functionReference, filterStrategy);
} }
else { else {
Collection<ResolvedCallImpl<D>> functions = convertWithImpliedThis(scope, Collections.singletonList(receiver), getNonExtensionsByName(scope, name)); Collection<ResolvedCallImpl<D>> functions = convertWithImpliedThis(scope, Collections.singletonList(receiver), getNonExtensionsByName(scope, name));
@@ -141,13 +163,13 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
//noinspection unchecked,RedundantTypeArguments //noinspection unchecked,RedundantTypeArguments
TaskPrioritizer.<D>splitLexicallyLocalDescriptors(functions, scope.getContainingDeclaration(), locals, nonlocals); TaskPrioritizer.<D>splitLexicallyLocalDescriptors(functions, scope.getContainingDeclaration(), locals, nonlocals);
addTask(result, locals, context, functionReference); addTask(result, locals, context, functionReference, filterStrategy);
for (ReceiverDescriptor implicitReceiver : implicitReceivers) { for (ReceiverDescriptor implicitReceiver : implicitReceivers) {
doComputeTasks(scope, implicitReceiver, name, result, context, functionReference); doComputeTasks(scope, implicitReceiver, name, result, context, functionReference, filterStrategy);
} }
addTask(result, nonlocals, context, functionReference); addTask(result, nonlocals, context, functionReference, filterStrategy);
} }
} }
@@ -215,18 +237,14 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
return false; return false;
} }
private void addTask(@NotNull List<ResolutionTask<D>> result, @NotNull Collection<ResolvedCallImpl<D>> candidates, @NotNull final BasicResolutionContext context, @NotNull JetReferenceExpression functionReference) { private void addTask(@NotNull List<ResolutionTask<D>> result,
Collection<ResolvedCallImpl<D>> visibleCandidates = Collections2.filter(candidates, new Predicate<ResolvedCallImpl<D>>() { @NotNull Collection<ResolvedCallImpl<D>> candidates,
@Override @NotNull final BasicResolutionContext context,
public boolean apply(@Nullable ResolvedCallImpl<D> call) { @NotNull JetReferenceExpression functionReference,
if (call == null) return false; @NotNull Predicate<ResolvedCallImpl<D>> filterStrategy) {
D candidateDescriptor = call.getCandidateDescriptor(); Collection<ResolvedCallImpl<D>> filteredCandidates = Collections2.filter(candidates, filterStrategy);
if (ErrorUtils.isError(candidateDescriptor)) return true; if (filteredCandidates.isEmpty()) return;
return Visibilities.isVisible(candidateDescriptor, context.scope.getContainingDeclaration()); result.add(new ResolutionTask<D>(filteredCandidates, functionReference, context));
}
});
if (visibleCandidates.isEmpty()) return;
result.add(new ResolutionTask<D>(visibleCandidates, functionReference, context));
} }
@NotNull @NotNull
@@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.resolve.calls;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BindingTrace;
@@ -77,6 +78,9 @@ import java.util.List;
@Override @Override
public void danglingFunctionLiteralArgumentSuspected(@NotNull BindingTrace trace, @NotNull List<JetExpression> functionLiteralArguments) {} public void danglingFunctionLiteralArgumentSuspected(@NotNull BindingTrace trace, @NotNull List<JetExpression> functionLiteralArguments) {}
@Override
public void invisibleMember(@NotNull BindingTrace trace, @NotNull DeclarationDescriptor descriptor) {}
}; };
<D extends CallableDescriptor> void bindReference(@NotNull BindingTrace trace, @NotNull ResolvedCallImpl<D> resolvedCall); <D extends CallableDescriptor> void bindReference(@NotNull BindingTrace trace, @NotNull ResolvedCallImpl<D> resolvedCall);
@@ -108,4 +112,6 @@ import java.util.List;
void unnecessarySafeCall(@NotNull BindingTrace trace, @NotNull JetType type); void unnecessarySafeCall(@NotNull BindingTrace trace, @NotNull JetType type);
void danglingFunctionLiteralArgumentSuspected(@NotNull BindingTrace trace, @NotNull List<JetExpression> functionLiteralArguments); void danglingFunctionLiteralArgumentSuspected(@NotNull BindingTrace trace, @NotNull List<JetExpression> functionLiteralArguments);
void invisibleMember(@NotNull BindingTrace trace, @NotNull DeclarationDescriptor descriptor);
} }
@@ -12,13 +12,13 @@ val mc = MyJavaClass()
//FILE: b.kt //FILE: b.kt
package b package b
import a.MyJavaClass import a.<!INVISIBLE_REFERENCE!>MyJavaClass<!>
val mc1 = <!UNRESOLVED_REFERENCE!>MyJavaClass<!>() val mc1 = <!INVISIBLE_MEMBER!>MyJavaClass<!>()
//FILE: c.kt //FILE: c.kt
package a.c package a.c
import a.MyJavaClass import a.<!INVISIBLE_REFERENCE!>MyJavaClass<!>
val mc1 = <!UNRESOLVED_REFERENCE!>MyJavaClass<!>() val mc1 = <!INVISIBLE_MEMBER!>MyJavaClass<!>()
@@ -6,13 +6,13 @@ package example;
fun test() { fun test() {
val p = test.Public() val p = test.Public()
if (p.public is Int) <!AUTOCAST_IMPOSSIBLE!>p.public<!> + 1 if (p.public is Int) <!AUTOCAST_IMPOSSIBLE!>p.public<!> + 1
if (p.<!UNRESOLVED_REFERENCE!>protected<!> is Int) p.<!UNRESOLVED_REFERENCE!>protected<!> + 1 if (p.<!INVISIBLE_MEMBER!>protected<!> is Int) <!AUTOCAST_IMPOSSIBLE!>p.<!INVISIBLE_MEMBER!>protected<!><!> + 1
if (p.<!UNRESOLVED_REFERENCE!>i_protected<!> is Int) p.<!UNRESOLVED_REFERENCE!>i_protected<!> + 1 if (p.<!INVISIBLE_MEMBER!>i_protected<!> is Int) p.<!INVISIBLE_MEMBER!>i_protected<!> + 1
if (p.internal is Int) p.internal + 1 if (p.internal is Int) p.internal + 1
val i = test.Public() val i = test.Public()
if (i.public is Int) <!AUTOCAST_IMPOSSIBLE!>i.public<!> + 1 if (i.public is Int) <!AUTOCAST_IMPOSSIBLE!>i.public<!> + 1
if (i.<!UNRESOLVED_REFERENCE!>protected<!> is Int) i.<!UNRESOLVED_REFERENCE!>protected<!> + 1 if (i.<!INVISIBLE_MEMBER!>protected<!> is Int) <!AUTOCAST_IMPOSSIBLE!>i.<!INVISIBLE_MEMBER!>protected<!><!> + 1
if (i.<!UNRESOLVED_REFERENCE!>i_protected<!> is Int) i.<!UNRESOLVED_REFERENCE!>i_protected<!> + 1 if (i.<!INVISIBLE_MEMBER!>i_protected<!> is Int) i.<!INVISIBLE_MEMBER!>i_protected<!> + 1
if (i.internal is Int) i.internal + 1 if (i.internal is Int) i.internal + 1
} }
@@ -11,6 +11,6 @@ class C() {
fun box(): String { fun box(): String {
val c = C() val c = C()
if (c.<!UNRESOLVED_REFERENCE!>f<!> != 610) return "fail" if (c.<!INVISIBLE_MEMBER!>f<!> != 610) return "fail"
return "OK" return "OK"
} }
@@ -35,8 +35,8 @@ class B {
} }
fun test3(a: A) { fun test3(a: A) {
a.<!UNRESOLVED_REFERENCE!>v<!> //todo .bMethod() a.<!INVISIBLE_MEMBER!>v<!> //todo .bMethod()
a.<!UNRESOLVED_REFERENCE!>f<!>(0, 1) //todo .bMethod() a.<!INVISIBLE_MEMBER!>f<!>(0, 1) //todo .bMethod()
} }
trait T trait T
@@ -49,7 +49,7 @@ open class C : T {
} }
fun test4(c: C) { fun test4(c: C) {
c.<!UNRESOLVED_REFERENCE!>i<!>++ c.<!INVISIBLE_MEMBER!>i<!>++
} }
class D : C() { class D : C() {
@@ -73,7 +73,7 @@ class F : C() {
class G : T { class G : T {
fun test8(c: C) { fun test8(c: C) {
doSmth(c.<!UNRESOLVED_REFERENCE!>i<!>) doSmth(c.<!INVISIBLE_MEMBER!>i<!>)
} }
} }
@@ -86,5 +86,5 @@ import test_visibility.*
fun test() { fun test() {
internal_fun() internal_fun()
<!UNRESOLVED_REFERENCE!>private_fun<!>() <!INVISIBLE_MEMBER!>private_fun<!>()
} }
@@ -15,20 +15,23 @@ private object PO {}
//+JDK //+JDK
package b package b
import a.* import a.<!INVISIBLE_REFERENCE!>A<!>
import a.<!INVISIBLE_REFERENCE!>foo<!>
import a.makeA
import a.<!INVISIBLE_REFERENCE!>PO<!>
fun test() { fun test() {
val y = makeA() val y = makeA()
y.<!UNRESOLVED_REFERENCE!>bar<!>() y.<!INVISIBLE_MEMBER!>bar<!>()
<!UNRESOLVED_REFERENCE!>foo<!>() <!INVISIBLE_MEMBER!>foo<!>()
val <!UNUSED_VARIABLE!>u<!> : <!INVISIBLE_MEMBER!>A<!> = <!UNRESOLVED_REFERENCE!>A<!>() val <!UNUSED_VARIABLE!>u<!> : <!INVISIBLE_REFERENCE!>A<!> = <!INVISIBLE_MEMBER!>A<!>()
val <!UNUSED_VARIABLE!>a<!> : java.util.Arrays.<!INVISIBLE_MEMBER!>ArrayList<!><Int>; val <!UNUSED_VARIABLE!>a<!> : java.util.Arrays.<!INVISIBLE_REFERENCE!>ArrayList<!><Int>;
val <!UNUSED_VARIABLE!>po<!> = <!UNRESOLVED_REFERENCE!>PO<!>() val <!UNUSED_VARIABLE!>po<!> = <!INVISIBLE_MEMBER!>PO<!>
} }
class B : <!INVISIBLE_MEMBER!>A<!>() {} class B : <!INVISIBLE_REFERENCE, INVISIBLE_MEMBER!>A<!>() {}
class Q { class Q {
class W { class W {
@@ -41,4 +44,4 @@ class Q {
//check that 'toString' can be invoked without specifying return type //check that 'toString' can be invoked without specifying return type
class NewClass : java.util.ArrayList<Integer>() { class NewClass : java.util.ArrayList<Integer>() {
public override fun toString() = "a" public override fun toString() = "a"
} }