Script refactoring, frontend: Treat scripts as classes (as opposed to function bodies)

ScriptDescriptor implements ClassDescriptor
Scripts are accessible in IDE via stub index
Replace special treatment of scripts with generic mechanism in several cases
Scripts to longer generate 'rv' property for storing result value (changes in repl required)
This commit is contained in:
Pavel V. Talanov
2015-11-17 15:09:01 +03:00
parent aebcebe8ca
commit efa4bf1d74
27 changed files with 198 additions and 580 deletions
@@ -1318,7 +1318,7 @@ public class JetControlFlowProcessor {
@Override @Override
public void visitObjectDeclaration(@NotNull KtObjectDeclaration objectDeclaration) { public void visitObjectDeclaration(@NotNull KtObjectDeclaration objectDeclaration) {
generateHeaderDelegationSpecifiers(objectDeclaration); generateHeaderDelegationSpecifiers(objectDeclaration);
generateClassOrObjectInitializers(objectDeclaration); generateInitializersForScriptClassOrObject(objectDeclaration);
generateDeclarationForLocalClassOrObjectIfNeeded(objectDeclaration); generateDeclarationForLocalClassOrObjectIfNeeded(objectDeclaration);
} }
@@ -1353,7 +1353,7 @@ public class JetControlFlowProcessor {
} }
} }
private void generateClassOrObjectInitializers(@NotNull KtClassOrObject classOrObject) { private void generateInitializersForScriptClassOrObject(@NotNull KtDeclarationContainer classOrObject) {
for (KtDeclaration declaration : classOrObject.getDeclarations()) { for (KtDeclaration declaration : classOrObject.getDeclarations()) {
if (declaration instanceof KtProperty || declaration instanceof KtClassInitializer) { if (declaration instanceof KtProperty || declaration instanceof KtClassInitializer) {
generateInstructions(declaration); generateInstructions(declaration);
@@ -1368,12 +1368,17 @@ public class JetControlFlowProcessor {
// delegation specifiers of primary constructor, anonymous class and property initializers // delegation specifiers of primary constructor, anonymous class and property initializers
generateHeaderDelegationSpecifiers(klass); generateHeaderDelegationSpecifiers(klass);
generateClassOrObjectInitializers(klass); generateInitializersForScriptClassOrObject(klass);
} }
generateDeclarationForLocalClassOrObjectIfNeeded(klass); generateDeclarationForLocalClassOrObjectIfNeeded(klass);
} }
@Override
public void visitScript(@NotNull KtScript script) {
generateInitializersForScriptClassOrObject(script);
}
private void generateDeclarationForLocalClassOrObjectIfNeeded(@NotNull KtClassOrObject classOrObject) { private void generateDeclarationForLocalClassOrObjectIfNeeded(@NotNull KtClassOrObject classOrObject) {
if (classOrObject.isLocal()) { if (classOrObject.isLocal()) {
for (KtDeclaration declaration : classOrObject.getDeclarations()) { for (KtDeclaration declaration : classOrObject.getDeclarations()) {
@@ -1402,7 +1407,7 @@ public class JetControlFlowProcessor {
generateCallOrMarkUnresolved(constructor.getDelegationCall()); generateCallOrMarkUnresolved(constructor.getDelegationCall());
if (!constructor.getDelegationCall().isCallToThis()) { if (!constructor.getDelegationCall().isCallToThis()) {
generateClassOrObjectInitializers(classOrObject); generateInitializersForScriptClassOrObject(classOrObject);
} }
generateInstructions(constructor.getBodyExpression()); generateInstructions(constructor.getBodyExpression());
@@ -213,7 +213,7 @@ public interface BindingContext {
WritableSlice[] DECLARATIONS_TO_DESCRIPTORS = new WritableSlice[] { WritableSlice[] DECLARATIONS_TO_DESCRIPTORS = new WritableSlice[] {
CLASS, TYPE_PARAMETER, FUNCTION, CONSTRUCTOR, VARIABLE, VALUE_PARAMETER, PROPERTY_ACCESSOR, CLASS, TYPE_PARAMETER, FUNCTION, CONSTRUCTOR, VARIABLE, VALUE_PARAMETER, PROPERTY_ACCESSOR,
PRIMARY_CONSTRUCTOR_PARAMETER PRIMARY_CONSTRUCTOR_PARAMETER, SCRIPT
}; };
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@@ -20,9 +20,13 @@ import org.jetbrains.annotations.Mutable;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.ReadOnly; import org.jetbrains.annotations.ReadOnly;
import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes;
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor;
import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor;
import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo; import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyScriptDescriptor;
import org.jetbrains.kotlin.resolve.scopes.LexicalScope; import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
import java.util.Collection; import java.util.Collection;
@@ -39,7 +43,7 @@ public interface BodiesResolveContext {
@Mutable @Mutable
Map<KtSecondaryConstructor, ConstructorDescriptor> getSecondaryConstructors(); Map<KtSecondaryConstructor, ConstructorDescriptor> getSecondaryConstructors();
@Mutable @Mutable
Map<KtScript, ScriptDescriptor> getScripts(); Map<KtScript, LazyScriptDescriptor> getScripts();
@Mutable @Mutable
Map<KtProperty, PropertyDescriptor> getProperties(); Map<KtProperty, PropertyDescriptor> getProperties();
@@ -60,7 +60,6 @@ import static org.jetbrains.kotlin.resolve.BindingContext.*;
import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE; import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
public class BodyResolver { public class BodyResolver {
@NotNull private final ScriptBodyResolver scriptBodyResolverResolver;
@NotNull private final AnnotationChecker annotationChecker; @NotNull private final AnnotationChecker annotationChecker;
@NotNull private final ExpressionTypingServices expressionTypingServices; @NotNull private final ExpressionTypingServices expressionTypingServices;
@NotNull private final CallResolver callResolver; @NotNull private final CallResolver callResolver;
@@ -82,7 +81,6 @@ public class BodyResolver {
@NotNull DelegatedPropertyResolver delegatedPropertyResolver, @NotNull DelegatedPropertyResolver delegatedPropertyResolver,
@NotNull ExpressionTypingServices expressionTypingServices, @NotNull ExpressionTypingServices expressionTypingServices,
@NotNull FunctionAnalyzerExtension functionAnalyzerExtension, @NotNull FunctionAnalyzerExtension functionAnalyzerExtension,
@NotNull ScriptBodyResolver scriptBodyResolverResolver,
@NotNull BindingTrace trace, @NotNull BindingTrace trace,
@NotNull ValueParameterResolver valueParameterResolver, @NotNull ValueParameterResolver valueParameterResolver,
@NotNull AnnotationChecker annotationChecker @NotNull AnnotationChecker annotationChecker
@@ -95,7 +93,6 @@ public class BodyResolver {
this.delegatedPropertyResolver = delegatedPropertyResolver; this.delegatedPropertyResolver = delegatedPropertyResolver;
this.expressionTypingServices = expressionTypingServices; this.expressionTypingServices = expressionTypingServices;
this.functionAnalyzerExtension = functionAnalyzerExtension; this.functionAnalyzerExtension = functionAnalyzerExtension;
this.scriptBodyResolverResolver = scriptBodyResolverResolver;
this.annotationChecker = annotationChecker; this.annotationChecker = annotationChecker;
this.trace = new ObservableBindingTrace(trace); this.trace = new ObservableBindingTrace(trace);
this.valueParameterResolver = valueParameterResolver; this.valueParameterResolver = valueParameterResolver;
@@ -112,8 +109,6 @@ public class BodyResolver {
resolveFunctionBodies(c); resolveFunctionBodies(c);
scriptBodyResolverResolver.resolveScriptBodies(c);
if (!c.getTopDownAnalysisMode().isLocalDeclarations()) { if (!c.getTopDownAnalysisMode().isLocalDeclarations()) {
computeDeferredTypes(); computeDeferredTypes();
} }
@@ -523,7 +518,9 @@ public class BodyResolver {
if (body != null) { if (body != null) {
PreliminaryDeclarationVisitor.Companion.createForDeclaration( PreliminaryDeclarationVisitor.Companion.createForDeclaration(
(KtDeclaration) anonymousInitializer.getParent().getParent(), trace); (KtDeclaration) anonymousInitializer.getParent().getParent(), trace);
expressionTypingServices.getType(scopeForInitializers, body, NO_EXPECTED_TYPE, outerDataFlowInfo, trace); expressionTypingServices.getTypeInfo(
scopeForInitializers, body, NO_EXPECTED_TYPE, outerDataFlowInfo, trace, /*isStatement = */true
);
} }
processModifiersOnInitializer(anonymousInitializer, scopeForInitializers); processModifiersOnInitializer(anonymousInitializer, scopeForInitializers);
} }
@@ -46,6 +46,9 @@ public class ControlFlowAnalyzer {
for (KtClassOrObject aClass : c.getDeclaredClasses().keySet()) { for (KtClassOrObject aClass : c.getDeclaredClasses().keySet()) {
checkDeclarationContainer(c, aClass); checkDeclarationContainer(c, aClass);
} }
for (KtScript script : c.getScripts().keySet()) {
checkDeclarationContainer(c, script);
}
for (KtSecondaryConstructor constructor : c.getSecondaryConstructors().keySet()) { for (KtSecondaryConstructor constructor : c.getSecondaryConstructors().keySet()) {
checkSecondaryConstructor(constructor); checkSecondaryConstructor(constructor);
} }
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.lazy.* import org.jetbrains.kotlin.resolve.lazy.*
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyScriptDescriptor
import org.jetbrains.kotlin.resolve.varianceChecker.VarianceChecker import org.jetbrains.kotlin.resolve.varianceChecker.VarianceChecker
import java.util.* import java.util.*
@@ -69,26 +70,22 @@ public class LazyTopDownAnalyzer(
throw IllegalArgumentException("Unsupported declaration: " + dcl + " " + dcl.getText()) throw IllegalArgumentException("Unsupported declaration: " + dcl + " " + dcl.getText())
} }
override fun visitScript(script: KtScript) {
c.getScripts().put(
script,
lazyDeclarationResolver.getScriptDescriptor(script, KotlinLookupLocation(script)) as LazyScriptDescriptor
)
registerDeclarations(script.declarations)
}
override fun visitKtFile(file: KtFile) { override fun visitKtFile(file: KtFile) {
if (file.isScript()) { DescriptorResolver.registerFileInPackage(trace, file)
val script = file.getScript() ?: throw AssertionError("getScript() is null for file: $file") registerDeclarations(file.declarations)
val packageDirective = file.packageDirective
DescriptorResolver.registerFileInPackage(trace, file) assert(file.isScript || packageDirective != null) { "No package in a non-script file: " + file }
c.getScripts().put(script, topLevelDescriptorProvider.getScriptDescriptor(script)) packageDirective?.accept(this)
} c.addFile(file)
else { topLevelFqNames.put(file.packageFqName, packageDirective)
val packageDirective = file.getPackageDirective()
assert(packageDirective != null) { "No package in a non-script file: " + file }
c.addFile(file)
packageDirective!!.accept(this)
DescriptorResolver.registerFileInPackage(trace, file)
registerDeclarations(file.getDeclarations())
topLevelFqNames.put(file.getPackageFqName(), packageDirective)
}
} }
override fun visitPackageDirective(directive: KtPackageDirective) { override fun visitPackageDirective(directive: KtPackageDirective) {
@@ -158,8 +155,8 @@ public class LazyTopDownAnalyzer(
} }
override fun visitAnonymousInitializer(initializer: KtClassInitializer) { override fun visitAnonymousInitializer(initializer: KtClassInitializer) {
val classOrObject = PsiTreeUtil.getParentOfType<KtClassOrObject>(initializer, javaClass<KtClassOrObject>())!! val containerDescriptor = lazyDeclarationResolver.resolveToDescriptor(initializer.containingDeclaration) as ClassDescriptorWithResolutionScopes
c.getAnonymousInitializers().put(initializer, lazyDeclarationResolver.resolveToDescriptor(classOrObject) as ClassDescriptorWithResolutionScopes) c.getAnonymousInitializers().put(initializer, containerDescriptor)
} }
override fun visitTypedef(typedef: KtTypedef) { override fun visitTypedef(typedef: KtTypedef) {
@@ -1,71 +0,0 @@
/*
* Copyright 2010-2015 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.kotlin.resolve;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.descriptors.ScriptDescriptor;
import org.jetbrains.kotlin.psi.KtScript;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
import org.jetbrains.kotlin.types.ErrorUtils;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.expressions.CoercionStrategy;
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext;
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices;
import org.jetbrains.kotlin.types.expressions.PreliminaryDeclarationVisitor;
import java.util.Map;
import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
public class ScriptBodyResolver {
private final ExpressionTypingServices expressionTypingServices;
public ScriptBodyResolver(
@NotNull ExpressionTypingServices expressionTypingServices
) {
this.expressionTypingServices = expressionTypingServices;
}
public void resolveScriptBodies(@NotNull BodiesResolveContext c) {
for (Map.Entry<KtScript, ScriptDescriptor> e : c.getScripts().entrySet()) {
ScriptDescriptor descriptor = e.getValue();
ForceResolveUtil.forceResolveAllContents(descriptor);
}
}
@NotNull
public KotlinType resolveScriptReturnType(
@NotNull KtScript script,
@NotNull LexicalScope scopeForBodyResolution,
@NotNull BindingTrace trace
) {
// Resolve all contents of the script
ExpressionTypingContext context = ExpressionTypingContext.newContext(
trace, scopeForBodyResolution, DataFlowInfo.EMPTY, NO_EXPECTED_TYPE
);
PreliminaryDeclarationVisitor.Companion.createForDeclaration(script, trace);
KotlinType returnType = expressionTypingServices.getBlockReturnedType(
script.getBlockExpression(), CoercionStrategy.NO_COERCION, context
).getType();
if (returnType == null) {
returnType = ErrorUtils.createErrorType("getBlockReturnedType returned null");
}
return returnType;
}
}
@@ -18,13 +18,13 @@ package org.jetbrains.kotlin.resolve;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import kotlin.CollectionsKt; import kotlin.CollectionsKt;
import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo; import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.lazy.DeclarationScopeProvider; import org.jetbrains.kotlin.resolve.lazy.DeclarationScopeProvider;
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyScriptDescriptor;
import org.jetbrains.kotlin.resolve.scopes.LexicalScope; import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
import java.io.PrintStream; import java.io.PrintStream;
@@ -47,7 +47,7 @@ public class TopDownAnalysisContext implements BodiesResolveContext {
private final Map<KtParameter, PropertyDescriptor> primaryConstructorParameterProperties = Maps.newHashMap(); private final Map<KtParameter, PropertyDescriptor> primaryConstructorParameterProperties = Maps.newHashMap();
private Map<KtCallableDeclaration, CallableMemberDescriptor> members = null; private Map<KtCallableDeclaration, CallableMemberDescriptor> members = null;
private final Map<KtScript, ScriptDescriptor> scripts = Maps.newLinkedHashMap(); private final Map<KtScript, LazyScriptDescriptor> scripts = Maps.newLinkedHashMap();
private final TopDownAnalysisMode topDownAnalysisMode; private final TopDownAnalysisMode topDownAnalysisMode;
private final DeclarationScopeProvider declarationScopeProvider; private final DeclarationScopeProvider declarationScopeProvider;
@@ -115,7 +115,7 @@ public class TopDownAnalysisContext implements BodiesResolveContext {
@Override @Override
@NotNull @NotNull
public Map<KtScript, ScriptDescriptor> getScripts() { public Map<KtScript, LazyScriptDescriptor> getScripts() {
return scripts; return scripts;
} }
@@ -158,15 +158,6 @@ public class TopDownAnalysisContext implements BodiesResolveContext {
@NotNull @NotNull
public Collection<ClassDescriptorWithResolutionScopes> getAllClasses() { public Collection<ClassDescriptorWithResolutionScopes> getAllClasses() {
Collection<ClassDescriptorWithResolutionScopes> scriptClasses = CollectionsKt.map( return CollectionsKt.plus(getDeclaredClasses().values(), getScripts().values());
getScripts().values(),
new Function1<ScriptDescriptor, ClassDescriptorWithResolutionScopes>() {
@Override
public ClassDescriptorWithResolutionScopes invoke(ScriptDescriptor scriptDescriptor) {
return (ClassDescriptorWithResolutionScopes) scriptDescriptor.getClassDescriptor();
}
}
);
return CollectionsKt.plus(getDeclaredClasses().values(), scriptClasses);
} }
} }
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt; import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo; import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor; import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor;
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyScriptDescriptor;
import org.jetbrains.kotlin.resolve.scopes.LexicalScope; import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
public class DeclarationScopeProviderImpl implements DeclarationScopeProvider { public class DeclarationScopeProviderImpl implements DeclarationScopeProvider {
@@ -71,6 +72,11 @@ public class DeclarationScopeProviderImpl implements DeclarationScopeProvider {
return classDescriptor.getScopeForMemberDeclarationResolution(); return classDescriptor.getScopeForMemberDeclarationResolution();
} }
//TODO: this is not how it works for classes and for exact parity we can try to use the code above
if (parentDeclaration instanceof KtScript) {
LazyScriptDescriptor scriptDescriptor = (LazyScriptDescriptor) lazyDeclarationResolver.resolveToDescriptor(parentDeclaration);
return scriptDescriptor.getScopeForInitializerResolution();
}
throw new IllegalStateException("Don't call this method for local declarations: " + ktDeclaration + "\n" + throw new IllegalStateException("Don't call this method for local declarations: " + ktDeclaration + "\n" +
PsiUtilsKt.getElementTextWithContext(ktDeclaration)); PsiUtilsKt.getElementTextWithContext(ktDeclaration));
@@ -66,22 +66,35 @@ public class LazyDeclarationResolver {
@NotNull @NotNull
public ClassDescriptor getClassDescriptor(@NotNull KtClassOrObject classOrObject, @NotNull LookupLocation location) { public ClassDescriptor getClassDescriptor(@NotNull KtClassOrObject classOrObject, @NotNull LookupLocation location) {
MemberScope scope = getMemberScopeDeclaredIn(classOrObject, location); return findClassDescriptor(classOrObject, location);
}
@NotNull
public ScriptDescriptor getScriptDescriptor(@NotNull KtScript script, @NotNull LookupLocation location) {
return (ScriptDescriptor) findClassDescriptor(script, location);
}
@NotNull
private ClassDescriptor findClassDescriptor(
@NotNull KtNamedDeclaration classObjectOrScript,
@NotNull LookupLocation location
) {
MemberScope scope = getMemberScopeDeclaredIn(classObjectOrScript, location);
// Why not use the result here. Because it may be that there is a redeclaration: // Why not use the result here. Because it may be that there is a redeclaration:
// class A {} class A { fun foo(): A<completion here>} // class A {} class A { fun foo(): A<completion here>}
// and if we find the class by name only, we may b-not get the right one. // and if we find the class by name only, we may b-not get the right one.
// This call is only needed to make sure the classes are written to trace // This call is only needed to make sure the classes are written to trace
ClassifierDescriptor scopeDescriptor = scope.getContributedClassifier(classOrObject.getNameAsSafeName(), location); ClassifierDescriptor scopeDescriptor = scope.getContributedClassifier(classObjectOrScript.getNameAsSafeName(), location);
DeclarationDescriptor descriptor = getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, classOrObject); DeclarationDescriptor descriptor = getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, classObjectOrScript);
if (descriptor == null) { if (descriptor == null) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
String.format("Could not find a classifier for %s.\n" + String.format("Could not find a classifier for %s.\n" +
"Found descriptor: %s (%s).\n", "Found descriptor: %s (%s).\n",
PsiUtilsKt.getElementTextWithContext(classOrObject), PsiUtilsKt.getElementTextWithContext(classObjectOrScript),
scopeDescriptor != null ? DescriptorRenderer.DEBUG_TEXT.render(scopeDescriptor) : "null", scopeDescriptor != null ? DescriptorRenderer.DEBUG_TEXT.render(scopeDescriptor) : "null",
scopeDescriptor != null ? (scopeDescriptor.getContainingDeclaration().getClass()) : null)); scopeDescriptor != null ? (scopeDescriptor.getContainingDeclaration().getClass()) : null));
} }
return (ClassDescriptor) descriptor; return (ClassDescriptor) descriptor;
@@ -210,7 +223,7 @@ public class LazyDeclarationResolver {
@Override @Override
public DeclarationDescriptor visitScript(@NotNull KtScript script, Void data) { public DeclarationDescriptor visitScript(@NotNull KtScript script, Void data) {
return topLevelDescriptorProvider.getScriptDescriptor(script); return getScriptDescriptor(script, lookupLocationFor(script, true));
} }
@Override @Override
@@ -238,7 +251,11 @@ public class LazyDeclarationResolver {
else { else {
if (parentDeclaration instanceof KtClassOrObject) { if (parentDeclaration instanceof KtClassOrObject) {
return getClassDescriptor((KtClassOrObject) parentDeclaration, location).getUnsubstitutedMemberScope(); return getClassDescriptor((KtClassOrObject) parentDeclaration, location).getUnsubstitutedMemberScope();
} else { }
else if (parentDeclaration instanceof KtScript) {
return getScriptDescriptor((KtScript) parentDeclaration, location).getUnsubstitutedMemberScope();
}
else {
throw new IllegalStateException("Don't call this method for local declarations: " + declaration + "\n" + throw new IllegalStateException("Don't call this method for local declarations: " + declaration + "\n" +
PsiUtilsKt.getElementTextWithContext(declaration)); PsiUtilsKt.getElementTextWithContext(declaration));
} }
@@ -35,13 +35,13 @@ import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.*; import org.jetbrains.kotlin.resolve.*;
import org.jetbrains.kotlin.resolve.lazy.data.JetClassLikeInfo; import org.jetbrains.kotlin.resolve.lazy.data.JetClassLikeInfo;
import org.jetbrains.kotlin.resolve.lazy.data.JetClassOrObjectInfo;
import org.jetbrains.kotlin.resolve.lazy.data.JetScriptInfo; import org.jetbrains.kotlin.resolve.lazy.data.JetScriptInfo;
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory; import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory;
import org.jetbrains.kotlin.resolve.lazy.declarations.PackageMemberDeclarationProvider; import org.jetbrains.kotlin.resolve.lazy.declarations.PackageMemberDeclarationProvider;
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotations; import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotations;
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotationsContextImpl; import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotationsContextImpl;
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyPackageDescriptor; import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyPackageDescriptor;
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyScriptDescriptor;
import org.jetbrains.kotlin.resolve.scopes.MemberScope; import org.jetbrains.kotlin.resolve.scopes.MemberScope;
import org.jetbrains.kotlin.resolve.scopes.LexicalScope; import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
import org.jetbrains.kotlin.storage.*; import org.jetbrains.kotlin.storage.*;
@@ -63,8 +63,6 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
private final MemoizedFunctionToNullable<FqName, LazyPackageDescriptor> packages; private final MemoizedFunctionToNullable<FqName, LazyPackageDescriptor> packages;
private final PackageFragmentProvider packageFragmentProvider; private final PackageFragmentProvider packageFragmentProvider;
private final MemoizedFunctionToNotNull<KtScript, LazyScriptDescriptor> scriptDescriptors;
private final MemoizedFunctionToNotNull<KtFile, LazyAnnotations> fileAnnotations; private final MemoizedFunctionToNotNull<KtFile, LazyAnnotations> fileAnnotations;
private final MemoizedFunctionToNotNull<KtFile, LazyAnnotations> danglingAnnotations; private final MemoizedFunctionToNotNull<KtFile, LazyAnnotations> danglingAnnotations;
@@ -73,7 +71,6 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
private DescriptorResolver descriptorResolver; private DescriptorResolver descriptorResolver;
private FunctionDescriptorResolver functionDescriptorResolver; private FunctionDescriptorResolver functionDescriptorResolver;
private TypeResolver typeResolver; private TypeResolver typeResolver;
private ScriptBodyResolver scriptBodyResolver;
private LazyDeclarationResolver lazyDeclarationResolver; private LazyDeclarationResolver lazyDeclarationResolver;
private FileScopeProvider fileScopeProvider; private FileScopeProvider fileScopeProvider;
private DeclarationScopeProvider declarationScopeProvider; private DeclarationScopeProvider declarationScopeProvider;
@@ -106,11 +103,6 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
this.typeResolver = typeResolver; this.typeResolver = typeResolver;
} }
@Inject
public void setScriptBodyResolver(ScriptBodyResolver scriptBodyResolver) {
this.scriptBodyResolver = scriptBodyResolver;
}
@Inject @Inject
public void setLazyDeclarationResolver(LazyDeclarationResolver lazyDeclarationResolver) { public void setLazyDeclarationResolver(LazyDeclarationResolver lazyDeclarationResolver) {
this.lazyDeclarationResolver = lazyDeclarationResolver; this.lazyDeclarationResolver = lazyDeclarationResolver;
@@ -179,20 +171,6 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
} }
}; };
this.scriptDescriptors = storageManager.createMemoizedFunction(
new Function1<KtScript, LazyScriptDescriptor>() {
@Override
public LazyScriptDescriptor invoke(KtScript script) {
return new LazyScriptDescriptor(
ResolveSession.this,
scriptBodyResolver,
script,
ScriptPriorities.getScriptPriority(script)
);
}
}
);
fileAnnotations = storageManager.createMemoizedFunction(new Function1<KtFile, LazyAnnotations>() { fileAnnotations = storageManager.createMemoizedFunction(new Function1<KtFile, LazyAnnotations>() {
@Override @Override
public LazyAnnotations invoke(KtFile file) { public LazyAnnotations invoke(KtFile file) {
@@ -267,12 +245,18 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
new Function<JetClassLikeInfo, ClassDescriptor>() { new Function<JetClassLikeInfo, ClassDescriptor>() {
@Override @Override
public ClassDescriptor fun(JetClassLikeInfo classLikeInfo) { public ClassDescriptor fun(JetClassLikeInfo classLikeInfo) {
if (classLikeInfo instanceof JetScriptInfo) { if (classLikeInfo instanceof JetClassOrObjectInfo) {
return getClassDescriptorForScript(((JetScriptInfo) classLikeInfo).getScript()); //noinspection RedundantCast
return getClassDescriptor(((JetClassOrObjectInfo) classLikeInfo).getCorrespondingClassOrObject(), location);
}
else if (classLikeInfo instanceof JetScriptInfo) {
return getScriptDescriptor(((JetScriptInfo) classLikeInfo).getScript());
}
else {
throw new IllegalStateException(
"Unexpected " + classLikeInfo + " of type " + classLikeInfo.getClass().getName()
);
} }
KtClassOrObject classOrObject = classLikeInfo.getCorrespondingClassOrObject();
if (classOrObject == null) return null;
return getClassDescriptor(classOrObject, location);
} }
} }
); );
@@ -284,19 +268,9 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
return lazyDeclarationResolver.getClassDescriptor(classOrObject, location); return lazyDeclarationResolver.getClassDescriptor(classOrObject, location);
} }
@NotNull
public ClassDescriptor getClassDescriptorForScript(@NotNull KtScript script) {
MemberScope memberScope = lazyDeclarationResolver.getMemberScopeDeclaredIn(script, NoLookupLocation.FOR_SCRIPT);
FqName fqName = ScriptNameUtil.classNameForScript(script);
ClassifierDescriptor classifier = memberScope.getContributedClassifier(fqName.shortName(), NoLookupLocation.FOR_SCRIPT);
assert classifier != null : "No descriptor for " + fqName + " in file " + script.getContainingFile();
return (ClassDescriptor) classifier;
}
@Override
@NotNull @NotNull
public ScriptDescriptor getScriptDescriptor(@NotNull KtScript script) { public ScriptDescriptor getScriptDescriptor(@NotNull KtScript script) {
return scriptDescriptors.invoke(script); return lazyDeclarationResolver.getScriptDescriptor(script, NoLookupLocation.FOR_SCRIPT);
} }
@Override @Override
@@ -17,17 +17,13 @@
package org.jetbrains.kotlin.resolve.lazy package org.jetbrains.kotlin.resolve.lazy
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtScript
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyPackageDescriptor import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyPackageDescriptor
public interface TopLevelDescriptorProvider { public interface TopLevelDescriptorProvider {
fun getPackageFragment(fqName: FqName): LazyPackageDescriptor? fun getPackageFragment(fqName: FqName): LazyPackageDescriptor?
fun getScriptDescriptor(script: KtScript): ScriptDescriptor
fun getTopLevelClassDescriptors(fqName: FqName, location: LookupLocation): Collection<ClassDescriptor> fun getTopLevelClassDescriptors(fqName: FqName, location: LookupLocation): Collection<ClassDescriptor>
} }
@@ -38,10 +34,6 @@ public object NoTopLevelDescriptorProvider : TopLevelDescriptorProvider {
shouldNotBeCalled() shouldNotBeCalled()
} }
override fun getScriptDescriptor(script: KtScript): ScriptDescriptor {
shouldNotBeCalled()
}
override fun getTopLevelClassDescriptors(fqName: FqName, location: LookupLocation): Collection<ClassDescriptor> { override fun getTopLevelClassDescriptors(fqName: FqName, location: LookupLocation): Collection<ClassDescriptor> {
shouldNotBeCalled() shouldNotBeCalled()
} }
@@ -40,6 +40,7 @@ public abstract class JetClassOrObjectInfo<E extends KtClassOrObject> implements
} }
@Override @Override
@NotNull
public KtClassOrObject getCorrespondingClassOrObject() { public KtClassOrObject getCorrespondingClassOrObject() {
return element; return element;
} }
@@ -34,14 +34,5 @@ public class JetScriptInfo(
override fun getPrimaryConstructorParameters() = listOf<KtParameter>() override fun getPrimaryConstructorParameters() = listOf<KtParameter>()
override fun getClassKind() = ClassKind.CLASS override fun getClassKind() = ClassKind.CLASS
override fun getDeclarations() = script.getDeclarations() override fun getDeclarations() = script.getDeclarations()
.filter(::shouldBeScriptClassMember)
override fun getDanglingAnnotations() = listOf<KtAnnotationEntry>() override fun getDanglingAnnotations() = listOf<KtAnnotationEntry>()
} }
public fun shouldBeScriptClassMember(declaration: KtDeclaration): Boolean {
// To avoid the necessity to always analyze the whole body of a script even if just its class descriptor is needed
// we only add those vals, vars and funs that have explicitly specified return types
// (or implicit Unit for function with block body)
return declaration is KtCallableDeclaration && declaration.getTypeReference() != null
|| declaration is KtNamedFunction && declaration.hasBlockBody()
}
@@ -17,7 +17,10 @@
package org.jetbrains.kotlin.resolve.lazy.descriptors package org.jetbrains.kotlin.resolve.lazy.descriptors
import com.google.common.collect.Sets import com.google.common.collect.Sets
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.incremental.record import org.jetbrains.kotlin.incremental.record
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -29,8 +32,8 @@ import org.jetbrains.kotlin.resolve.lazy.ResolveSession
import org.jetbrains.kotlin.resolve.lazy.data.JetScriptInfo import org.jetbrains.kotlin.resolve.lazy.data.JetScriptInfo
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProvider import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProvider
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl
import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl
import org.jetbrains.kotlin.storage.MemoizedFunctionToNotNull import org.jetbrains.kotlin.storage.MemoizedFunctionToNotNull
import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.utils.Printer import org.jetbrains.kotlin.utils.Printer
@@ -53,7 +56,7 @@ protected constructor(
private fun resolveClassDescriptor(name: Name): List<ClassDescriptor> { private fun resolveClassDescriptor(name: Name): List<ClassDescriptor> {
return declarationProvider.getClassOrObjectDeclarations(name).map { return declarationProvider.getClassOrObjectDeclarations(name).map {
if (it is JetScriptInfo) if (it is JetScriptInfo)
LazyScriptClassDescriptor(c as ResolveSession, thisDescriptor, name, it) LazyScriptDescriptor(c as ResolveSession, thisDescriptor, name, it)
else else
LazyClassDescriptor(c, thisDescriptor, name, it) LazyClassDescriptor(c, thisDescriptor, name, it)
}.toReadOnlyList() }.toReadOnlyList()
@@ -1,66 +0,0 @@
/*
* Copyright 2010-2015 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.kotlin.resolve.lazy.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.resolve.lazy.LazyClassContext;
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.kotlin.descriptors.Visibilities;
import org.jetbrains.kotlin.descriptors.Visibility;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace;
import org.jetbrains.kotlin.resolve.lazy.ResolveSession;
import org.jetbrains.kotlin.resolve.lazy.data.JetScriptInfo;
import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider;
public class LazyScriptClassDescriptor extends LazyClassDescriptor {
public LazyScriptClassDescriptor(
@NotNull ResolveSession resolveSession,
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull Name name,
@NotNull JetScriptInfo scriptInfo
) {
super(resolveSession, containingDeclaration, name, scriptInfo);
}
@NotNull
@Override
protected LazyScriptClassMemberScope createMemberScope(
@NotNull LazyClassContext c,
@NotNull ClassMemberDeclarationProvider declarationProvider
) {
return new LazyScriptClassMemberScope(
// Must be a ResolveSession for scripts
(ResolveSession) c,
declarationProvider,
this,
TemporaryBindingTrace.create(c.getTrace(), "A trace for script class, needed to avoid rewrites on members")
);
}
@NotNull
@Override
public LazyScriptClassMemberScope getUnsubstitutedMemberScope() {
return (LazyScriptClassMemberScope) super.getUnsubstitutedMemberScope();
}
@NotNull
@Override
public Visibility getVisibility() {
return Visibilities.PUBLIC;
}
}
@@ -20,112 +20,76 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.ConstructorDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ConstructorDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.parsing.KotlinScriptDefinitionProvider
import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.lazy.ResolveSession import org.jetbrains.kotlin.resolve.lazy.ResolveSession
import org.jetbrains.kotlin.resolve.lazy.data.JetScriptInfo
import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider
import org.jetbrains.kotlin.storage.NotNullLazyValue
import org.jetbrains.kotlin.utils.toReadOnlyList import org.jetbrains.kotlin.utils.toReadOnlyList
public class LazyScriptClassMemberScope protected constructor( public class LazyScriptClassMemberScope(
private val resolveSession: ResolveSession, private val resolveSession: ResolveSession,
declarationProvider: ClassMemberDeclarationProvider, declarationProvider: ClassMemberDeclarationProvider,
thisClass: LazyClassDescriptor, private val scriptDescriptor: LazyScriptDescriptor,
trace: BindingTrace) trace: BindingTrace)
: LazyClassMemberScope(resolveSession, declarationProvider, thisClass, trace) { : LazyClassMemberScope(resolveSession, declarationProvider, scriptDescriptor, trace) {
private val scriptResultProperty: NotNullLazyValue<PropertyDescriptor> = resolveSession.storageManager.createLazyValue {
val scriptInfo = declarationProvider.getOwnerInfo() as JetScriptInfo
createScriptResultProperty(resolveSession.getScriptDescriptor(scriptInfo.script))
}
override fun computeExtraDescriptors(location: LookupLocation): Collection<DeclarationDescriptor> {
return (super.computeExtraDescriptors(location)
+ getContributedVariables(Name.identifier(ScriptDescriptor.LAST_EXPRESSION_VALUE_FIELD_NAME), location)
+ getPropertiesForScriptParameters()).toReadOnlyList()
}
private fun getPropertiesForScriptParameters() = getPrimaryConstructor()!!.valueParameters.flatMap { getContributedVariables(it.name, NoLookupLocation.FOR_SCRIPT) }
override fun getNonDeclaredProperties(name: Name, result: MutableSet<PropertyDescriptor>) {
super.getNonDeclaredProperties(name, result)
if (name.asString() == ScriptDescriptor.LAST_EXPRESSION_VALUE_FIELD_NAME) {
result.add(scriptResultProperty())
}
}
public fun getScriptResultProperty(): PropertyDescriptor = scriptResultProperty()
override fun createPropertiesFromPrimaryConstructorParameters(name: Name, result: MutableSet<PropertyDescriptor>) {
val scriptInfo = declarationProvider.getOwnerInfo() as JetScriptInfo
// From primary constructor parameters
val primaryConstructor = getPrimaryConstructor()
if (primaryConstructor == null) return
for (valueParameterDescriptor in primaryConstructor.getValueParameters()) {
if (name == valueParameterDescriptor.getName()) {
result.add(createPropertyFromScriptParameter(resolveSession.getScriptDescriptor(scriptInfo.script), valueParameterDescriptor))
}
}
}
override fun resolvePrimaryConstructor(): ConstructorDescriptor? { override fun resolvePrimaryConstructor(): ConstructorDescriptor? {
val scriptInfo = declarationProvider.getOwnerInfo() as JetScriptInfo val constructor = ConstructorDescriptorImpl.create(
val scriptDescriptor = resolveSession.getScriptDescriptor(scriptInfo.script) scriptDescriptor,
val constructor = createConstructor(scriptDescriptor, scriptDescriptor.getScriptCodeDescriptor().getValueParameters()) Annotations.EMPTY,
true,
SourceElement.NO_SOURCE
)
constructor.initialize(
createScriptParameters(constructor),
Visibilities.PUBLIC
)
setDeferredReturnType(constructor) setDeferredReturnType(constructor)
return constructor return constructor
} }
private fun createScriptResultProperty(scriptDescriptor: ScriptDescriptor): PropertyDescriptor { private fun createScriptParameters(constructor: ConstructorDescriptorImpl): List<ValueParameterDescriptor> {
val propertyDescriptor = PropertyDescriptorImpl.create( val file = scriptDescriptor.scriptInfo.script.getContainingKtFile()
scriptDescriptor.getClassDescriptor(), val scriptDefinition = KotlinScriptDefinitionProvider.getInstance(file.project).findScriptDefinition(file)
Annotations.EMPTY, return scriptDefinition.scriptParameters.mapIndexed { index, scriptParameter ->
Modality.FINAL, ValueParameterDescriptorImpl(
Visibilities.PUBLIC, constructor, null, index, Annotations.EMPTY, scriptParameter.getName(), scriptParameter.getType(),
false, /* declaresDefaultValue = */ false,
Name.identifier(ScriptDescriptor.LAST_EXPRESSION_VALUE_FIELD_NAME), /* isCrossinline = */ false,
CallableMemberDescriptor.Kind.DECLARATION, /* isNoinline = */ false,
SourceElement.NO_SOURCE, null, SourceElement.NO_SOURCE
/* lateInit = */ false, )
/* isConst = */ false }
)
val returnType = scriptDescriptor.getScriptCodeDescriptor().getReturnType()
assert(returnType != null) { "Return type not initialized for " + scriptDescriptor }
returnType!!
propertyDescriptor.setType(
returnType,
listOf<TypeParameterDescriptor>(),
scriptDescriptor.getThisAsReceiverParameter(),
null as ReceiverParameterDescriptor?
)
propertyDescriptor.initialize(null, null)
return propertyDescriptor
} }
private fun createConstructor(scriptDescriptor: ScriptDescriptor, valueParameters: List<ValueParameterDescriptor>): ConstructorDescriptorImpl { override fun computeExtraDescriptors(location: LookupLocation): Collection<DeclarationDescriptor> {
return ConstructorDescriptorImpl.create( return (super.computeExtraDescriptors(location)
scriptDescriptor.getClassDescriptor(), + getPropertiesForScriptParameters()).toReadOnlyList()
Annotations.EMPTY,
true,
SourceElement.NO_SOURCE
).initialize(
valueParameters,
Visibilities.PUBLIC
)
} }
private fun createPropertyFromScriptParameter(scriptDescriptor: ScriptDescriptor, parameter: ValueParameterDescriptor): PropertyDescriptor { private fun getPropertiesForScriptParameters() = getPrimaryConstructor()!!.valueParameters.flatMap {
getContributedVariables(it.name, NoLookupLocation.FOR_SCRIPT)
}
override fun createPropertiesFromPrimaryConstructorParameters(name: Name, result: MutableSet<PropertyDescriptor>) {
val primaryConstructor = getPrimaryConstructor()!!
for (valueParameterDescriptor in primaryConstructor.valueParameters) {
if (name == valueParameterDescriptor.getName()) {
result.add(createPropertyFromScriptParameter(scriptDescriptor, valueParameterDescriptor))
}
}
}
private fun createPropertyFromScriptParameter(
scriptDescriptor: ScriptDescriptor,
parameter: ValueParameterDescriptor
): PropertyDescriptor {
val propertyDescriptor = PropertyDescriptorImpl.create( val propertyDescriptor = PropertyDescriptorImpl.create(
scriptDescriptor.getClassDescriptor(), scriptDescriptor,
Annotations.EMPTY, Annotations.EMPTY,
Modality.FINAL, Modality.FINAL,
Visibilities.PUBLIC, Visibilities.PUBLIC,
@@ -16,100 +16,57 @@
package org.jetbrains.kotlin.resolve.lazy.descriptors package org.jetbrains.kotlin.resolve.lazy.descriptors
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorVisitor import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.DeclarationDescriptorNonRootImpl
import org.jetbrains.kotlin.descriptors.impl.ReceiverParameterDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ScriptCodeDescriptor
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.parsing.KotlinScriptDefinitionProvider
import org.jetbrains.kotlin.psi.KtScript
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.ScriptBodyResolver import org.jetbrains.kotlin.resolve.ScriptPriorities
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil import org.jetbrains.kotlin.resolve.lazy.LazyClassContext
import org.jetbrains.kotlin.resolve.lazy.LazyEntity
import org.jetbrains.kotlin.resolve.lazy.ResolveSession import org.jetbrains.kotlin.resolve.lazy.ResolveSession
import org.jetbrains.kotlin.resolve.scopes.LexicalScopeImpl import org.jetbrains.kotlin.resolve.lazy.data.JetScriptInfo
import org.jetbrains.kotlin.resolve.scopes.receivers.ScriptReceiver import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider
import org.jetbrains.kotlin.resolve.source.toSourceElement import org.jetbrains.kotlin.resolve.source.toSourceElement
import org.jetbrains.kotlin.types.DeferredType
import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.utils.sure
public class LazyScriptDescriptor( public class LazyScriptDescriptor(
private val resolveSession: ResolveSession, private val resolveSession: ResolveSession,
scriptBodyResolver: ScriptBodyResolver, containingDeclaration: DeclarationDescriptor,
private val jetScript: KtScript, name: Name,
private val priority: Int internal val scriptInfo: JetScriptInfo
) : ScriptDescriptor, LazyEntity, DeclarationDescriptorNonRootImpl( ) : ScriptDescriptor, LazyClassDescriptor(
jetScript.getContainingKtFile().getPackageFqName().let { resolveSession,
fqName -> containingDeclaration,
resolveSession.getPackageFragment(fqName).sure { "Package not found $fqName" } name,
}, scriptInfo
Annotations.EMPTY,
ScriptDescriptor.NAME,
jetScript.toSourceElement()
) { ) {
init { init {
resolveSession.trace.record(BindingContext.SCRIPT, jetScript, this) resolveSession.trace.record(BindingContext.SCRIPT, scriptInfo.script, this)
} }
private val implicitReceiver = ReceiverParameterDescriptorImpl(this, ScriptReceiver(this)) private val sourceElement = scriptInfo.script.toSourceElement()
override fun getThisAsReceiverParameter() = implicitReceiver override fun getSource() = sourceElement
private val priority: Int = ScriptPriorities.getScriptPriority(scriptInfo.script)
override fun getPriority() = priority override fun getPriority() = priority
override fun getClassDescriptor() = resolveSession.getClassDescriptorForScript(jetScript) as LazyScriptClassDescriptor
override fun getScriptResultProperty(): PropertyDescriptor = getClassDescriptor().getUnsubstitutedMemberScope().getScriptResultProperty()
private val scriptCodeDescriptor = resolveSession.storageManager.createLazyValue {
val result = ScriptCodeDescriptor(this)
val file = jetScript.getContainingKtFile()
val scriptDefinition = KotlinScriptDefinitionProvider.getInstance(file.getProject()).findScriptDefinition(file)
result.initialize(
implicitReceiver,
scriptDefinition.getScriptParameters().mapIndexed { index, scriptParameter ->
ValueParameterDescriptorImpl(
result, null, index, Annotations.EMPTY, scriptParameter.getName(), scriptParameter.getType(),
/* declaresDefaultValue = */ false,
/* isCrossinline = */ false,
/* isNoinline = */ false,
null, SourceElement.NO_SOURCE
)
},
DeferredType.create(resolveSession.storageManager, resolveSession.trace) {
val scope = LexicalScopeImpl(
resolveSession.fileScopeProvider.getFileResolutionScope(jetScript.getContainingKtFile()),
this, false, implicitReceiver, "Scope for body resolution for $this"
) {
for (valueParameterDescriptor in result.valueParameters) {
addVariableDescriptor(valueParameterDescriptor)
}
}
scriptBodyResolver.resolveScriptReturnType(jetScript, scope, resolveSession.trace)
}
)
result
}
override fun getScriptCodeDescriptor(): ScriptCodeDescriptor = scriptCodeDescriptor()
override fun forceResolveAllContents() {
ForceResolveUtil.forceResolveAllContents(getClassDescriptor())
ForceResolveUtil.forceResolveAllContents(getScriptCodeDescriptor())
}
override fun substitute(substitutor: TypeSubstitutor) = this override fun substitute(substitutor: TypeSubstitutor) = this
override fun <R, D> accept(visitor: DeclarationDescriptorVisitor<R, D>, data: D): R { override fun <R, D> accept(visitor: DeclarationDescriptorVisitor<R, D>, data: D): R {
return visitor.visitScriptDescriptor(this, data) return visitor.visitScriptDescriptor(this, data)
} }
protected override fun createMemberScope(
c: LazyClassContext,
declarationProvider: ClassMemberDeclarationProvider): LazyScriptClassMemberScope {
return LazyScriptClassMemberScope(
// Must be a ResolveSession for scripts
c as ResolveSession,
declarationProvider,
this,
c.trace
)
}
override fun getUnsubstitutedPrimaryConstructor() = super.getUnsubstitutedPrimaryConstructor()!!
} }
@@ -1,48 +0,0 @@
/*
* Copyright 2010-2015 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.kotlin.resolve.scopes.receivers;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.descriptors.ScriptDescriptor;
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
import org.jetbrains.kotlin.types.KotlinType;
public class ScriptReceiver implements ImplicitReceiver {
private final ScriptDescriptor scriptDescriptor;
public ScriptReceiver(@NotNull ScriptDescriptor scriptDescriptor) {
this.scriptDescriptor = scriptDescriptor;
}
@NotNull
@Override
public ScriptDescriptor getDeclarationDescriptor() {
return scriptDescriptor;
}
@NotNull
@Override
public KotlinType getType() {
// not sure
return DescriptorUtilsKt.getBuiltIns(scriptDescriptor).getAnyType();
}
@Override
public boolean exists() {
return true;
}
}
@@ -159,13 +159,6 @@ public class ExpressionTypingServices {
List<KtExpression> block = StatementFilterKt.filterStatements(statementFilter, expression); List<KtExpression> block = StatementFilterKt.filterStatements(statementFilter, expression);
DeclarationDescriptor containingDescriptor = context.scope.getOwnerDescriptor(); DeclarationDescriptor containingDescriptor = context.scope.getOwnerDescriptor();
if (containingDescriptor instanceof ScriptDescriptor) {
if (!(expression.getParent() instanceof KtScript)) {
// top level script declarations should have ScriptDescriptor parent
// and lower level script declarations should be ScriptCodeDescriptor parent
containingDescriptor = ((ScriptDescriptor) containingDescriptor).getScriptCodeDescriptor();
}
}
LexicalWritableScope scope = new LexicalWritableScope(context.scope, containingDescriptor, false, null, LexicalWritableScope scope = new LexicalWritableScope(context.scope, containingDescriptor, false, null,
new TraceBasedRedeclarationHandler(context.trace), "getBlockReturnedType"); new TraceBasedRedeclarationHandler(context.trace), "getBlockReturnedType");
scope.changeLockLevel(LexicalWritableScope.LockLevel.BOTH); scope.changeLockLevel(LexicalWritableScope.LockLevel.BOTH);
@@ -122,7 +122,7 @@ public class RecursiveDescriptorProcessor {
@Override @Override
public Boolean visitScriptDescriptor(ScriptDescriptor scriptDescriptor, D data) { public Boolean visitScriptDescriptor(ScriptDescriptor scriptDescriptor, D data) {
return visitClassDescriptor(scriptDescriptor.getClassDescriptor(), data); return visitClassDescriptor(scriptDescriptor, data);
} }
@Override @Override
@@ -17,24 +17,11 @@
package org.jetbrains.kotlin.descriptors; package org.jetbrains.kotlin.descriptors;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.descriptors.impl.ScriptCodeDescriptor;
import org.jetbrains.kotlin.name.Name;
public interface ScriptDescriptor extends DeclarationDescriptorNonRoot {
String LAST_EXPRESSION_VALUE_FIELD_NAME = "rv";
Name NAME = Name.special("<script>");
public interface ScriptDescriptor extends ClassDescriptor {
int getPriority(); int getPriority();
@NotNull @NotNull
ScriptCodeDescriptor getScriptCodeDescriptor(); @Override
ConstructorDescriptor getUnsubstitutedPrimaryConstructor();
@NotNull
ReceiverParameterDescriptor getThisAsReceiverParameter();
@NotNull
ClassDescriptor getClassDescriptor();
@NotNull
PropertyDescriptor getScriptResultProperty();
} }
@@ -65,7 +65,7 @@ public class DeclarationDescriptorVisitorEmptyBodies<R, D> implements Declaratio
@Override @Override
public R visitScriptDescriptor(ScriptDescriptor scriptDescriptor, D data) { public R visitScriptDescriptor(ScriptDescriptor scriptDescriptor, D data) {
return visitDeclarationDescriptor(scriptDescriptor, data); return visitClassDescriptor(scriptDescriptor, data);
} }
@Override @Override
@@ -1,75 +0,0 @@
/*
* Copyright 2010-2015 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.kotlin.descriptors.impl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.types.KotlinType;
import java.util.Collections;
import java.util.List;
public class ScriptCodeDescriptor extends FunctionDescriptorImpl {
public ScriptCodeDescriptor(@NotNull ScriptDescriptor containingDeclaration) {
super(containingDeclaration, null, Annotations.Companion.getEMPTY(), Name.special("<script-code>"), Kind.DECLARATION, SourceElement.NO_SOURCE);
}
public void initialize(
@NotNull ReceiverParameterDescriptor dispatchReceiverParameter,
@NotNull List<ValueParameterDescriptor> valueParameters,
@NotNull KotlinType returnType) {
super.initialize(null, dispatchReceiverParameter, Collections.<TypeParameterDescriptor>emptyList(), valueParameters, returnType,
Modality.FINAL, Visibilities.INTERNAL);
}
@NotNull
@Override
protected FunctionDescriptorImpl createSubstitutedCopy(
@NotNull DeclarationDescriptor newOwner,
@Nullable FunctionDescriptor original,
@NotNull Kind kind,
@Nullable Name newName,
boolean preserveSource
) {
throw new IllegalStateException("no need to copy script code descriptor");
}
@NotNull
@Override
public FunctionDescriptor copy(DeclarationDescriptor newOwner, Modality modality, Visibility visibility, Kind kind, boolean copyOverrides) {
throw new IllegalStateException("no need to copy script code descriptor");
}
@Override
public boolean isExternal() {
return false;
}
@Override
public boolean isInline() {
return false;
}
@Override
public boolean isTailrec() {
return false;
}
}
@@ -872,10 +872,6 @@ internal class DescriptorRendererImpl(
/* OTHER */ /* OTHER */
private fun renderModuleOrScript(moduleOrScript: DeclarationDescriptor, builder: StringBuilder) {
renderName(moduleOrScript, builder)
}
private fun renderPackageView(packageView: PackageViewDescriptor, builder: StringBuilder) { private fun renderPackageView(packageView: PackageViewDescriptor, builder: StringBuilder) {
builder.append(renderKeyword("package")).append(" ") builder.append(renderKeyword("package")).append(" ")
builder.append(renderFqName(packageView.fqName.toUnsafe())) builder.append(renderFqName(packageView.fqName.toUnsafe()))
@@ -962,11 +958,11 @@ internal class DescriptorRendererImpl(
} }
override fun visitModuleDeclaration(descriptor: ModuleDescriptor, builder: StringBuilder) { override fun visitModuleDeclaration(descriptor: ModuleDescriptor, builder: StringBuilder) {
renderModuleOrScript(descriptor, builder) renderName(descriptor, builder)
} }
override fun visitScriptDescriptor(scriptDescriptor: ScriptDescriptor, builder: StringBuilder) { override fun visitScriptDescriptor(scriptDescriptor: ScriptDescriptor, builder: StringBuilder) {
renderModuleOrScript(scriptDescriptor, builder) visitClassDescriptor(scriptDescriptor, builder)
} }
override fun visitClassDescriptor(descriptor: ClassDescriptor, builder: StringBuilder) { override fun visitClassDescriptor(descriptor: ClassDescriptor, builder: StringBuilder) {
@@ -43,6 +43,7 @@ import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.lazy.* import org.jetbrains.kotlin.resolve.lazy.*
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyScriptDescriptor
import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.utils.addToStdlib.check import org.jetbrains.kotlin.utils.addToStdlib.check
@@ -491,8 +492,7 @@ public class ResolveElementCache(
private fun initializerAdditionalResolve(resolveSession: ResolveSession, classInitializer: KtClassInitializer, file: KtFile, statementFilter: StatementFilter): BindingTrace { private fun initializerAdditionalResolve(resolveSession: ResolveSession, classInitializer: KtClassInitializer, file: KtFile, statementFilter: StatementFilter): BindingTrace {
val trace = createDelegatingTrace(classInitializer) val trace = createDelegatingTrace(classInitializer)
val classOrObject = classInitializer.getParentOfType<KtClassOrObject>(true)!! val classOrObjectDescriptor = resolveSession.resolveToDescriptor(classInitializer.containingDeclaration) as LazyClassDescriptor
val classOrObjectDescriptor = resolveSession.resolveToDescriptor(classOrObject) as LazyClassDescriptor
val bodyResolver = createBodyResolver(resolveSession, trace, file, statementFilter) val bodyResolver = createBodyResolver(resolveSession, trace, file, statementFilter)
bodyResolver.resolveAnonymousInitializer(DataFlowInfo.EMPTY, classInitializer, classOrObjectDescriptor) bodyResolver.resolveAnonymousInitializer(DataFlowInfo.EMPTY, classInitializer, classOrObjectDescriptor)
@@ -550,7 +550,7 @@ public class ResolveElementCache(
override fun getDeclaringScope(declaration: KtDeclaration): LexicalScope? = declaringScopes(declaration) override fun getDeclaringScope(declaration: KtDeclaration): LexicalScope? = declaringScopes(declaration)
override fun getScripts(): MutableMap<KtScript, ScriptDescriptor> = hashMapOf() override fun getScripts(): MutableMap<KtScript, LazyScriptDescriptor> = hashMapOf()
override fun getOuterDataFlowInfo(): DataFlowInfo = DataFlowInfo.EMPTY override fun getOuterDataFlowInfo(): DataFlowInfo = DataFlowInfo.EMPTY
@@ -22,19 +22,14 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.lazy.declarations.PackageMemberDeclarationProvider import org.jetbrains.kotlin.resolve.lazy.declarations.PackageMemberDeclarationProvider
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.idea.stubindex.KotlinFullClassNameIndex
import org.jetbrains.kotlin.idea.stubindex.PackageIndexUtil
import org.jetbrains.kotlin.resolve.lazy.data.JetClassLikeInfo import org.jetbrains.kotlin.resolve.lazy.data.JetClassLikeInfo
import org.jetbrains.kotlin.resolve.lazy.data.JetClassInfoUtil import org.jetbrains.kotlin.resolve.lazy.data.JetClassInfoUtil
import org.jetbrains.kotlin.resolve.lazy.ResolveSessionUtils import org.jetbrains.kotlin.resolve.lazy.ResolveSessionUtils
import java.util.ArrayList import java.util.ArrayList
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelFunctionByPackageIndex
import com.intellij.psi.stubs.StringStubIndexExtension import com.intellij.psi.stubs.StringStubIndexExtension
import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelPropertyByPackageIndex import org.jetbrains.kotlin.idea.stubindex.*
import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelPropertyFqnNameIndex import org.jetbrains.kotlin.resolve.lazy.data.JetScriptInfo
import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelFunctionFqnNameIndex
import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelClassByPackageIndex
public class StubBasedPackageMemberDeclarationProvider( public class StubBasedPackageMemberDeclarationProvider(
private val fqName: FqName, private val fqName: FqName,
@@ -65,8 +60,13 @@ public class StubBasedPackageMemberDeclarationProvider(
} }
override fun getClassOrObjectDeclarations(name: Name): Collection<JetClassLikeInfo> { override fun getClassOrObjectDeclarations(name: Name): Collection<JetClassLikeInfo> {
return KotlinFullClassNameIndex.getInstance().get(childName(name), project, searchScope) val result = ArrayList<JetClassLikeInfo>()
.map { JetClassInfoUtil.createClassLikeInfo(it) } KotlinFullClassNameIndex.getInstance().get(childName(name), project, searchScope)
.mapTo(result) { JetClassInfoUtil.createClassLikeInfo(it) }
KotlinScriptFqnIndex.instance.get(childName(name), project, searchScope)
.mapTo(result) { JetScriptInfo(it) }
return result
} }
override fun getFunctionDeclarations(name: Name): Collection<KtNamedFunction> { override fun getFunctionDeclarations(name: Name): Collection<KtNamedFunction> {