ResolveSession knows about script classes

This commit is contained in:
Andrey Breslav
2014-03-28 21:51:53 +04:00
parent b48d9884ee
commit 086e16f67f
6 changed files with 88 additions and 37 deletions
@@ -25,6 +25,7 @@ import org.jetbrains.jet.lang.descriptors.impl.PropertyDescriptorImpl;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.lazy.ForceResolveUtil;
import org.jetbrains.jet.lang.resolve.lazy.data.DataPackage;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetType;
@@ -76,13 +77,13 @@ public class ScriptBodyResolver {
BindingContext bindingContext = trace.getBindingContext();
for (JetDeclaration jetDeclaration : declaration.getDeclarations()) {
if (jetDeclaration instanceof JetProperty) {
if (!shouldBeScriptClassMember(jetDeclaration)) continue;
if (!DataPackage.shouldBeScriptClassMember(jetDeclaration)) continue;
PropertyDescriptorImpl propertyDescriptor = (PropertyDescriptorImpl) bindingContext.get(BindingContext.VARIABLE, jetDeclaration);
properties.add(propertyDescriptor);
}
else if (jetDeclaration instanceof JetNamedFunction) {
if (!shouldBeScriptClassMember(jetDeclaration)) continue;
if (!DataPackage.shouldBeScriptClassMember(jetDeclaration)) continue;
SimpleFunctionDescriptor function = bindingContext.get(BindingContext.FUNCTION, jetDeclaration);
assert function != null;
@@ -115,12 +116,4 @@ public class ScriptBodyResolver {
}
return returnType;
}
public static boolean shouldBeScriptClassMember(@NotNull JetDeclaration declaration) {
// 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 instanceof JetCallableDeclaration && ((JetCallableDeclaration) declaration).getReturnTypeRef() != null ||
declaration instanceof JetNamedFunction && ((JetNamedFunction) declaration).hasBlockBody();
}
}
@@ -31,6 +31,7 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.lazy.data.JetClassLikeInfo;
import org.jetbrains.jet.lang.resolve.lazy.data.JetScriptInfo;
import org.jetbrains.jet.lang.resolve.lazy.declarations.DeclarationProviderFactory;
import org.jetbrains.jet.lang.resolve.lazy.declarations.PackageMemberDeclarationProvider;
import org.jetbrains.jet.lang.resolve.lazy.descriptors.LazyClassDescriptor;
@@ -213,6 +214,9 @@ public class ResolveSession implements KotlinCodeAnalyzer {
new Function<JetClassLikeInfo, ClassDescriptor>() {
@Override
public ClassDescriptor fun(JetClassLikeInfo classLikeInfo) {
if (classLikeInfo instanceof JetScriptInfo) {
return getClassDescriptorForScript(((JetScriptInfo) classLikeInfo).getScript());
}
JetClassOrObject classOrObject = classLikeInfo.getCorrespondingClassOrObject();
if (classOrObject == null) return null;
return getClassDescriptor(classOrObject);
@@ -249,6 +253,15 @@ public class ResolveSession implements KotlinCodeAnalyzer {
return (ClassDescriptor) descriptor;
}
@NotNull
public ClassDescriptor getClassDescriptorForScript(@NotNull JetScript script) {
JetScope resolutionScope = getScopeProvider().getResolutionScopeForDeclaration(script);
FqName fqName = ScriptNameUtil.classNameForScript(script);
ClassifierDescriptor classifier = resolutionScope.getClassifier(fqName.shortName());
assert classifier != null : "No descriptor for " + fqName + " in file " + script.getContainingFile();
return (ClassDescriptor) classifier;
}
@NotNull
/*package*/ LazyClassDescriptor getClassObjectDescriptor(@NotNull JetClassObject classObject) {
JetClass aClass = PsiTreeUtil.getParentOfType(classObject, JetClass.class);
@@ -0,0 +1,52 @@
/*
* 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.lazy.data
import org.jetbrains.jet.lang.psi.JetTypeParameter
import org.jetbrains.jet.lang.psi.JetParameter
import org.jetbrains.jet.lang.descriptors.ClassKind
import org.jetbrains.jet.lang.psi.JetScript
import org.jetbrains.jet.lang.resolve.ScriptNameUtil
import org.jetbrains.jet.lang.psi.JetFile
import org.jetbrains.jet.lang.psi.JetNamedFunction
import org.jetbrains.jet.lang.psi.JetDeclaration
import org.jetbrains.jet.lang.psi.JetCallableDeclaration
import org.jetbrains.jet.lang.resolve.name.FqName
public class JetScriptInfo(
val script: JetScript
) : JetClassLikeInfo {
public val fqName: FqName = ScriptNameUtil.classNameForScript(script)
override fun getContainingPackageFqName() = fqName.parent()
override fun getModifierList() = null
override fun getClassObject() = null
override fun getScopeAnchor() = script
override fun getCorrespondingClassOrObject() = null
override fun getTypeParameters() = listOf<JetTypeParameter>()
override fun getPrimaryConstructorParameters() = listOf<JetParameter>()
override fun getClassKind() = ClassKind.CLASS
override fun getDeclarations() = script.getDeclarations()
.filter(::shouldBeScriptClassMember)
}
public fun shouldBeScriptClassMember(declaration: JetDeclaration): 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 JetCallableDeclaration && declaration.getReturnTypeRef() != null
|| declaration is JetNamedFunction && declaration.hasBlockBody()
}
@@ -25,6 +25,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.lazy.data.JetClassInfoUtil;
import org.jetbrains.jet.lang.resolve.lazy.data.JetClassLikeInfo;
import org.jetbrains.jet.lang.resolve.lazy.data.JetScriptInfo;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.storage.NotNullLazyValue;
import org.jetbrains.jet.storage.StorageManager;
@@ -63,10 +64,17 @@ public abstract class AbstractPsiBasedDeclarationProvider implements Declaration
JetClassInfoUtil.createClassLikeInfo(classOrObject)
);
}
else if (declaration instanceof JetScript) {
JetScript script = (JetScript) declaration;
JetScriptInfo scriptInfo = new JetScriptInfo(script);
classesAndObjects.put(
scriptInfo.getFqName().shortName(),
scriptInfo
);
}
else if (declaration instanceof JetParameter ||
declaration instanceof JetTypedef ||
declaration instanceof JetMultiDeclaration ||
declaration instanceof JetScript) {
declaration instanceof JetMultiDeclaration) {
// Do nothing, just put it into allDeclarations is enough
}
else {
@@ -26,9 +26,11 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
import org.jetbrains.jet.lang.resolve.lazy.data.JetClassLikeInfo;
import org.jetbrains.jet.lang.resolve.lazy.data.JetScriptInfo;
import org.jetbrains.jet.lang.resolve.lazy.declarations.DeclarationProvider;
import org.jetbrains.jet.lang.resolve.name.LabelName;
import org.jetbrains.jet.lang.resolve.name.Name;
@@ -109,7 +111,13 @@ public abstract class AbstractLazyMemberScope<D extends DeclarationDescriptor, D
return ContainerUtil.mapNotNull(classOrObjectDeclarations, new Function<JetClassLikeInfo, ClassDescriptor>() {
@Override
public ClassDescriptor fun(JetClassLikeInfo classLikeInfo) {
return new LazyClassDescriptor(resolveSession, thisDescriptor, name, classLikeInfo);
BindingTrace traceForMembers = classLikeInfo instanceof JetScriptInfo
? TemporaryBindingTrace.create(
resolveSession.getTrace(),
"A trace for script class, needed to avoid rewrites on members"
)
: resolveSession.getTrace();
return new LazyClassDescriptor(resolveSession, thisDescriptor, name, classLikeInfo, traceForMembers);
}
});
}
@@ -77,30 +77,7 @@ public class LazyScriptDescriptor(
override fun getPriority() = _priority
private val _classDescriptor = resolveSession.getStorageManager().createLazyValue {
val nameForScript = ScriptNameUtil.classNameForScript(jetScript)
val className = nameForScript.shortName()
LazyClassDescriptor(
resolveSession,
getContainingDeclaration(),
className,
object: JetClassLikeInfo {
override fun getContainingPackageFqName() = nameForScript.parent()
override fun getModifierList() = null
override fun getClassObject() = null
override fun getScopeAnchor() = jetScript
override fun getCorrespondingClassOrObject() = null
override fun getTypeParameters() = listOf<JetTypeParameter>()
override fun getPrimaryConstructorParameters() = listOf<JetParameter>()
override fun getClassKind() = ClassKind.CLASS
override fun getDeclarations() = jetScript.getDeclarations()
.filter { ScriptBodyResolver.shouldBeScriptClassMember(it) }
},
TemporaryBindingTrace.create(resolveSession.getTrace(), "A trace for script class, needed to avoid rewrites on members")
)
}
override fun getClassDescriptor(): ClassDescriptor = _classDescriptor()
override fun getClassDescriptor() = resolveSession.getClassDescriptorForScript(jetScript)
private val _scriptCodeDescriptor = resolveSession.getStorageManager().createLazyValue {
val result = ScriptCodeDescriptor(this)