From 086e16f67f59fd0425b206204ca22de0e26b7a4f Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Fri, 28 Mar 2014 21:51:53 +0400 Subject: [PATCH] ResolveSession knows about script classes --- .../jet/lang/resolve/ScriptBodyResolver.java | 13 ++--- .../jet/lang/resolve/lazy/ResolveSession.java | 13 +++++ .../lang/resolve/lazy/data/JetScriptInfo.kt | 52 +++++++++++++++++++ .../AbstractPsiBasedDeclarationProvider.java | 12 ++++- .../descriptors/AbstractLazyMemberScope.java | 10 +++- .../lazy/descriptors/LazyScriptDescriptor.kt | 25 +-------- 6 files changed, 88 insertions(+), 37 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/JetScriptInfo.kt diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptBodyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptBodyResolver.java index 7fd37672db8..00c0da185e3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptBodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptBodyResolver.java @@ -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(); - } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSession.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSession.java index f25a7f43ca2..d7d33ad128c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSession.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/ResolveSession.java @@ -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() { @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); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/JetScriptInfo.kt b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/JetScriptInfo.kt new file mode 100644 index 00000000000..3c5fb51df29 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/JetScriptInfo.kt @@ -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() + override fun getPrimaryConstructorParameters() = listOf() + 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() +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/declarations/AbstractPsiBasedDeclarationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/declarations/AbstractPsiBasedDeclarationProvider.java index 1c4934ef272..4ee18c5b915 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/declarations/AbstractPsiBasedDeclarationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/declarations/AbstractPsiBasedDeclarationProvider.java @@ -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 { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/AbstractLazyMemberScope.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/AbstractLazyMemberScope.java index fd1df1b65b4..36569f24f8e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/AbstractLazyMemberScope.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/AbstractLazyMemberScope.java @@ -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() { @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); } }); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/LazyScriptDescriptor.kt b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/LazyScriptDescriptor.kt index d9719db39dd..6f70505cb20 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/LazyScriptDescriptor.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/LazyScriptDescriptor.kt @@ -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() - override fun getPrimaryConstructorParameters() = listOf() - 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)