Introduced QualifierReceiver instead of PackageType

This commit is contained in:
Svetlana Isakova
2014-08-02 15:52:44 +04:00
parent cc92589378
commit 8289f13016
32 changed files with 401 additions and 382 deletions
@@ -229,6 +229,13 @@ public fun JetSimpleNameExpression.getQualifiedElement(): JetElement {
}
}
public fun JetSimpleNameExpression.getTopmostParentQualifiedExpressionForSelector(): JetQualifiedExpression? {
return stream<JetExpression>(this) {
val parentQualified = it.getParent() as? JetQualifiedExpression
if (parentQualified?.getSelectorExpression() == it) parentQualified else null
}.last() as? JetQualifiedExpression
}
/**
* Returns rightmost selector of the qualified element (null if there is no such selector)
*/
@@ -34,6 +34,7 @@ import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.QualifierReceiver;
import org.jetbrains.jet.lang.types.DeferredType;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.expressions.CaptureKind;
@@ -84,6 +85,8 @@ public interface BindingContext {
WritableSlice<JetExpression, DataFlowInfo> EXPRESSION_DATA_FLOW_INFO = new BasicWritableSlice<JetExpression, DataFlowInfo>(DO_NOTHING);
WritableSlice<JetExpression, DataFlowInfo> DATAFLOW_INFO_AFTER_CONDITION = Slices.createSimpleSlice();
WritableSlice<JetExpression, QualifierReceiver> QUALIFIER_RECEIVER = new BasicWritableSlice<JetExpression, QualifierReceiver>(DO_NOTHING);
WritableSlice<JetReferenceExpression, DeclarationDescriptor> REFERENCE_TARGET =
new BasicWritableSlice<JetReferenceExpression, DeclarationDescriptor>(DO_NOTHING);
@@ -20,19 +20,10 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
import org.jetbrains.jet.lang.descriptors.PackageViewDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.SubpackagesScope;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.SpecialNames;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.jet.lang.types.PackageType;
public class JetModuleUtil {
public static PackageType getRootPackageType(JetElement expression) {
// TODO: this is a stub: at least the modules' root packages must be indexed here
return new PackageType(SpecialNames.ROOT_PACKAGE, JetScope.EMPTY, ReceiverValue.NO_RECEIVER);
}
public static JetScope getSubpackagesOfRootScope(@NotNull ModuleDescriptor module) {
return getRootPackageScope(module, /* scopeIncludingMembers = */ false);
}
@@ -24,8 +24,10 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.evaluate.ConstantExpressionEvaluator;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.psi.codeFragmentUtil.CodeFragmentUtilPackage;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage;
import org.jetbrains.jet.lang.resolve.calls.context.BasicCallResolutionContext;
import org.jetbrains.jet.lang.resolve.calls.context.CheckValueArgumentsMode;
import org.jetbrains.jet.lang.resolve.calls.context.ResolutionContext;
@@ -37,32 +39,27 @@ import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
import org.jetbrains.jet.lang.resolve.calls.util.FakeCallableDescriptorForObject;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.constants.IntegerValueConstant;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.ChainedScope;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.JetScopeImpl;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.QualifierReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiversPackage;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.JetTypeInfo;
import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lang.types.expressions.BasicExpressionTypingVisitor;
import org.jetbrains.jet.lang.types.expressions.DataFlowUtils;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingContext;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.utils.Printer;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
import static org.jetbrains.jet.lang.psi.JetPsiUtil.isLHSOfDot;
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getStaticNestedClassesScope;
import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.INDEPENDENT;
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue.NO_RECEIVER;
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiversPackage.*;
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
public class CallExpressionResolver {
@@ -74,156 +71,6 @@ public class CallExpressionResolver {
this.expressionTypingServices = expressionTypingServices;
}
@Nullable
private JetType lookupPackageOrClassObject(@NotNull JetSimpleNameExpression expression, @NotNull ExpressionTypingContext context) {
Name referencedName = expression.getReferencedNameAsName();
final ClassifierDescriptor classifier = context.scope.getClassifier(referencedName);
if (classifier != null) {
JetType classObjectType = classifier.getClassObjectType();
if (classObjectType != null) {
context.trace.record(REFERENCE_TARGET, expression, classifier);
JetType result = getExtendedClassObjectType(expression, classObjectType, classifier, context.scope);
checkClassObjectVisibility(classifier, expression, context);
return result;
}
}
JetType[] result = new JetType[1];
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(
context.trace, "trace for package/class object lookup of name", referencedName);
if (furtherNameLookup(expression, result, context.replaceBindingTrace(temporaryTrace))) {
temporaryTrace.commit();
return DataFlowUtils.checkType(result[0], expression, context);
}
// To report NO_CLASS_OBJECT when no package found
if (classifier != null) {
if (classifier instanceof TypeParameterDescriptor) {
if (isLHSOfDot(expression)) {
context.trace.report(TYPE_PARAMETER_ON_LHS_OF_DOT.on(expression, (TypeParameterDescriptor) classifier));
}
else {
context.trace.report(TYPE_PARAMETER_IS_NOT_AN_EXPRESSION.on(expression, (TypeParameterDescriptor) classifier));
}
}
else if (!isLHSOfDot(expression)) {
context.trace.report(NO_CLASS_OBJECT.on(expression, classifier));
}
context.trace.record(REFERENCE_TARGET, expression, classifier);
JetScope scopeForStaticMembersResolution =
classifier instanceof ClassDescriptor
? getStaticNestedClassesScope((ClassDescriptor) classifier)
: new JetScopeImpl() {
@NotNull
@Override
public DeclarationDescriptor getContainingDeclaration() {
return classifier;
}
@Override
public String toString() {
return "Scope for the type parameter on the left hand side of dot";
}
@Override
public void printScopeStructure(@NotNull Printer p) {
p.println(toString(), " for ", classifier);
}
};
return new PackageType(referencedName, scopeForStaticMembersResolution, NO_RECEIVER);
}
temporaryTrace.commit();
return result[0];
}
private static void checkClassObjectVisibility(
@NotNull ClassifierDescriptor classifier,
@NotNull JetSimpleNameExpression expression,
@NotNull ExpressionTypingContext context
) {
if (!(classifier instanceof ClassDescriptor)) return;
ClassDescriptor classObject = ((ClassDescriptor) classifier).getClassObjectDescriptor();
assert classObject != null : "This check should be done only for classes with class objects: " + classifier;
DeclarationDescriptor from = context.scope.getContainingDeclaration();
if (!Visibilities.isVisible(classObject, from)) {
context.trace.report(INVISIBLE_MEMBER.on(expression, classObject, classObject.getVisibility(), from));
}
}
@NotNull
private static JetType getExtendedClassObjectType(
@NotNull JetSimpleNameExpression expression,
@NotNull JetType classObjectType,
@NotNull ClassifierDescriptor classifier,
@NotNull JetScope receiverScope
) {
if (!isLHSOfDot(expression) || !(classifier instanceof ClassDescriptor)) {
return classObjectType;
}
ClassDescriptor classDescriptor = (ClassDescriptor) classifier;
if (classDescriptor.getKind() == ClassKind.ENUM_ENTRY) {
return classObjectType;
}
List<JetScope> scopes = new ArrayList<JetScope>(3);
scopes.add(classObjectType.getMemberScope());
scopes.add(getStaticNestedClassesScope(classDescriptor));
Name referencedName = expression.getReferencedNameAsName();
PackageViewDescriptor packageView = receiverScope.getPackage(referencedName);
if (packageView != null) {
//for enums loaded from java binaries
scopes.add(packageView.getMemberScope());
}
JetScope scope = new ChainedScope(
classifier, "Member scope for extended class object type " + classifier, scopes.toArray(new JetScope[scopes.size()])
);
return new PackageType(referencedName, scope, new ExpressionReceiver(expression, classObjectType));
}
private boolean furtherNameLookup(
@NotNull JetSimpleNameExpression expression,
@NotNull JetType[] result,
@NotNull ResolutionContext context
) {
PackageType packageType = lookupPackageType(expression, context);
if (packageType == null) {
return false;
}
if (isLHSOfDot(expression)) {
result[0] = packageType;
return true;
}
context.trace.report(EXPRESSION_EXPECTED_PACKAGE_FOUND.on(expression));
result[0] = ErrorUtils.createErrorType("Type for " + expression.getReferencedNameAsName());
return false;
}
@Nullable
private PackageType lookupPackageType(@NotNull JetSimpleNameExpression expression, @NotNull ResolutionContext context) {
Name name = expression.getReferencedNameAsName();
PackageViewDescriptor packageView = context.scope.getPackage(name);
if (packageView == null) {
return null;
}
context.trace.record(REFERENCE_TARGET, expression, packageView);
// Construct a PackageType with everything from the package and with nested classes of the corresponding class (if any)
JetScope scope;
ClassifierDescriptor classifier = context.scope.getClassifier(name);
if (classifier instanceof ClassDescriptor) {
scope = new ChainedScope(
packageView, "Package type member scope for " + expression.getText(), packageView.getMemberScope(), getStaticNestedClassesScope((ClassDescriptor) classifier)
);
}
else {
scope = packageView.getMemberScope();
}
return new PackageType(name, scope, NO_RECEIVER);
}
@Nullable
public ResolvedCall<FunctionDescriptor> getResolvedCallForFunction(
@NotNull Call call, @NotNull JetExpression callExpression,
@@ -254,36 +101,27 @@ public class CallExpressionResolver {
context.replaceTraceAndCache(temporaryForVariable),
call, CheckValueArgumentsMode.ENABLED);
OverloadResolutionResults<VariableDescriptor> resolutionResult = callResolver.resolveSimpleProperty(contextForVariable);
JetScope receiverScope = receiver.exists() ? receiver.getType().getMemberScope() : context.scope;
if (resolutionResult.isSuccess()) {
result[0] = true;
if (resolutionResult.getResultingDescriptor() instanceof FakeCallableDescriptorForObject) {
FakeCallableDescriptorForObject fakeCallableDescriptorForObject =
(FakeCallableDescriptorForObject) resolutionResult.getResultingDescriptor();
ClassDescriptor classDescriptor = fakeCallableDescriptorForObject.getClassDescriptor();
context.trace.record(REFERENCE_TARGET, nameExpression, classDescriptor);
checkClassObjectVisibility(classDescriptor, nameExpression, context);
return getExtendedClassObjectType(nameExpression, fakeCallableDescriptorForObject.getType(), classDescriptor, receiverScope);
// if the expression is a receiver in a qualified expression, it should be resolved after the selector is resolved
boolean isLHSOfDot = JetPsiUtil.isLHSOfDot(nameExpression);
if (!resolutionResult.isNothing()) {
boolean isQualifier = isLHSOfDot && resolutionResult.isSingleResult()
&& resolutionResult.getResultingDescriptor() instanceof FakeCallableDescriptorForObject;
if (!isQualifier) {
result[0] = true;
temporaryForVariable.commit();
checkSuper(receiver, resolutionResult, context.trace, nameExpression);
return resolutionResult.isSingleResult() ? resolutionResult.getResultingDescriptor().getReturnType() : null;
}
temporaryForVariable.commit();
checkSuper(receiver, resolutionResult, context.trace, nameExpression);
return resolutionResult.getResultingDescriptor().getReturnType();
}
ExpressionTypingContext newContext = context.replaceScope(receiverScope);
TemporaryTraceAndCache temporaryForPackageOrClassObject = TemporaryTraceAndCache.create(
context, "trace to resolve as package or class object", nameExpression);
JetType jetType = lookupPackageOrClassObject(nameExpression, newContext.replaceTraceAndCache(temporaryForPackageOrClassObject));
if (jetType != null) {
temporaryForPackageOrClassObject.commit();
// Uncommitted changes in temp context
context.trace.record(RESOLUTION_SCOPE, nameExpression, context.scope);
if (context.dataFlowInfo.hasTypeInfoConstraints()) {
context.trace.record(NON_DEFAULT_EXPRESSION_DATA_FLOW, nameExpression, context.dataFlowInfo);
}
QualifierReceiver qualifierReceiver = createQualifierReceiver(nameExpression, receiver, context);
if (qualifierReceiver != null) {
result[0] = true;
return jetType;
if (!isLHSOfDot) {
resolveAsStandaloneExpression(qualifierReceiver, context);
}
return null;
}
temporaryForVariable.commit();
result[0] = !resolutionResult.isNothing();
@@ -301,9 +139,6 @@ public class CallExpressionResolver {
JetType type = getVariableType(nameExpression, receiver, callOperationNode, context.replaceTraceAndCache(temporaryForVariable), result);
if (result[0]) {
temporaryForVariable.commit();
if (type instanceof PackageType && !isLHSOfDot(nameExpression)) {
type = null;
}
return JetTypeInfo.create(type, context.dataFlowInfo);
}
@@ -425,7 +260,7 @@ public class CallExpressionResolver {
private JetTypeInfo getSelectorReturnTypeInfo(
@NotNull ReceiverValue receiver,
@Nullable ASTNode callOperationNode,
@NotNull JetExpression selectorExpression,
@Nullable JetExpression selectorExpression,
@NotNull ExpressionTypingContext context
) {
if (selectorExpression instanceof JetCallExpression) {
@@ -435,7 +270,7 @@ public class CallExpressionResolver {
else if (selectorExpression instanceof JetSimpleNameExpression) {
return getSimpleNameExpressionTypeInfo((JetSimpleNameExpression) selectorExpression, receiver, callOperationNode, context);
}
else {
else if (selectorExpression != null) {
context.trace.report(ILLEGAL_SELECTOR.on(selectorExpression, selectorExpression.getText()));
}
return JetTypeInfo.create(null, context.dataFlowInfo);
@@ -451,18 +286,21 @@ public class CallExpressionResolver {
ResolutionContext contextForReceiver = context.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
JetTypeInfo receiverTypeInfo = expressionTypingServices.getTypeInfo(receiverExpression, contextForReceiver);
JetType receiverType = receiverTypeInfo.getType();
if (selectorExpression == null) return JetTypeInfo.create(null, context.dataFlowInfo);
QualifierReceiver qualifierReceiver = context.trace.get(BindingContext.QUALIFIER_RECEIVER, receiverExpression);
if (receiverType == null) receiverType = ErrorUtils.createErrorType("Type for " + expression.getText());
context = context.replaceDataFlowInfo(receiverTypeInfo.getDataFlowInfo());
ReceiverValue receiver = qualifierReceiver == null ? new ExpressionReceiver(receiverExpression, receiverType) : qualifierReceiver;
JetTypeInfo selectorReturnTypeInfo = getSelectorReturnTypeInfo(
new ExpressionReceiver(receiverExpression, receiverType),
expression.getOperationTokenNode(), selectorExpression, context);
receiver, expression.getOperationTokenNode(), selectorExpression, context);
JetType selectorReturnType = selectorReturnTypeInfo.getType();
resolveDeferredReceiverInQualifiedExpression(qualifierReceiver, expression, context);
//TODO move further
if (!(receiverType instanceof PackageType) && expression.getOperationSign() == JetTokens.SAFE_ACCESS) {
if (expression.getOperationSign() == JetTokens.SAFE_ACCESS) {
if (selectorReturnType != null && !KotlinBuiltIns.getInstance().isUnit(selectorReturnType)) {
if (receiverType.isNullable()) {
selectorReturnType = TypeUtils.makeNullable(selectorReturnType);
@@ -486,4 +324,18 @@ public class CallExpressionResolver {
}
return typeInfo;
}
private static void resolveDeferredReceiverInQualifiedExpression(
@Nullable QualifierReceiver qualifierReceiver,
@NotNull JetQualifiedExpression qualifiedExpression,
@NotNull ExpressionTypingContext context
) {
if (qualifierReceiver == null) return;
JetExpression calleeExpression =
JetPsiUtil.deparenthesize(CallUtilPackage.getCalleeExpressionIfAny(qualifiedExpression.getSelectorExpression()), false);
DeclarationDescriptor selectorDescriptor =
calleeExpression instanceof JetReferenceExpression
? context.trace.get(BindingContext.REFERENCE_TARGET, (JetReferenceExpression) calleeExpression) : null;
ReceiversPackage.resolveAsReceiverInQualifiedExpression(qualifierReceiver, context, selectorDescriptor);
}
}
@@ -154,7 +154,7 @@ public class DataFlowValueFactory {
return getIdForThisReceiver(declarationDescriptor);
}
else if (expression instanceof JetRootPackageExpression) {
return createPackageInfo(JetModuleUtil.getRootPackageType(expression));
//todo return createPackageInfo());
}
return NO_IDENTIFIER_INFO;
}
@@ -19,7 +19,6 @@ package org.jetbrains.jet.lang.resolve.calls.tasks;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.intellij.openapi.progress.ProgressIndicatorProvider;
import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
@@ -32,14 +31,13 @@ import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.JetScopeUtils;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.QualifierReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.PackageType;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -84,25 +82,22 @@ public class TaskPrioritizer {
@NotNull TracingStrategy tracing,
@NotNull CallableDescriptorCollectors<D> callableDescriptorCollectors
) {
List<Pair<JetScope, ReceiverValue>> variants = new ArrayList<Pair<JetScope, ReceiverValue>>(2);
ReceiverValue explicitReceiver = context.call.getExplicitReceiver();
if (explicitReceiver.exists() && explicitReceiver.getType() instanceof PackageType) {
JetType receiverType = explicitReceiver.getType();
variants.add(Pair.create(receiverType.getMemberScope(), NO_RECEIVER));
ReceiverValue value = ((PackageType) receiverType).getReceiverValue();
if (value.exists()) {
variants.add(Pair.create(context.scope, value));
ResolutionTaskHolder<D, F> result =
new ResolutionTaskHolder<D, F>(context, new MyPriorityProvider<D>(context), tracing);
TaskPrioritizerContext<D, F> taskPrioritizerContext =
new TaskPrioritizerContext<D, F>(name, result, context, context.scope, callableDescriptorCollectors);
if (explicitReceiver instanceof QualifierReceiver) {
QualifierReceiver qualifierReceiver = (QualifierReceiver) explicitReceiver;
doComputeTasks(NO_RECEIVER, taskPrioritizerContext.replaceScope(qualifierReceiver.getNestedClassesAndPackageMembersScope()));
ReceiverValue classObjectReceiver = qualifierReceiver.getClassObjectReceiver();
if (classObjectReceiver.exists()) {
doComputeTasks(classObjectReceiver, taskPrioritizerContext);
}
}
else {
variants.add(Pair.create(context.scope, explicitReceiver));
}
ResolutionTaskHolder<D, F> result =
new ResolutionTaskHolder<D, F>(context, new MyPriorityProvider<D>(context), tracing);
for (Pair<JetScope, ReceiverValue> pair : variants) {
doComputeTasks(pair.second, new TaskPrioritizerContext<D, F>(name, result, context, pair.first, callableDescriptorCollectors));
doComputeTasks(explicitReceiver, taskPrioritizerContext);
}
return result.getTasks();
@@ -401,5 +396,9 @@ public class TaskPrioritizer {
this.scope = scope;
this.callableDescriptorCollectors = callableDescriptorCollectors;
}
private TaskPrioritizerContext<D, F> replaceScope(JetScope newScope) {
return new TaskPrioritizerContext<D, F>(name, result, context, newScope, callableDescriptorCollectors);
}
}
}
@@ -114,12 +114,12 @@ public fun Call.getValueArgumentForExpression(expression: JetExpression): ValueA
// Get call / resolved call from binding context
public fun JetElement.getCalleeExpressionIfAny(): JetExpression? {
public fun JetElement?.getCalleeExpressionIfAny(): JetExpression? {
val element = if (this is JetExpression) JetPsiUtil.safeDeparenthesize(this, false) else this
return when (element) {
is JetSimpleNameExpression -> element
is JetCallElement -> element.getCalleeExpression()
is JetQualifiedExpression -> element.getSelectorExpression()?.getCalleeExpressionIfAny()
is JetQualifiedExpression -> element.getSelectorExpression().getCalleeExpressionIfAny()
is JetOperationExpression -> element.getOperationReference()
else -> null
}
@@ -0,0 +1,163 @@
/*
* Copyright 2010-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.scopes.receivers
import org.jetbrains.jet.lang.types.JetType
import org.jetbrains.jet.lang.descriptors.PackageViewDescriptor
import org.jetbrains.jet.lang.resolve.scopes.JetScope
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression
import org.jetbrains.jet.lang.descriptors.ClassDescriptor
import org.jetbrains.jet.lang.descriptors.ClassKind
import org.jetbrains.jet.lang.resolve.DescriptorUtils
import org.jetbrains.jet.lang.resolve.DescriptorUtils.getFqName
import org.jetbrains.jet.lang.resolve.name.Name
import org.jetbrains.jet.lang.resolve.scopes.ChainedScope
import java.util.ArrayList
import org.jetbrains.jet.utils.addIfNotNull
import org.jetbrains.jet.lang.resolve.BindingContext.*
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor
import org.jetbrains.jet.lang.diagnostics.Errors.*
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor
import org.jetbrains.jet.lang.descriptors.impl.PackageFragmentDescriptorImpl
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingContext
import org.jetbrains.jet.lang.psi.psiUtil.getTopmostParentQualifiedExpressionForSelector
public class QualifierReceiver(
val expression: JetSimpleNameExpression,
val packageView: PackageViewDescriptor?,
val classifier: ClassifierDescriptor?
) : ReceiverValue {
val name: Name
get() = classifier?.getName() ?: packageView!!.getName()
fun getClassObjectReceiver(): ReceiverValue =
classifier?.getClassObjectType()?.let { ExpressionReceiver(expression, it) } ?: ReceiverValue.NO_RECEIVER
val descriptor: DeclarationDescriptor
get() = classifier ?: packageView ?: throw AssertionError("PackageView and classifier both are null")
fun getScope(): JetScope {
val scopes = listOf(classifier?.getClassObjectType()?.getMemberScope(), getNestedClassesAndPackageMembersScope()).filterNotNull().copyToArray()
return ChainedScope(descriptor, "Member scope for " + name + " as package or class or object", *scopes as Array<JetScope?>)
}
fun getNestedClassesAndPackageMembersScope(): JetScope {
val scopes = ArrayList<JetScope>(3)
scopes.addIfNotNull(classifier?.getClassObjectType()?.getMemberScope())
scopes.addIfNotNull(packageView?.getMemberScope())
if (classifier is ClassDescriptor && classifier.getKind() != ClassKind.ENUM_ENTRY) {
scopes.add(DescriptorUtils.getStaticNestedClassesScope(classifier))
}
return ChainedScope(descriptor, "Static scope for " + name + " as package or class or object", *scopes.copyToArray())
}
override fun getType(): JetType = throw IllegalStateException("No type corresponds to QualifierReceiver '$this'")
override fun exists() = true
override fun toString() = "Package{$packageView} OR Class{$classifier}"
}
fun createQualifierReceiver(
expression: JetSimpleNameExpression,
receiver: ReceiverValue,
context: ExpressionTypingContext
): QualifierReceiver? {
val receiverScope = when {
!receiver.exists() -> context.scope
receiver is QualifierReceiver -> receiver.getScope()
else -> receiver.getType().getMemberScope()
}
val name = expression.getReferencedNameAsName()
val packageViewDescriptor = receiverScope.getPackage(name)
val classifierDescriptor = receiverScope.getClassifier(name)
if (packageViewDescriptor == null && classifierDescriptor == null) return null
context.trace.record(RESOLUTION_SCOPE, expression, context.scope)
if (context.dataFlowInfo.hasTypeInfoConstraints()) {
context.trace.record(NON_DEFAULT_EXPRESSION_DATA_FLOW, expression, context.dataFlowInfo)
}
val qualifierReceiver = QualifierReceiver(expression, packageViewDescriptor, classifierDescriptor)
context.trace.record(QUALIFIER_RECEIVER, expression.getTopmostParentQualifiedExpressionForSelector() ?: expression, qualifierReceiver)
return qualifierReceiver
}
private fun QualifierReceiver.resolveAsStandaloneExpression(context: ExpressionTypingContext): JetType? {
context.trace.record(REFERENCE_TARGET, expression, resolveReferenceTarget(selector = null))
if (classifier is TypeParameterDescriptor) {
context.trace.report(TYPE_PARAMETER_IS_NOT_AN_EXPRESSION.on(expression, classifier))
}
else if (classifier is ClassDescriptor && classifier.getClassObjectType() == null) {
context.trace.report(NO_CLASS_OBJECT.on(expression, classifier))
}
else if (packageView != null) {
context.trace.report(EXPRESSION_EXPECTED_PACKAGE_FOUND.on(expression))
}
return null
}
private fun QualifierReceiver.resolveAsReceiverInQualifiedExpression(context: ExpressionTypingContext, selector: DeclarationDescriptor?) {
context.trace.record(REFERENCE_TARGET, expression, resolveReferenceTarget(selector))
if (classifier is TypeParameterDescriptor) {
context.trace.report(TYPE_PARAMETER_ON_LHS_OF_DOT.on(expression, classifier as TypeParameterDescriptor))
}
else if (classifier is ClassDescriptor && classifier.getClassObjectDescriptor() != null) {
checkClassObjectVisibility(context)
context.trace.record(EXPRESSION_TYPE, expression, classifier.getClassObjectType())
}
}
private fun QualifierReceiver.resolveReferenceTarget(selector: DeclarationDescriptor?): DeclarationDescriptor {
if (classifier is TypeParameterDescriptor) {
return classifier
}
val containingDeclaration = when {
selector is ConstructorDescriptor -> selector.getContainingDeclaration().getContainingDeclaration()
else -> selector?.getContainingDeclaration()
}
if (packageView != null && (containingDeclaration is PackageFragmentDescriptorImpl || containingDeclaration is PackageViewDescriptor)
&& getFqName(packageView) == getFqName(containingDeclaration)) {
return packageView
}
return descriptor
}
private fun QualifierReceiver.checkClassObjectVisibility(context: ExpressionTypingContext) {
if (classifier !is ClassDescriptor) return
val scopeContainer = context.scope.getContainingDeclaration()
val classObject = classifier.getClassObjectDescriptor()
assert(classObject != null) { "This check should be done only for classes with class objects: " + classifier }
if (!Visibilities.isVisible(classObject!!, scopeContainer)) {
context.trace.report(INVISIBLE_MEMBER.on(expression, classObject, classObject.getVisibility(), scopeContainer))
}
}
@@ -1221,10 +1221,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
@Override
public JetTypeInfo visitRootPackageExpression(@NotNull JetRootPackageExpression expression, ExpressionTypingContext context) {
if (JetPsiUtil.isLHSOfDot(expression)) {
return DataFlowUtils.checkType(JetModuleUtil.getRootPackageType(expression), expression, context, context.dataFlowInfo);
if (!JetPsiUtil.isLHSOfDot(expression)) {
context.trace.report(PACKAGE_IS_NOT_AN_EXPRESSION.on(expression));
}
context.trace.report(PACKAGE_IS_NOT_AN_EXPRESSION.on(expression));
return JetTypeInfo.create(null, context.dataFlowInfo);
}
@@ -231,11 +231,6 @@ public class ExpressionTypingUtils {
) {
JetType type = receiverArgument.getType();
if (type instanceof PackageType) {
// This fake class ruins standard algorithms
return false;
}
if (checkReceiverResolution(receiverArgument, type, callableDescriptor)) return true;
if (type.isNullable()) {
JetType notNullableType = TypeUtils.makeNotNullable(type);
@@ -0,0 +1,7 @@
fun Any.foo() = 1
class A {
class object
}
fun box() = if (A.foo() == 1) "OK" else "fail"
@@ -13,7 +13,7 @@ val xssss = <!EXPRESSION_EXPECTED_PACKAGE_FOUND!>foo<!>
val f = { <!NO_CLASS_OBJECT!>System<!> }
fun main(args : Array<String>) {
<!EXPRESSION_EXPECTED_PACKAGE_FOUND, VARIABLE_EXPECTED!>java<!> = null
<!EXPRESSION_EXPECTED_PACKAGE_FOUND!>java<!> = null
<!NO_CLASS_OBJECT!>System<!> = null
<!NO_CLASS_OBJECT!>System<!>!!
java.lang.<!NO_CLASS_OBJECT!>System<!> = null
@@ -0,0 +1,11 @@
enum class E {
A
B
C
}
fun foo() {
val e = E.<!SYNTAX!><!>
}
@@ -0,0 +1,30 @@
// FILE: a.kt
package a
class A
// FILE: b.kt
package b
import a.A
val A.d: Int get() = 1
// FILE: c.kt
package c
import a.A
val A.d: Int get() = 2
// FILE: d.kt
package d
import a.A
import b.d
import c.d
fun A.test() {
<!OVERLOAD_RESOLUTION_AMBIGUITY!>d<!>
}
@@ -0,0 +1,9 @@
open class A {
fun foo() = 42
object B: A()
}
fun test() {
A.B.(A::foo)()
}
@@ -3882,6 +3882,11 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest("compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/funcitonTypes.kt");
}
@TestMetadata("incompleteEnumReference.kt")
public void testIncompleteEnumReference() throws Exception {
doTest("compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/incompleteEnumReference.kt");
}
@TestMetadata("incompleteVal.kt")
public void testIncompleteVal() throws Exception {
doTest("compiler/testData/diagnostics/tests/incompleteCode/diagnosticWithSyntaxError/incompleteVal.kt");
@@ -6973,6 +6978,11 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/resolve"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("ambiguityOnPropertiesWithTheSamePackageName.kt")
public void testAmbiguityOnPropertiesWithTheSamePackageName() throws Exception {
doTest("compiler/testData/diagnostics/tests/resolve/ambiguityOnPropertiesWithTheSamePackageName.kt");
}
@TestMetadata("incompleteConstructorInvocation.kt")
public void testIncompleteConstructorInvocation() throws Exception {
doTest("compiler/testData/diagnostics/tests/resolve/incompleteConstructorInvocation.kt");
@@ -129,6 +129,11 @@ public class JetDiagnosticsTestWithStdLibGenerated extends AbstractJetDiagnostic
doTest("compiler/testData/diagnostics/testsWithStdLib/callableReference/function/ambiguityTopLevelVsTopLevel.kt");
}
@TestMetadata("callableRefrenceOnNestedObject.kt")
public void testCallableRefrenceOnNestedObject() throws Exception {
doTest("compiler/testData/diagnostics/testsWithStdLib/callableReference/function/callableRefrenceOnNestedObject.kt");
}
@TestMetadata("constructorFromClass.kt")
public void testConstructorFromClass() throws Exception {
doTest("compiler/testData/diagnostics/testsWithStdLib/callableReference/function/constructorFromClass.kt");
@@ -685,6 +685,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest("compiler/testData/codegen/box/classes/classObject.kt");
}
@TestMetadata("classObjectAsExtensionReceiver.kt")
public void testClassObjectAsExtensionReceiver() throws Exception {
doTest("compiler/testData/codegen/box/classes/classObjectAsExtensionReceiver.kt");
}
@TestMetadata("classObjectAsStaticInitializer.kt")
public void testClassObjectAsStaticInitializer() throws Exception {
doTest("compiler/testData/codegen/box/classes/classObjectAsStaticInitializer.kt");
@@ -351,7 +351,6 @@ public class ErrorUtils {
public static boolean containsErrorType(@Nullable JetType type) {
if (type == null) return false;
if (type instanceof PackageType) return false;
if (type.isError()) return true;
for (TypeProjection projection : type.getArguments()) {
if (containsErrorType(projection.getType())) return true;
@@ -1,92 +0,0 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
import java.util.List;
/**
* This is a fake type assigned to package expressions. Only member lookup is
* supposed to be done on these types.
*/
public class PackageType implements JetType {
private final Name name;
private final JetScope memberScope;
private final ReceiverValue receiver;
public PackageType(@NotNull Name name, @NotNull JetScope memberScope, @NotNull ReceiverValue receiver) {
this.name = name;
this.memberScope = memberScope;
this.receiver = receiver;
}
@NotNull
@Override
public JetScope getMemberScope() {
return memberScope;
}
@Override
public boolean isError() {
return false;
}
@NotNull
public ReceiverValue getReceiverValue() {
return receiver;
}
@NotNull
@Override
public TypeConstructor getConstructor() {
return throwException();
}
private TypeConstructor throwException() {
throw new UnsupportedOperationException("Only member lookup is allowed on a package type " + name);
}
@NotNull
@Override
public List<TypeProjection> getArguments() {
throwException();
return null;
}
@Override
public boolean isNullable() {
throwException();
return false;
}
@NotNull
@Override
public Annotations getAnnotations() {
throwException();
return null;
}
@Override
public String toString() {
return "[Package-type " + name + "]";
}
}
@@ -519,7 +519,6 @@ public class TypeUtils {
) {
if (type == null) return false;
if (isSpecialType.invoke(type)) return true;
if (type instanceof PackageType) return false;
for (TypeProjection projection : type.getArguments()) {
if (containsSpecialType(projection.getType(), isSpecialType)) return true;
}
@@ -724,7 +724,6 @@ public class KotlinBuiltIns {
}
public boolean isFunctionType(@NotNull JetType type) {
if (type instanceof PackageType) return false;
if (isExactFunctionType(type)) return true;
for (JetType superType : type.getConstructor().getSupertypes()) {
@@ -735,7 +734,6 @@ public class KotlinBuiltIns {
}
public boolean isExtensionFunctionType(@NotNull JetType type) {
if (type instanceof PackageType) return false;
if (isExactExtensionFunctionType(type)) return true;
for (JetType superType : type.getConstructor().getSupertypes()) {
@@ -833,21 +831,19 @@ public class KotlinBuiltIns {
}
public boolean isNothingOrNullableNothing(@NotNull JetType type) {
return !(type instanceof PackageType)
&& type.getConstructor() == getNothing().getTypeConstructor();
return type.getConstructor() == getNothing().getTypeConstructor();
}
public boolean isAnyOrNullableAny(@NotNull JetType type) {
return !(type instanceof PackageType) &&
type.getConstructor() == getAny().getTypeConstructor();
return type.getConstructor() == getAny().getTypeConstructor();
}
public boolean isUnit(@NotNull JetType type) {
return !(type instanceof PackageType) && type.equals(getUnitType());
return type.equals(getUnitType());
}
public boolean isString(@Nullable JetType type) {
return !(type instanceof PackageType) && getStringType().equals(type);
return getStringType().equals(type);
}
public boolean isCloneable(@NotNull ClassDescriptor descriptor) {
@@ -279,9 +279,6 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
}
return "???";
}
if (type instanceof PackageType) {
return type.toString();
}
if (type instanceof LazyType && debugMode) {
return type.toString();
}
@@ -35,9 +35,9 @@ import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.JetScopeUtils;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.QualifierReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.PackageType;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
import java.util.*;
@@ -58,32 +58,32 @@ public final class TipsManager {
if (receiverExpression != null && inPositionForCompletionWithReceiver) {
// Process as call expression
JetScope resolutionScope = context.get(BindingContext.RESOLUTION_SCOPE, expression);
QualifierReceiver qualifierReceiver = context.get(BindingContext.QUALIFIER_RECEIVER, receiverExpression);
if (qualifierReceiver != null && resolutionScope != null) {
return includeExternalCallableExtensions(
excludePrivateDescriptors(qualifierReceiver.getScope().getAllDescriptors()),
resolutionScope, qualifierReceiver);
}
JetType expressionType = context.get(BindingContext.EXPRESSION_TYPE, receiverExpression);
if (expressionType != null && resolutionScope != null && !expressionType.isError()) {
if (!(expressionType instanceof PackageType)) {
ExpressionReceiver receiverValue = new ExpressionReceiver(receiverExpression, expressionType);
Set<DeclarationDescriptor> descriptors = new HashSet<DeclarationDescriptor>();
ExpressionReceiver receiverValue = new ExpressionReceiver(receiverExpression, expressionType);
Set<DeclarationDescriptor> descriptors = new HashSet<DeclarationDescriptor>();
DataFlowInfo info = context.get(BindingContext.NON_DEFAULT_EXPRESSION_DATA_FLOW, expression);
if (info == null) {
info = DataFlowInfo.EMPTY;
}
List<JetType> variantsForExplicitReceiver = AutoCastUtils.getAutoCastVariants(receiverValue, context, info);
for (JetType variant : variantsForExplicitReceiver) {
descriptors.addAll(includeExternalCallableExtensions(
excludePrivateDescriptors(variant.getMemberScope().getAllDescriptors()),
resolutionScope, receiverValue));
}
return descriptors;
DataFlowInfo info = context.get(BindingContext.NON_DEFAULT_EXPRESSION_DATA_FLOW, expression);
if (info == null) {
info = DataFlowInfo.EMPTY;
}
return includeExternalCallableExtensions(
excludePrivateDescriptors(expressionType.getMemberScope().getAllDescriptors()),
resolutionScope, new ExpressionReceiver(receiverExpression, expressionType));
List<JetType> variantsForExplicitReceiver = AutoCastUtils.getAutoCastVariants(receiverValue, context, info);
for (JetType variant : variantsForExplicitReceiver) {
descriptors.addAll(includeExternalCallableExtensions(
excludePrivateDescriptors(variant.getMemberScope().getAllDescriptors()),
resolutionScope, receiverValue));
}
return descriptors;
}
return Collections.emptyList();
}
@@ -197,11 +197,9 @@ public final class TipsManager {
@NotNull final ReceiverValue receiverValue
) {
// It's impossible to add extension function for package
JetType receiverType = receiverValue.getType();
if (receiverType instanceof PackageType) {
if (receiverValue instanceof QualifierReceiver) {
return new HashSet<DeclarationDescriptor>(descriptors);
}
Set<DeclarationDescriptor> descriptorsSet = Sets.newHashSet(descriptors);
descriptorsSet.addAll(
@@ -24,7 +24,6 @@ import org.jetbrains.jet.lang.resolve.BindingContext
import org.jetbrains.jet.plugin.JetBundle
import org.jetbrains.jet.lang.psi.JetValueArgument
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
import org.jetbrains.jet.lang.types.PackageType
import org.jetbrains.jet.lang.psi.JetPsiUnparsingUtils
import org.jetbrains.jet.lang.psi.JetPsiFactory
import com.intellij.codeInsight.hint.HintManager
@@ -91,15 +90,13 @@ public open class ReplaceWithInfixFunctionCallIntention : JetSelfTargetingIntent
val functionLiteralArguments = element.getFunctionLiteralArguments()
val bindingContext = AnalyzerFacadeWithCache.getContextForElement(parent)
val receiverType = bindingContext[BindingContext.EXPRESSION_TYPE, receiver]
when {
receiverType == null -> {
intentionFailed(editor, "resolution.failed")
return
}
receiverType is PackageType -> {
if (receiverType == null) {
if (bindingContext[BindingContext.QUALIFIER_RECEIVER, receiver] != null) {
intentionFailed(editor, "package.call")
return
}
intentionFailed(editor, "resolution.failed")
return
}
rightHandTextStringBuilder.append(
@@ -48,8 +48,6 @@ import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils;
import org.jetbrains.jet.lang.resolve.OverrideResolver;
import org.jetbrains.jet.lang.resolve.java.jetAsJava.KotlinLightMethod;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.PackageType;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.lexer.JetKeywordToken;
import org.jetbrains.jet.lexer.JetTokens;
@@ -432,9 +430,7 @@ public class JetRefactoringUtil {
JetExpression expression = (JetExpression)element;
BindingContext bindingContext = AnalyzerFacadeWithCache.getContextForElement(expression);
JetType expressionType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression);
if (expressionType == null || !(expressionType instanceof PackageType) &&
!JetTypeChecker.DEFAULT.equalTypes(KotlinBuiltIns.
getInstance().getUnitType(), expressionType)) {
if (expressionType == null || !KotlinBuiltIns.getInstance().isUnit(expressionType)) {
expressions.add(expression);
}
}
@@ -44,7 +44,6 @@ import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.PackageType;
import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
@@ -139,7 +138,8 @@ public class KotlinIntroduceVariableHandler extends KotlinIntroduceHandlerBase {
noTypeInference = true;
}
}
if (expressionType instanceof PackageType) {
if (expressionType == null && bindingContext.get(BindingContext.QUALIFIER_RECEIVER, expression) != null) {
showErrorHint(project, editor, JetRefactoringBundle.message("cannot.refactor.package.expression"));
return;
}
@@ -0,0 +1,11 @@
package a
class Test {
class object {
class Some
}
}
fun test() {
a.Test.S<caret>
}
@@ -0,0 +1,11 @@
package a
class Test {
class object {
class Some
}
}
fun test() {
a.Test.Some<caret>
}
@@ -0,0 +1,15 @@
trait A
fun A.foo(i: Int) = i
class B {
class object : A
}
fun test() {
B.foo(<caret>)
}
/*
Text: (<highlight>i: Int</highlight>), Disabled: false, Strikeout: false, Green: true
*/
@@ -137,6 +137,7 @@ public class BasicCompletionHandlerTest : CompletionHandlerTestBase(){
fun testEnumMember() = doTest(1, "A", null, '\n')
fun testEnumMember1() = doTest(1, "A", null, '\n')
fun testClassFromClassObject() = doTest(1, "Some", null, '\n')
fun testClassFromClassObjectInPackage() = doTest(1, "Some", null, '\n')
fun testParameterType() = doTest(1, "StringBuilder", " (java.lang)", '\n')
@@ -38,6 +38,11 @@ public class FunctionParameterInfoTestGenerated extends AbstractFunctionParamete
doTest("idea/testData/parameterInfo/functionParameterInfo/Deprecated.kt");
}
@TestMetadata("ExtensionOnClassObject.kt")
public void testExtensionOnClassObject() throws Exception {
doTest("idea/testData/parameterInfo/functionParameterInfo/ExtensionOnClassObject.kt");
}
@TestMetadata("InheritedFunctions.kt")
public void testInheritedFunctions() throws Exception {
doTest("idea/testData/parameterInfo/functionParameterInfo/InheritedFunctions.kt");