diff --git a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java index 19b42f4e948..76694c8ec99 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java @@ -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); diff --git a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java index 60b3fbbf92b..908103838b3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java +++ b/compiler/frontend/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerBasic.java @@ -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); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetDeclarationContainer.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetDeclarationContainer.java index 42fcc3c860e..a188aeaba57 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetDeclarationContainer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetDeclarationContainer.java @@ -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 getDeclarations(); } 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 6142dcde11a..7fd37672db8 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptBodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptBodyResolver.java @@ -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 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 diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptHeaderResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptHeaderResolver.java index 2106b7f6bc4..b6f92c5f6c1 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptHeaderResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptHeaderResolver.java @@ -95,7 +95,11 @@ public class ScriptHeaderResolver { JetScript declaration = e.getKey(); ScriptDescriptorImpl descriptor = (ScriptDescriptorImpl) e.getValue(); - List valueParameters = scriptParameterResolver.resolveScriptParameters(c, declaration, descriptor); + List valueParameters = scriptParameterResolver.resolveScriptParameters( + c.getTopDownAnalysisParameters(), + declaration, + descriptor + ); descriptor.setValueParameters(valueParameters); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptNameUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptNameUtil.java index 917f467e0ef..35f892e35d4 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptNameUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptNameUtil.java @@ -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); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptParameterResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptParameterResolver.java index b2e7055722b..e2ab9bae3e2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptParameterResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ScriptParameterResolver.java @@ -49,7 +49,7 @@ public class ScriptParameterResolver { @NotNull public List resolveScriptParameters( - @NotNull TopDownAnalysisContext c, + @NotNull TopDownAnalysisParameters topDownAnalysisParameters, @NotNull JetScript declaration, @NotNull ScriptDescriptor scriptDescriptor ) { @@ -61,7 +61,7 @@ public class ScriptParameterResolver { int index = 0; List scriptParameters = !scriptDefinition.getScriptParameters().isEmpty() ? scriptDefinition.getScriptParameters() - : c.getTopDownAnalysisParameters().getScriptParameters(); + : topDownAnalysisParameters.getScriptParameters(); for (AnalyzerScriptParameter scriptParameter : scriptParameters) { ValueParameterDescriptor parameter = resolveScriptParameter(scriptParameter, index, scriptDescriptor); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index 8716a356922..5ef2a8273a2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -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; } + } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/JetClassLikeInfo.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/JetClassLikeInfo.java index b66c75b75c8..f11473ebb93 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/JetClassLikeInfo.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/data/JetClassLikeInfo.java @@ -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 getTypeParameters(); @NotNull + @ReadOnly List getPrimaryConstructorParameters(); @NotNull 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 29a5b4540af..9ac4497fafb 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 @@ -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 getAllDeclarations() { return index.invoke().allDeclarations; 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 new file mode 100644 index 00000000000..d77759ccbb6 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/descriptors/LazyScriptDescriptor.kt @@ -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() + override fun getPrimaryConstructorParameters() = listOf() + 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 accept(visitor: DeclarationDescriptorVisitor, data: D): R { + return visitor.visitScriptDescriptor(this, data) as R + } +} \ No newline at end of file diff --git a/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java b/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java index 6453fbac973..c0c96c26676 100644 --- a/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java +++ b/js/js.translator/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJs.java @@ -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);