Support scripts in LAZY mode

This commit is contained in:
Andrey Breslav
2014-03-28 12:49:10 +04:00
parent 5166c73060
commit 6ac2e2da8a
12 changed files with 201 additions and 17 deletions
@@ -195,7 +195,8 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly
this.topDownAnalyzer.setOverrideResolver(overrideResolver);
this.topDownAnalyzer.setPackageFragmentProvider(mutablePackageFragmentProvider);
this.topDownAnalyzer.setProject(project);
this.topDownAnalyzer.setScriptHeaderResolver(scriptHeaderResolver);
this.topDownAnalyzer.setScriptBodyResolver(scriptBodyResolver);
this.topDownAnalyzer.setScriptParameterResolver(scriptParameterResolver);
this.topDownAnalyzer.setTrace(bindingTrace);
this.topDownAnalyzer.setTypeHierarchyResolver(typeHierarchyResolver);
@@ -149,7 +149,8 @@ public class InjectorForTopDownAnalyzerBasic {
this.topDownAnalyzer.setOverrideResolver(overrideResolver);
this.topDownAnalyzer.setPackageFragmentProvider(mutablePackageFragmentProvider);
this.topDownAnalyzer.setProject(project);
this.topDownAnalyzer.setScriptHeaderResolver(scriptHeaderResolver);
this.topDownAnalyzer.setScriptBodyResolver(scriptBodyResolver);
this.topDownAnalyzer.setScriptParameterResolver(scriptParameterResolver);
this.topDownAnalyzer.setTrace(bindingTrace);
this.topDownAnalyzer.setTypeHierarchyResolver(typeHierarchyResolver);
@@ -17,10 +17,12 @@
package org.jetbrains.jet.lang.psi;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.ReadOnly;
import java.util.List;
public interface JetDeclarationContainer {
@NotNull
@ReadOnly
List<JetDeclaration> getDeclarations();
}
@@ -24,6 +24,7 @@ import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
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.scopes.WritableScope;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetType;
@@ -55,10 +56,17 @@ public class ScriptBodyResolver {
public void resolveScriptBodies(@NotNull BodiesResolveContext c, @NotNull BindingTrace trace) {
for (Map.Entry<JetScript, ScriptDescriptor> e : c.getScripts().entrySet()) {
JetScript declaration = e.getKey();
ScriptDescriptorImpl descriptor = (ScriptDescriptorImpl) e.getValue();
ScriptDescriptor descriptor = e.getValue();
if (TopDownAnalyzer.LAZY && !c.getTopDownAnalysisParameters().isDeclaredLocally()) {
ForceResolveUtil.forceResolveAllContents(descriptor);
continue;
}
ScriptDescriptorImpl descriptorImpl = (ScriptDescriptorImpl) descriptor;
// TODO: lock in resolveScriptDeclarations
descriptor.getScopeForBodyResolution().changeLockLevel(WritableScope.LockLevel.READING);
descriptorImpl.getScopeForBodyResolution().changeLockLevel(WritableScope.LockLevel.READING);
JetType returnType = resolveScriptReturnType(declaration, descriptor, trace);
@@ -83,11 +91,12 @@ public class ScriptBodyResolver {
}
}
descriptor.initialize(returnType, properties, functions);
descriptorImpl.initialize(returnType, properties, functions);
}
}
private JetType resolveScriptReturnType(
@NotNull
public JetType resolveScriptReturnType(
@NotNull JetScript script,
@NotNull ScriptDescriptor scriptDescriptor,
@NotNull BindingTrace trace
@@ -95,7 +95,11 @@ public class ScriptHeaderResolver {
JetScript declaration = e.getKey();
ScriptDescriptorImpl descriptor = (ScriptDescriptorImpl) e.getValue();
List<ValueParameterDescriptor> valueParameters = scriptParameterResolver.resolveScriptParameters(c, declaration, descriptor);
List<ValueParameterDescriptor> valueParameters = scriptParameterResolver.resolveScriptParameters(
c.getTopDownAnalysisParameters(),
declaration,
descriptor
);
descriptor.setValueParameters(valueParameters);
@@ -16,6 +16,7 @@
package org.jetbrains.jet.lang.resolve;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.parsing.JetScriptDefinition;
import org.jetbrains.jet.lang.parsing.JetScriptDefinitionProvider;
import org.jetbrains.jet.lang.psi.JetFile;
@@ -26,6 +27,7 @@ public class ScriptNameUtil {
private ScriptNameUtil() {
}
@NotNull
public static FqName classNameForScript(JetFile file) {
JetScriptDefinition scriptDefinition = JetScriptDefinitionProvider.getInstance(file.getProject()).findScriptDefinition(file);
@@ -49,7 +49,7 @@ public class ScriptParameterResolver {
@NotNull
public List<ValueParameterDescriptor> resolveScriptParameters(
@NotNull TopDownAnalysisContext c,
@NotNull TopDownAnalysisParameters topDownAnalysisParameters,
@NotNull JetScript declaration,
@NotNull ScriptDescriptor scriptDescriptor
) {
@@ -61,7 +61,7 @@ public class ScriptParameterResolver {
int index = 0;
List<AnalyzerScriptParameter> scriptParameters = !scriptDefinition.getScriptParameters().isEmpty()
? scriptDefinition.getScriptParameters()
: c.getTopDownAnalysisParameters().getScriptParameters();
: topDownAnalysisParameters.getScriptParameters();
for (AnalyzerScriptParameter scriptParameter : scriptParameters) {
ValueParameterDescriptor parameter = resolveScriptParameter(scriptParameter, index, scriptDescriptor);
@@ -38,6 +38,7 @@ import org.jetbrains.jet.lang.resolve.lazy.ForceResolveUtil;
import org.jetbrains.jet.lang.resolve.lazy.LazyImportScope;
import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
import org.jetbrains.jet.lang.resolve.lazy.declarations.FileBasedDeclarationProviderFactory;
import org.jetbrains.jet.lang.resolve.lazy.descriptors.LazyScriptDescriptor;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
@@ -76,7 +77,9 @@ public class TopDownAnalyzer {
@NotNull
private BodyResolver bodyResolver;
@NotNull
private ScriptHeaderResolver scriptHeaderResolver;
private ScriptParameterResolver scriptParameterResolver;
@NotNull
private ScriptBodyResolver scriptBodyResolver;
@NotNull
private Project project;
@@ -121,8 +124,13 @@ public class TopDownAnalyzer {
}
@Inject
public void setScriptHeaderResolver(@NotNull ScriptHeaderResolver scriptHeaderResolver) {
this.scriptHeaderResolver = scriptHeaderResolver;
public void setScriptParameterResolver(@NotNull ScriptParameterResolver scriptParameterResolver) {
this.scriptParameterResolver = scriptParameterResolver;
}
@Inject
public void setScriptBodyResolver(@NotNull ScriptBodyResolver scriptBodyResolver) {
this.scriptBodyResolver = scriptBodyResolver;
}
@Inject
@@ -187,10 +195,17 @@ public class TopDownAnalyzer {
if (file.isScript()) {
JetScript script = file.getScript();
assert script != null;
scriptHeaderResolver.processScriptHierarchy(
c,
c.getScripts().put(
script,
(WritableScope) resolveSession.getScopeProvider().getFileScope(file)
new LazyScriptDescriptor(
resolveSession,
scriptParameterResolver,
c.getTopDownAnalysisParameters(),
scriptBodyResolver,
script,
ScriptHeaderResolver.getScriptPriority(script)
)
);
}
else {
@@ -445,6 +460,7 @@ public class TopDownAnalyzer {
public MutablePackageFragmentProvider getPackageFragmentProvider() {
return packageFragmentProvider;
}
}
@@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.resolve.lazy.data;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.ReadOnly;
import org.jetbrains.jet.lang.descriptors.ClassKind;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.name.FqName;
@@ -44,9 +45,11 @@ public interface JetClassLikeInfo extends JetDeclarationContainer {
JetClassOrObject getCorrespondingClassOrObject();
@NotNull
@ReadOnly
List<JetTypeParameter> getTypeParameters();
@NotNull
@ReadOnly
List<? extends JetParameter> getPrimaryConstructorParameters();
@NotNull
@@ -58,7 +58,10 @@ public abstract class AbstractPsiBasedDeclarationProvider implements Declaration
JetClassOrObject classOrObject = (JetClassOrObject) declaration;
classesAndObjects.put(safeNameForLazyResolve(classOrObject.getNameAsName()), classOrObject);
}
else if (declaration instanceof JetParameter || declaration instanceof JetTypedef || declaration instanceof JetMultiDeclaration) {
else if (declaration instanceof JetParameter ||
declaration instanceof JetTypedef ||
declaration instanceof JetMultiDeclaration ||
declaration instanceof JetScript) {
// Do nothing, just put it into allDeclarations is enough
}
else {
@@ -82,6 +85,7 @@ public abstract class AbstractPsiBasedDeclarationProvider implements Declaration
protected abstract void doCreateIndex(@NotNull Index index);
@NotNull
@Override
public List<JetDeclaration> getAllDeclarations() {
return index.invoke().allDeclarations;
@@ -0,0 +1,141 @@
/*
* 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.descriptors
import org.jetbrains.jet.lang.resolve.lazy.ResolveSession
import org.jetbrains.jet.lang.psi.JetScript
import org.jetbrains.jet.lang.resolve.lazy.LazyEntity
import org.jetbrains.jet.lang.descriptors.impl.DeclarationDescriptorNonRootImpl
import org.jetbrains.jet.lang.descriptors.annotations.Annotations
import org.jetbrains.jet.lang.descriptors.ScriptDescriptor
import org.jetbrains.jet.lang.resolve.scopes.receivers.ScriptReceiver
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
import org.jetbrains.jet.lang.descriptors.impl.ReceiverParameterDescriptorImpl
import org.jetbrains.jet.lang.resolve.BindingContext
import org.jetbrains.jet.lang.psi.JetFile
import org.jetbrains.kotlin.util.sure
import org.jetbrains.jet.lang.resolve.ScriptParameterResolver
import org.jetbrains.jet.lang.resolve.TopDownAnalysisParameters
import org.jetbrains.jet.lang.resolve.ScriptBodyResolver
import org.jetbrains.jet.lang.resolve.lazy.data.JetClassLikeInfo
import org.jetbrains.jet.lang.resolve.ScriptNameUtil
import org.jetbrains.jet.lang.descriptors.ClassKind
import org.jetbrains.jet.lang.descriptors.ClassDescriptor
import org.jetbrains.jet.lang.descriptors.impl.ScriptCodeDescriptor
import org.jetbrains.jet.lang.types.DeferredType
import org.jetbrains.jet.lang.resolve.scopes.JetScope
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl
import org.jetbrains.jet.lang.resolve.scopes.ChainedScope
import org.jetbrains.jet.lang.resolve.lazy.ForceResolveUtil
import org.jetbrains.jet.lang.types.TypeSubstitutor
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptorVisitor
import org.jetbrains.jet.lang.psi.JetParameter
import org.jetbrains.jet.lang.psi.JetTypeParameter
import org.jetbrains.jet.lang.resolve.scopes.RedeclarationHandler
import org.jetbrains.jet.lang.psi.JetCallableDeclaration
import org.jetbrains.jet.lang.resolve.scopes.WritableScope
public class LazyScriptDescriptor(
val resolveSession: ResolveSession,
scriptParameterResolver: ScriptParameterResolver,
topDownAnalysisParameters: TopDownAnalysisParameters,
scriptBodyResolver: ScriptBodyResolver,
val jetScript: JetScript,
val _priority: Int
) : ScriptDescriptor, LazyEntity, DeclarationDescriptorNonRootImpl(
(jetScript.getContainingFile() as JetFile).getPackageFqName().let {
fqName ->
resolveSession.getPackageFragment(fqName).sure("Package not found $fqName")
},
Annotations.EMPTY,
ScriptDescriptor.NAME
) {
{
resolveSession.getTrace().record(BindingContext.SCRIPT, jetScript, this)
}
private val _implicitReceiver = ReceiverParameterDescriptorImpl(this, KotlinBuiltIns.getInstance().getAnyType(), ScriptReceiver(this))
override fun getThisAsReceiverParameter() = _implicitReceiver
override fun getPriority() = _priority
private val _classDescriptor = resolveSession.getStorageManager().createLazyValue {
val nameForScript = ScriptNameUtil.classNameForScript(jetScript.getContainingFile() as JetFile)
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) }
}
)
}
override fun getClassDescriptor(): ClassDescriptor = _classDescriptor()
private val _scriptCodeDescriptor = resolveSession.getStorageManager().createLazyValue {
val result = ScriptCodeDescriptor(this)
result.initialize(
_implicitReceiver,
scriptParameterResolver.resolveScriptParameters(topDownAnalysisParameters, jetScript, this),
DeferredType.create(resolveSession.getStorageManager(), resolveSession.getTrace()) {
scriptBodyResolver.resolveScriptReturnType(jetScript, this, resolveSession.getTrace())
}
)
result
}
override fun getScriptCodeDescriptor() = _scriptCodeDescriptor()
override fun getScopeForBodyResolution(): JetScope {
val parametersScope = WritableScopeImpl(JetScope.EMPTY, this, RedeclarationHandler.DO_NOTHING, "Parameters of " + this)
parametersScope.setImplicitReceiver(_implicitReceiver)
for (valueParameterDescriptor in getScriptCodeDescriptor().getValueParameters()) {
parametersScope.addVariableDescriptor(valueParameterDescriptor)
}
parametersScope.changeLockLevel(WritableScope.LockLevel.READING)
return ChainedScope(
this,
"Scope for body resolution for " + this,
resolveSession.getScopeProvider().getFileScope(jetScript.getContainingFile() as JetFile),
parametersScope
)
}
override fun forceResolveAllContents() {
ForceResolveUtil.forceResolveAllContents(getClassDescriptor())
ForceResolveUtil.forceResolveAllContents(getScriptCodeDescriptor())
}
override fun substitute(substitutor: TypeSubstitutor) = this
override fun <R, D> accept(visitor: DeclarationDescriptorVisitor<R, D>, data: D): R {
return visitor.visitScriptDescriptor(this, data) as R
}
}
@@ -149,7 +149,8 @@ public class InjectorForTopDownAnalyzerForJs {
this.topDownAnalyzer.setOverrideResolver(overrideResolver);
this.topDownAnalyzer.setPackageFragmentProvider(mutablePackageFragmentProvider);
this.topDownAnalyzer.setProject(project);
this.topDownAnalyzer.setScriptHeaderResolver(scriptHeaderResolver);
this.topDownAnalyzer.setScriptBodyResolver(scriptBodyResolver);
this.topDownAnalyzer.setScriptParameterResolver(scriptParameterResolver);
this.topDownAnalyzer.setTrace(bindingTrace);
this.topDownAnalyzer.setTypeHierarchyResolver(typeHierarchyResolver);