Move part of lazy element resolver structure to new module ide-lazy-resolve
This new module will be used from Eclipse, it should not have any idea specific logic that is applicable only for idea
This commit is contained in:
committed by
Andrey Breslav
parent
97a95d6a6a
commit
9fe42be7c4
Generated
+9
@@ -0,0 +1,9 @@
|
||||
<component name="ArtifactManager">
|
||||
<artifact type="jar" name="IdeLazyResolver">
|
||||
<output-path>$PROJECT_DIR$/out/artifacts/IdeLazyResolver</output-path>
|
||||
<root id="archive" name="ide-lazy-resolver.jar">
|
||||
<element id="module-output" name="ide-lazy-resolve" />
|
||||
<element id="dir-copy" path="$PROJECT_DIR$/idea/ide-lazy-resolve" />
|
||||
</root>
|
||||
</artifact>
|
||||
</component>
|
||||
Generated
+1
@@ -23,6 +23,7 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/generators/generators.iml" filepath="$PROJECT_DIR$/generators/generators.iml" group="infrastructure" />
|
||||
<module fileurl="file://$PROJECT_DIR$/grammar/grammar.iml" filepath="$PROJECT_DIR$/grammar/grammar.iml" group="compiler" />
|
||||
<module fileurl="file://$PROJECT_DIR$/ide-compiler-runner/ide-compiler-runner.iml" filepath="$PROJECT_DIR$/ide-compiler-runner/ide-compiler-runner.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/ide-lazy-resolve/ide-lazy-resolve.iml" filepath="$PROJECT_DIR$/idea/ide-lazy-resolve/ide-lazy-resolve.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea.iml" filepath="$PROJECT_DIR$/idea/idea.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea-analysis/idea-analysis.iml" filepath="$PROJECT_DIR$/idea/idea-analysis/idea-analysis.iml" group="ide" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea_runner/idea_runner.iml" filepath="$PROJECT_DIR$/idea_runner/idea_runner.iml" group="ide" />
|
||||
|
||||
@@ -665,6 +665,9 @@
|
||||
source="${java.target}" target="${java.target}">
|
||||
<withKotlin externalannotations="${external.annotations.path}"/>
|
||||
<src>
|
||||
<dirset dir="${basedir}/idea/ide-lazy-resolve">
|
||||
<include name="src"/>
|
||||
</dirset>
|
||||
<dirset dir="${basedir}/idea/idea-analysis">
|
||||
<include name="src"/>
|
||||
</dirset>
|
||||
@@ -674,16 +677,16 @@
|
||||
<fileset dir="${idea.sdk}" includes="core-analysis/*.jar"/>
|
||||
<fileset dir="${idea.sdk}" includes="lib/protobuf-2.5.0.jar"/>
|
||||
|
||||
<fileset dir="${basedir}/lib" includes="**/*.jar"/>
|
||||
<fileset dir="${dependencies.dir}" includes="jline.jar"/>
|
||||
<fileset dir="${dependencies.dir}" includes="jansi.jar"/>
|
||||
<fileset dir="${dependencies.dir}" includes="cli-parser-1.1.1.jar"/>
|
||||
<fileset dir="${basedir}/ideaSDK/jps" includes="jps-model.jar"/>
|
||||
<pathelement location="${output}/classes/runtime"/>
|
||||
<pathelement location="${output}/classes/compiler"/>
|
||||
<pathelement location="${output}/classes/stdlib"/>
|
||||
</classpath>
|
||||
</javac2>
|
||||
<fileset dir="${basedir}/lib" includes="**/*.jar"/>
|
||||
<fileset dir="${dependencies.dir}" includes="jline.jar"/>
|
||||
<fileset dir="${dependencies.dir}" includes="jansi.jar"/>
|
||||
<fileset dir="${dependencies.dir}" includes="cli-parser-1.1.1.jar"/>
|
||||
<fileset dir="${basedir}/ideaSDK/jps" includes="jps-model.jar"/>
|
||||
<pathelement location="${output}/classes/runtime"/>
|
||||
<pathelement location="${output}/classes/compiler"/>
|
||||
<pathelement location="${output}/classes/stdlib"/>
|
||||
</classpath>
|
||||
</javac2>
|
||||
<!--copy resources-->
|
||||
<copy todir="${output}/classes/idea-analysis">
|
||||
<fileset dir="${basedir}/idea/idea-analysis/src" excludes="**/*.java, **/*.kt"/>
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="frontend" />
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$MODULE_DIR$/../../ideaSDK/core/annotations.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="library" name="intellij-core-analysis" level="project" />
|
||||
<orderEntry type="library" name="guava" level="project" />
|
||||
<orderEntry type="module" module-name="util" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
@@ -0,0 +1,528 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Functions;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.analyzer.AnalyzerPackage;
|
||||
import org.jetbrains.jet.di.InjectorForBodyResolve;
|
||||
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.Annotated;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.*;
|
||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
||||
import org.jetbrains.jet.lang.resolve.lazy.descriptors.LazyClassDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.lazy.descriptors.LazyPackageDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.ChainedScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.types.TypeConstructor;
|
||||
import org.jetbrains.jet.lang.types.TypeUtils;
|
||||
import org.jetbrains.jet.storage.ExceptionTracker;
|
||||
import org.jetbrains.jet.storage.StorageManager;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
public class ElementResolver {
|
||||
|
||||
protected final ResolveSession resolveSession;
|
||||
|
||||
protected ElementResolver(@NotNull ResolveSession session) {
|
||||
resolveSession = session;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public BindingContext getElementAdditionalResolve(@NotNull JetElement jetElement) {
|
||||
return elementAdditionalResolve(jetElement);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public BindingContext resolveToElement(@NotNull JetElement jetElement) {
|
||||
@SuppressWarnings("unchecked") JetElement elementOfAdditionalResolve = (JetElement) JetPsiUtil.getTopmostParentOfTypes(
|
||||
jetElement,
|
||||
JetNamedFunction.class,
|
||||
JetClassInitializer.class,
|
||||
JetProperty.class,
|
||||
JetParameter.class,
|
||||
JetDelegationSpecifierList.class,
|
||||
JetImportDirective.class,
|
||||
JetAnnotationEntry.class,
|
||||
JetTypeParameter.class,
|
||||
JetTypeConstraint.class,
|
||||
JetPackageDirective.class,
|
||||
JetCodeFragment.class);
|
||||
|
||||
if (elementOfAdditionalResolve != null && !(elementOfAdditionalResolve instanceof JetParameter)) {
|
||||
if (elementOfAdditionalResolve instanceof JetPackageDirective) {
|
||||
elementOfAdditionalResolve = jetElement;
|
||||
}
|
||||
|
||||
return getElementAdditionalResolve(elementOfAdditionalResolve);
|
||||
}
|
||||
|
||||
JetParameter parameter = (JetParameter) elementOfAdditionalResolve;
|
||||
if (parameter != null) {
|
||||
JetClass klass = PsiTreeUtil.getParentOfType(parameter, JetClass.class);
|
||||
if (klass != null && parameter.getParent() == klass.getPrimaryConstructorParameterList()) {
|
||||
return getElementAdditionalResolve(klass);
|
||||
}
|
||||
|
||||
// Parameters for function literal could be met inside other parameters. We can't make resolveToDescriptors for internal elements.
|
||||
jetElement = parameter;
|
||||
}
|
||||
|
||||
JetDeclaration declaration = PsiTreeUtil.getParentOfType(jetElement, JetDeclaration.class, false);
|
||||
if (declaration != null) {
|
||||
// Activate descriptor resolution
|
||||
resolveSession.resolveToDescriptor(declaration);
|
||||
}
|
||||
|
||||
return resolveSession.getBindingContext();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected BindingContext elementAdditionalResolve(@NotNull JetElement resolveElement) {
|
||||
// All additional resolve should be done to separate trace
|
||||
BindingTrace trace = resolveSession.getStorageManager().createSafeTrace(
|
||||
new DelegatingBindingTrace(resolveSession.getBindingContext(), "trace to resolve element", resolveElement));
|
||||
|
||||
JetFile file = resolveElement.getContainingJetFile();
|
||||
|
||||
if (resolveElement instanceof JetNamedFunction) {
|
||||
functionAdditionalResolve(resolveSession, (JetNamedFunction) resolveElement, trace, file);
|
||||
}
|
||||
else if (resolveElement instanceof JetClassInitializer) {
|
||||
initializerAdditionalResolve(resolveSession, (JetClassInitializer) resolveElement, trace, file);
|
||||
}
|
||||
else if (resolveElement instanceof JetProperty) {
|
||||
propertyAdditionalResolve(resolveSession, (JetProperty) resolveElement, trace, file);
|
||||
}
|
||||
else if (resolveElement instanceof JetDelegationSpecifierList) {
|
||||
delegationSpecifierAdditionalResolve(resolveSession, (JetDelegationSpecifierList) resolveElement, trace, file);
|
||||
}
|
||||
else if (resolveElement instanceof JetImportDirective) {
|
||||
JetImportDirective importDirective = (JetImportDirective) resolveElement;
|
||||
LazyImportScope scope = resolveSession.getScopeProvider().getExplicitImportsScopeForFile(importDirective.getContainingJetFile());
|
||||
scope.forceResolveAllContents();
|
||||
}
|
||||
else if (resolveElement instanceof JetAnnotationEntry) {
|
||||
annotationAdditionalResolve(resolveSession, (JetAnnotationEntry) resolveElement);
|
||||
}
|
||||
else if (resolveElement instanceof JetClass) {
|
||||
constructorAdditionalResolve(resolveSession, (JetClass) resolveElement, trace, file);
|
||||
}
|
||||
else if (resolveElement instanceof JetTypeParameter) {
|
||||
typeParameterAdditionalResolve(resolveSession, (JetTypeParameter) resolveElement);
|
||||
}
|
||||
else if (resolveElement instanceof JetTypeConstraint) {
|
||||
typeConstraintAdditionalResolve(resolveSession, (JetTypeConstraint) resolveElement);
|
||||
}
|
||||
else if (resolveElement instanceof JetCodeFragment) {
|
||||
codeFragmentAdditionalResolve(resolveSession, (JetCodeFragment) resolveElement, trace);
|
||||
}
|
||||
else if (PsiTreeUtil.getParentOfType(resolveElement, JetPackageDirective.class) != null) {
|
||||
packageRefAdditionalResolve(resolveSession, trace, resolveElement);
|
||||
}
|
||||
else {
|
||||
assert false : "Invalid type of the topmost parent";
|
||||
}
|
||||
|
||||
new JetFlowInformationProvider(resolveElement, trace).checkDeclaration();
|
||||
|
||||
return trace.getBindingContext();
|
||||
}
|
||||
|
||||
private static void packageRefAdditionalResolve(ResolveSession resolveSession, BindingTrace trace, JetElement jetElement) {
|
||||
if (jetElement instanceof JetSimpleNameExpression) {
|
||||
JetPackageDirective header = PsiTreeUtil.getParentOfType(jetElement, JetPackageDirective.class);
|
||||
assert header != null;
|
||||
|
||||
JetSimpleNameExpression packageNameExpression = (JetSimpleNameExpression) jetElement;
|
||||
if (trace.getBindingContext().get(BindingContext.RESOLUTION_SCOPE, packageNameExpression) == null) {
|
||||
JetScope scope = getExpressionMemberScope(resolveSession, packageNameExpression);
|
||||
if (scope != null) {
|
||||
trace.record(BindingContext.RESOLUTION_SCOPE, packageNameExpression, scope);
|
||||
}
|
||||
}
|
||||
|
||||
if (Name.isValidIdentifier(packageNameExpression.getReferencedName())) {
|
||||
if (trace.getBindingContext().get(BindingContext.REFERENCE_TARGET, packageNameExpression) == null) {
|
||||
FqName fqName = header.getFqName(packageNameExpression);
|
||||
PackageViewDescriptor packageDescriptor = resolveSession.getModuleDescriptor().getPackage(fqName);
|
||||
assert packageDescriptor != null: "Package descriptor should be present in session for " + fqName;
|
||||
trace.record(BindingContext.REFERENCE_TARGET, packageNameExpression, packageDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void typeConstraintAdditionalResolve(KotlinCodeAnalyzer analyzer, JetTypeConstraint jetTypeConstraint) {
|
||||
JetDeclaration declaration = PsiTreeUtil.getParentOfType(jetTypeConstraint, JetDeclaration.class);
|
||||
DeclarationDescriptor descriptor = analyzer.resolveToDescriptor(declaration);
|
||||
|
||||
assert (descriptor instanceof ClassDescriptor);
|
||||
|
||||
TypeConstructor constructor = ((ClassDescriptor) descriptor).getTypeConstructor();
|
||||
for (TypeParameterDescriptor parameterDescriptor : constructor.getParameters()) {
|
||||
LazyEntity lazyEntity = (LazyEntity) parameterDescriptor;
|
||||
lazyEntity.forceResolveAllContents();
|
||||
}
|
||||
}
|
||||
|
||||
private void codeFragmentAdditionalResolve(
|
||||
ResolveSession resolveSession,
|
||||
JetCodeFragment codeFragment,
|
||||
BindingTrace trace
|
||||
) {
|
||||
JetElement codeFragmentExpression = codeFragment.getContentElement();
|
||||
if (!(codeFragmentExpression instanceof JetExpression)) return;
|
||||
|
||||
PsiElement contextElement = codeFragment.getContext();
|
||||
if (!(contextElement instanceof JetExpression)) return;
|
||||
|
||||
JetExpression contextExpression = (JetExpression) contextElement;
|
||||
BindingContext contextForElement = resolveToElement(contextExpression);
|
||||
|
||||
JetScope scopeForContextElement = contextForElement.get(BindingContext.RESOLUTION_SCOPE, contextExpression);
|
||||
if (scopeForContextElement != null) {
|
||||
JetScope codeFragmentScope = resolveSession.getScopeProvider().getFileScope(codeFragment);
|
||||
ChainedScope chainedScope = new ChainedScope(
|
||||
scopeForContextElement.getContainingDeclaration(),
|
||||
"Scope for resolve code fragment",
|
||||
scopeForContextElement,
|
||||
codeFragmentScope
|
||||
);
|
||||
|
||||
DataFlowInfo dataFlowInfoForContextElement = contextForElement.get(BindingContext.EXPRESSION_DATA_FLOW_INFO, contextExpression);
|
||||
AnalyzerPackage.computeTypeInContext(
|
||||
(JetExpression) codeFragmentExpression,
|
||||
chainedScope,
|
||||
trace,
|
||||
dataFlowInfoForContextElement == null ? DataFlowInfo.EMPTY : dataFlowInfoForContextElement,
|
||||
TypeUtils.NO_EXPECTED_TYPE,
|
||||
resolveSession.getModuleDescriptor()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static void annotationAdditionalResolve(ResolveSession resolveSession, JetAnnotationEntry jetAnnotationEntry) {
|
||||
JetDeclaration declaration = PsiTreeUtil.getParentOfType(jetAnnotationEntry, JetDeclaration.class);
|
||||
if (declaration != null) {
|
||||
Annotated descriptor = resolveSession.resolveToDescriptor(declaration);
|
||||
|
||||
AnnotationResolver.resolveAnnotationsArguments(
|
||||
descriptor,
|
||||
resolveSession.getTrace()
|
||||
);
|
||||
|
||||
ForceResolveUtil.forceResolveAllContents(descriptor.getAnnotations());
|
||||
}
|
||||
}
|
||||
|
||||
private static void typeParameterAdditionalResolve(KotlinCodeAnalyzer analyzer, JetTypeParameter typeParameter) {
|
||||
DeclarationDescriptor descriptor = analyzer.resolveToDescriptor(typeParameter);
|
||||
assert descriptor instanceof LazyEntity;
|
||||
|
||||
LazyEntity parameterDescriptor = (LazyEntity) descriptor;
|
||||
parameterDescriptor.forceResolveAllContents();
|
||||
}
|
||||
|
||||
private static void delegationSpecifierAdditionalResolve(
|
||||
ResolveSession resolveSession,
|
||||
JetDelegationSpecifierList specifier, BindingTrace trace, JetFile file) {
|
||||
|
||||
JetClassOrObject classOrObject = (JetClassOrObject) specifier.getParent();
|
||||
LazyClassDescriptor descriptor = (LazyClassDescriptor) resolveSession.resolveToDescriptor(classOrObject);
|
||||
|
||||
// Activate resolving of supertypes
|
||||
descriptor.getTypeConstructor().getSupertypes();
|
||||
|
||||
BodyResolver bodyResolver = createBodyResolver(resolveSession, trace, file);
|
||||
bodyResolver.resolveDelegationSpecifierList(createEmptyContext(resolveSession), classOrObject, descriptor,
|
||||
descriptor.getUnsubstitutedPrimaryConstructor(),
|
||||
descriptor.getScopeForClassHeaderResolution(),
|
||||
descriptor.getScopeForMemberDeclarationResolution());
|
||||
}
|
||||
|
||||
private static void propertyAdditionalResolve(final ResolveSession resolveSession, final JetProperty jetProperty, BindingTrace trace, JetFile file) {
|
||||
JetScope propertyResolutionScope = resolveSession.getScopeProvider().getResolutionScopeForDeclaration(jetProperty);
|
||||
|
||||
BodyResolveContextForLazy bodyResolveContext = new BodyResolveContextForLazy(
|
||||
createParameters(resolveSession),
|
||||
new Function<JetDeclaration, JetScope>() {
|
||||
@Override
|
||||
public JetScope apply(JetDeclaration declaration) {
|
||||
assert declaration.getParent() == jetProperty : "Must be called only for property accessors, but called for " +
|
||||
declaration;
|
||||
return resolveSession.getScopeProvider().getResolutionScopeForDeclaration(declaration);
|
||||
}
|
||||
});
|
||||
BodyResolver bodyResolver = createBodyResolver(resolveSession, trace, file);
|
||||
PropertyDescriptor descriptor = (PropertyDescriptor) resolveSession.resolveToDescriptor(jetProperty);
|
||||
|
||||
JetExpression propertyInitializer = jetProperty.getInitializer();
|
||||
if (propertyInitializer != null) {
|
||||
bodyResolver.resolvePropertyInitializer(bodyResolveContext, jetProperty, descriptor, propertyInitializer, propertyResolutionScope);
|
||||
}
|
||||
|
||||
JetExpression propertyDelegate = jetProperty.getDelegateExpression();
|
||||
if (propertyDelegate != null) {
|
||||
bodyResolver.resolvePropertyDelegate(bodyResolveContext, jetProperty, descriptor, propertyDelegate, propertyResolutionScope, propertyResolutionScope);
|
||||
}
|
||||
|
||||
bodyResolver.resolvePropertyAccessors(bodyResolveContext, jetProperty, descriptor);
|
||||
|
||||
for (JetPropertyAccessor accessor : jetProperty.getAccessors()) {
|
||||
new JetFlowInformationProvider(accessor, trace).checkDeclaration();
|
||||
}
|
||||
}
|
||||
|
||||
private static void functionAdditionalResolve(
|
||||
ResolveSession resolveSession,
|
||||
JetNamedFunction namedFunction,
|
||||
BindingTrace trace,
|
||||
JetFile file
|
||||
) {
|
||||
JetScope scope = resolveSession.getScopeProvider().getResolutionScopeForDeclaration(namedFunction);
|
||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) resolveSession.resolveToDescriptor(namedFunction);
|
||||
|
||||
BodyResolver bodyResolver = createBodyResolver(resolveSession, trace, file);
|
||||
bodyResolver.resolveFunctionBody(createEmptyContext(resolveSession), trace, namedFunction, functionDescriptor, scope);
|
||||
}
|
||||
|
||||
private static void constructorAdditionalResolve(
|
||||
ResolveSession resolveSession,
|
||||
JetClass klass,
|
||||
BindingTrace trace,
|
||||
JetFile file
|
||||
) {
|
||||
JetScope scope = resolveSession.getScopeProvider().getResolutionScopeForDeclaration(klass);
|
||||
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) resolveSession.resolveToDescriptor(klass);
|
||||
ConstructorDescriptor constructorDescriptor = classDescriptor.getUnsubstitutedPrimaryConstructor();
|
||||
assert constructorDescriptor != null;
|
||||
|
||||
BodyResolver bodyResolver = createBodyResolver(resolveSession, trace, file);
|
||||
bodyResolver.resolveConstructorParameterDefaultValuesAndAnnotations(createEmptyContext(resolveSession), trace, klass,
|
||||
constructorDescriptor, scope);
|
||||
}
|
||||
|
||||
private static boolean initializerAdditionalResolve(
|
||||
ResolveSession resolveSession,
|
||||
JetClassInitializer classInitializer,
|
||||
BindingTrace trace,
|
||||
JetFile file
|
||||
) {
|
||||
JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(classInitializer, JetClassOrObject.class);
|
||||
LazyClassDescriptor classOrObjectDescriptor = (LazyClassDescriptor) resolveSession.resolveToDescriptor(classOrObject);
|
||||
|
||||
BodyResolver bodyResolver = createBodyResolver(resolveSession, trace, file);
|
||||
bodyResolver.resolveAnonymousInitializer(createEmptyContext(resolveSession), classInitializer, classOrObjectDescriptor);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static BodyResolver createBodyResolver(ResolveSession resolveSession, BindingTrace trace, JetFile file) {
|
||||
InjectorForBodyResolve bodyResolve = new InjectorForBodyResolve(
|
||||
file.getProject(),
|
||||
createParameters(resolveSession),
|
||||
trace,
|
||||
resolveSession.getModuleDescriptor()
|
||||
);
|
||||
return bodyResolve.getBodyResolver();
|
||||
}
|
||||
|
||||
private static TopDownAnalysisParameters createParameters(@NotNull ResolveSession resolveSession) {
|
||||
return TopDownAnalysisParameters.createForLocalDeclarations(
|
||||
resolveSession.getStorageManager(), resolveSession.getExceptionTracker(),
|
||||
Predicates.<PsiFile>alwaysTrue());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static BodyResolveContextForLazy createEmptyContext(@NotNull ResolveSession resolveSession) {
|
||||
return new BodyResolveContextForLazy(createParameters(resolveSession), Functions.<JetScope>constant(null));
|
||||
}
|
||||
|
||||
private static JetScope getExpressionResolutionScope(@NotNull ResolveSession resolveSession, @NotNull JetExpression expression) {
|
||||
ScopeProvider provider = resolveSession.getScopeProvider();
|
||||
JetDeclaration parentDeclaration = PsiTreeUtil.getParentOfType(expression, JetDeclaration.class);
|
||||
if (parentDeclaration == null) {
|
||||
return provider.getFileScope(expression.getContainingJetFile());
|
||||
}
|
||||
return provider.getResolutionScopeForDeclaration(parentDeclaration);
|
||||
}
|
||||
|
||||
private static JetScope getExpressionMemberScope(@NotNull ResolveSession resolveSession, @NotNull JetExpression expression) {
|
||||
BindingTrace trace = resolveSession.getStorageManager().createSafeTrace(new DelegatingBindingTrace(
|
||||
resolveSession.getBindingContext(), "trace to resolve a member scope of expression", expression));
|
||||
|
||||
if (BindingContextUtils.isExpressionWithValidReference(expression, resolveSession.getBindingContext())) {
|
||||
QualifiedExpressionResolver qualifiedExpressionResolver = resolveSession.getQualifiedExpressionResolver();
|
||||
|
||||
// In some type declaration
|
||||
if (expression.getParent() instanceof JetUserType) {
|
||||
JetUserType qualifier = ((JetUserType) expression.getParent()).getQualifier();
|
||||
if (qualifier != null) {
|
||||
Collection<? extends DeclarationDescriptor> descriptors = qualifiedExpressionResolver
|
||||
.lookupDescriptorsForUserType(qualifier, getExpressionResolutionScope(resolveSession, expression), trace);
|
||||
|
||||
for (DeclarationDescriptor descriptor : descriptors) {
|
||||
if (descriptor instanceof LazyPackageDescriptor) {
|
||||
return ((LazyPackageDescriptor) descriptor).getMemberScope();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Inside import
|
||||
if (PsiTreeUtil.getParentOfType(expression, JetImportDirective.class, false) != null) {
|
||||
PackageViewDescriptor rootPackage = resolveSession.getModuleDescriptor().getPackage(FqName.ROOT);
|
||||
assert rootPackage != null;
|
||||
|
||||
if (expression.getParent() instanceof JetDotQualifiedExpression) {
|
||||
JetExpression element = ((JetDotQualifiedExpression) expression.getParent()).getReceiverExpression();
|
||||
FqName fqName = expression.getContainingJetFile().getPackageFqName();
|
||||
|
||||
PackageViewDescriptor filePackage = resolveSession.getModuleDescriptor().getPackage(fqName);
|
||||
assert filePackage != null : "File package should be already resolved and be found";
|
||||
|
||||
JetScope scope = filePackage.getMemberScope();
|
||||
Collection<? extends DeclarationDescriptor> descriptors;
|
||||
|
||||
if (element instanceof JetDotQualifiedExpression) {
|
||||
descriptors = qualifiedExpressionResolver.lookupDescriptorsForQualifiedExpression(
|
||||
(JetDotQualifiedExpression) element, rootPackage.getMemberScope(), scope, trace,
|
||||
QualifiedExpressionResolver.LookupMode.EVERYTHING, false);
|
||||
}
|
||||
else {
|
||||
descriptors = qualifiedExpressionResolver.lookupDescriptorsForSimpleNameReference(
|
||||
(JetSimpleNameExpression) element, rootPackage.getMemberScope(), scope, trace,
|
||||
QualifiedExpressionResolver.LookupMode.EVERYTHING, false, false);
|
||||
}
|
||||
|
||||
for (DeclarationDescriptor descriptor : descriptors) {
|
||||
if (descriptor instanceof PackageViewDescriptor) {
|
||||
return ((PackageViewDescriptor) descriptor).getMemberScope();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
return rootPackage.getMemberScope();
|
||||
}
|
||||
}
|
||||
|
||||
// Inside package declaration
|
||||
JetPackageDirective packageDirective = PsiTreeUtil.getParentOfType(expression, JetPackageDirective.class, false);
|
||||
if (packageDirective != null) {
|
||||
PackageViewDescriptor packageDescriptor = resolveSession.getModuleDescriptor().getPackage(
|
||||
packageDirective.getFqName((JetSimpleNameExpression) expression).parent());
|
||||
if (packageDescriptor != null) {
|
||||
return packageDescriptor.getMemberScope();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static class BodyResolveContextForLazy implements BodiesResolveContext {
|
||||
|
||||
private final Function<? super JetDeclaration, JetScope> declaringScopes;
|
||||
private final TopDownAnalysisParameters topDownAnalysisParameters;
|
||||
|
||||
private BodyResolveContextForLazy(
|
||||
@NotNull TopDownAnalysisParameters parameters,
|
||||
@NotNull Function<? super JetDeclaration, JetScope> declaringScopes
|
||||
) {
|
||||
this.topDownAnalysisParameters = parameters;
|
||||
this.declaringScopes = declaringScopes;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public StorageManager getStorageManager() {
|
||||
return topDownAnalysisParameters.getStorageManager();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ExceptionTracker getExceptionTracker() {
|
||||
return topDownAnalysisParameters.getExceptionTracker();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<JetFile> getFiles() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<JetClassOrObject, ClassDescriptorWithResolutionScopes> getDeclaredClasses() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<JetClassInitializer, ClassDescriptorWithResolutionScopes> getAnonymousInitializers() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<JetProperty, PropertyDescriptor> getProperties() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<JetNamedFunction, SimpleFunctionDescriptor> getFunctions() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<JetDeclaration, JetScope> getDeclaringScopes() {
|
||||
//noinspection unchecked
|
||||
return (Function<JetDeclaration, JetScope>) declaringScopes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<JetScript, ScriptDescriptor> getScripts() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataFlowInfo getOuterDataFlowInfo() {
|
||||
return DataFlowInfo.EMPTY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public TopDownAnalysisParameters getTopDownAnalysisParameters() {
|
||||
return topDownAnalysisParameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean completeAnalysisNeeded(@NotNull PsiElement element) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,7 @@
|
||||
<orderEntry type="module" module-name="util" />
|
||||
<orderEntry type="module" module-name="js.frontend" />
|
||||
<orderEntry type="library" name="trove4j" level="project" />
|
||||
<orderEntry type="module" module-name="ide-lazy-resolve" exported="" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
|
||||
@@ -16,48 +16,26 @@
|
||||
|
||||
package org.jetbrains.jet.plugin.project;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Functions;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.psi.util.CachedValue;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import kotlin.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.analyzer.AnalyzerPackage;
|
||||
import org.jetbrains.jet.di.InjectorForBodyResolve;
|
||||
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.Annotated;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.*;
|
||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
||||
import org.jetbrains.jet.lang.resolve.lazy.*;
|
||||
import org.jetbrains.jet.lang.resolve.lazy.descriptors.LazyClassDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.lazy.descriptors.LazyPackageDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.ChainedScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.types.TypeConstructor;
|
||||
import org.jetbrains.jet.lang.types.TypeUtils;
|
||||
import org.jetbrains.jet.storage.ExceptionTracker;
|
||||
import org.jetbrains.jet.lang.psi.JetElement;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.lazy.ElementResolver;
|
||||
import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
|
||||
import org.jetbrains.jet.storage.LazyResolveStorageManager;
|
||||
import org.jetbrains.jet.storage.MemoizedFunctionToNotNull;
|
||||
import org.jetbrains.jet.storage.StorageManager;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
public class ResolveElementCache {
|
||||
public class ResolveElementCache extends ElementResolver {
|
||||
private final CachedValue<MemoizedFunctionToNotNull<JetElement, BindingContext>> additionalResolveCache;
|
||||
private final ResolveSession resolveSession;
|
||||
|
||||
public ResolveElementCache(ResolveSession resolveSession, Project project) {
|
||||
this.resolveSession = resolveSession;
|
||||
super(resolveSession);
|
||||
|
||||
// Recreate internal cache after change of modification count
|
||||
this.additionalResolveCache =
|
||||
@@ -84,469 +62,8 @@ public class ResolveElementCache {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public BindingContext resolveToElement(@NotNull JetElement jetElement) {
|
||||
@SuppressWarnings("unchecked") JetElement elementOfAdditionalResolve = (JetElement) JetPsiUtil.getTopmostParentOfTypes(
|
||||
jetElement,
|
||||
JetNamedFunction.class,
|
||||
JetClassInitializer.class,
|
||||
JetProperty.class,
|
||||
JetParameter.class,
|
||||
JetDelegationSpecifierList.class,
|
||||
JetImportDirective.class,
|
||||
JetAnnotationEntry.class,
|
||||
JetTypeParameter.class,
|
||||
JetTypeConstraint.class,
|
||||
JetPackageDirective.class,
|
||||
JetCodeFragment.class);
|
||||
|
||||
if (elementOfAdditionalResolve != null && !(elementOfAdditionalResolve instanceof JetParameter)) {
|
||||
if (elementOfAdditionalResolve instanceof JetPackageDirective) {
|
||||
elementOfAdditionalResolve = jetElement;
|
||||
}
|
||||
|
||||
return additionalResolveCache.getValue().invoke(elementOfAdditionalResolve);
|
||||
}
|
||||
|
||||
JetParameter parameter = (JetParameter) elementOfAdditionalResolve;
|
||||
if (parameter != null) {
|
||||
JetClass klass = PsiTreeUtil.getParentOfType(parameter, JetClass.class);
|
||||
if (klass != null && parameter.getParent() == klass.getPrimaryConstructorParameterList()) {
|
||||
return additionalResolveCache.getValue().invoke(klass);
|
||||
}
|
||||
|
||||
// Parameters for function literal could be met inside other parameters. We can't make resolveToDescriptors for internal elements.
|
||||
jetElement = parameter;
|
||||
}
|
||||
|
||||
JetDeclaration declaration = PsiTreeUtil.getParentOfType(jetElement, JetDeclaration.class, false);
|
||||
if (declaration != null) {
|
||||
// Activate descriptor resolution
|
||||
resolveSession.resolveToDescriptor(declaration);
|
||||
}
|
||||
|
||||
return resolveSession.getBindingContext();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private BindingContext elementAdditionalResolve(@NotNull JetElement resolveElement) {
|
||||
// All additional resolve should be done to separate trace
|
||||
BindingTrace trace = resolveSession.getStorageManager().createSafeTrace(
|
||||
new DelegatingBindingTrace(resolveSession.getBindingContext(), "trace to resolve element", resolveElement));
|
||||
|
||||
JetFile file = resolveElement.getContainingJetFile();
|
||||
|
||||
if (resolveElement instanceof JetNamedFunction) {
|
||||
functionAdditionalResolve(resolveSession, (JetNamedFunction) resolveElement, trace, file);
|
||||
}
|
||||
else if (resolveElement instanceof JetClassInitializer) {
|
||||
initializerAdditionalResolve(resolveSession, (JetClassInitializer) resolveElement, trace, file);
|
||||
}
|
||||
else if (resolveElement instanceof JetProperty) {
|
||||
propertyAdditionalResolve(resolveSession, (JetProperty) resolveElement, trace, file);
|
||||
}
|
||||
else if (resolveElement instanceof JetDelegationSpecifierList) {
|
||||
delegationSpecifierAdditionalResolve(resolveSession, (JetDelegationSpecifierList) resolveElement, trace, file);
|
||||
}
|
||||
else if (resolveElement instanceof JetImportDirective) {
|
||||
JetImportDirective importDirective = (JetImportDirective) resolveElement;
|
||||
LazyImportScope scope = resolveSession.getScopeProvider().getExplicitImportsScopeForFile(importDirective.getContainingJetFile());
|
||||
scope.forceResolveAllContents();
|
||||
}
|
||||
else if (resolveElement instanceof JetAnnotationEntry) {
|
||||
annotationAdditionalResolve(resolveSession, (JetAnnotationEntry) resolveElement);
|
||||
}
|
||||
else if (resolveElement instanceof JetClass) {
|
||||
constructorAdditionalResolve(resolveSession, (JetClass) resolveElement, trace, file);
|
||||
}
|
||||
else if (resolveElement instanceof JetTypeParameter) {
|
||||
typeParameterAdditionalResolve(resolveSession, (JetTypeParameter) resolveElement);
|
||||
}
|
||||
else if (resolveElement instanceof JetTypeConstraint) {
|
||||
typeConstraintAdditionalResolve(resolveSession, (JetTypeConstraint) resolveElement);
|
||||
}
|
||||
else if (resolveElement instanceof JetCodeFragment) {
|
||||
codeFragmentAdditionalResolve(resolveSession, (JetCodeFragment) resolveElement, trace);
|
||||
}
|
||||
else if (PsiTreeUtil.getParentOfType(resolveElement, JetPackageDirective.class) != null) {
|
||||
packageRefAdditionalResolve(resolveSession, trace, resolveElement);
|
||||
}
|
||||
else {
|
||||
assert false : "Invalid type of the topmost parent";
|
||||
}
|
||||
|
||||
new JetFlowInformationProvider(resolveElement, trace).checkDeclaration();
|
||||
|
||||
return trace.getBindingContext();
|
||||
}
|
||||
|
||||
private static void packageRefAdditionalResolve(ResolveSession resolveSession, BindingTrace trace, JetElement jetElement) {
|
||||
if (jetElement instanceof JetSimpleNameExpression) {
|
||||
JetPackageDirective header = PsiTreeUtil.getParentOfType(jetElement, JetPackageDirective.class);
|
||||
assert header != null;
|
||||
|
||||
JetSimpleNameExpression packageNameExpression = (JetSimpleNameExpression) jetElement;
|
||||
if (trace.getBindingContext().get(BindingContext.RESOLUTION_SCOPE, packageNameExpression) == null) {
|
||||
JetScope scope = getExpressionMemberScope(resolveSession, packageNameExpression);
|
||||
if (scope != null) {
|
||||
trace.record(BindingContext.RESOLUTION_SCOPE, packageNameExpression, scope);
|
||||
}
|
||||
}
|
||||
|
||||
if (Name.isValidIdentifier(packageNameExpression.getReferencedName())) {
|
||||
if (trace.getBindingContext().get(BindingContext.REFERENCE_TARGET, packageNameExpression) == null) {
|
||||
FqName fqName = header.getFqName(packageNameExpression);
|
||||
PackageViewDescriptor packageDescriptor = resolveSession.getModuleDescriptor().getPackage(fqName);
|
||||
assert packageDescriptor != null: "Package descriptor should be present in session for " + fqName;
|
||||
trace.record(BindingContext.REFERENCE_TARGET, packageNameExpression, packageDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void typeConstraintAdditionalResolve(KotlinCodeAnalyzer analyzer, JetTypeConstraint jetTypeConstraint) {
|
||||
JetDeclaration declaration = PsiTreeUtil.getParentOfType(jetTypeConstraint, JetDeclaration.class);
|
||||
DeclarationDescriptor descriptor = analyzer.resolveToDescriptor(declaration);
|
||||
|
||||
assert (descriptor instanceof ClassDescriptor);
|
||||
|
||||
TypeConstructor constructor = ((ClassDescriptor) descriptor).getTypeConstructor();
|
||||
for (TypeParameterDescriptor parameterDescriptor : constructor.getParameters()) {
|
||||
LazyEntity lazyEntity = (LazyEntity) parameterDescriptor;
|
||||
lazyEntity.forceResolveAllContents();
|
||||
}
|
||||
}
|
||||
|
||||
private void codeFragmentAdditionalResolve(
|
||||
ResolveSession resolveSession,
|
||||
JetCodeFragment codeFragment,
|
||||
BindingTrace trace
|
||||
) {
|
||||
JetElement codeFragmentExpression = codeFragment.getContentElement();
|
||||
if (!(codeFragmentExpression instanceof JetExpression)) return;
|
||||
|
||||
PsiElement contextElement = codeFragment.getContext();
|
||||
if (!(contextElement instanceof JetExpression)) return;
|
||||
|
||||
JetExpression contextExpression = (JetExpression) contextElement;
|
||||
BindingContext contextForElement = resolveToElement(contextExpression);
|
||||
|
||||
JetScope scopeForContextElement = contextForElement.get(BindingContext.RESOLUTION_SCOPE, contextExpression);
|
||||
if (scopeForContextElement != null) {
|
||||
JetScope codeFragmentScope = resolveSession.getScopeProvider().getFileScope(codeFragment);
|
||||
ChainedScope chainedScope = new ChainedScope(
|
||||
scopeForContextElement.getContainingDeclaration(),
|
||||
"Scope for resolve code fragment",
|
||||
scopeForContextElement,
|
||||
codeFragmentScope
|
||||
);
|
||||
|
||||
DataFlowInfo dataFlowInfoForContextElement = contextForElement.get(BindingContext.EXPRESSION_DATA_FLOW_INFO, contextExpression);
|
||||
AnalyzerPackage.computeTypeInContext(
|
||||
(JetExpression) codeFragmentExpression,
|
||||
chainedScope,
|
||||
trace,
|
||||
dataFlowInfoForContextElement == null ? DataFlowInfo.EMPTY : dataFlowInfoForContextElement,
|
||||
TypeUtils.NO_EXPECTED_TYPE,
|
||||
resolveSession.getModuleDescriptor()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static void annotationAdditionalResolve(ResolveSession resolveSession, JetAnnotationEntry jetAnnotationEntry) {
|
||||
JetDeclaration declaration = PsiTreeUtil.getParentOfType(jetAnnotationEntry, JetDeclaration.class);
|
||||
if (declaration != null) {
|
||||
Annotated descriptor = resolveSession.resolveToDescriptor(declaration);
|
||||
|
||||
AnnotationResolver.resolveAnnotationsArguments(
|
||||
descriptor,
|
||||
resolveSession.getTrace()
|
||||
);
|
||||
|
||||
ForceResolveUtil.forceResolveAllContents(descriptor.getAnnotations());
|
||||
}
|
||||
}
|
||||
|
||||
private static void typeParameterAdditionalResolve(KotlinCodeAnalyzer analyzer, JetTypeParameter typeParameter) {
|
||||
DeclarationDescriptor descriptor = analyzer.resolveToDescriptor(typeParameter);
|
||||
assert descriptor instanceof LazyEntity;
|
||||
|
||||
LazyEntity parameterDescriptor = (LazyEntity) descriptor;
|
||||
parameterDescriptor.forceResolveAllContents();
|
||||
}
|
||||
|
||||
private static void delegationSpecifierAdditionalResolve(
|
||||
ResolveSession resolveSession,
|
||||
JetDelegationSpecifierList specifier, BindingTrace trace, JetFile file) {
|
||||
|
||||
JetClassOrObject classOrObject = (JetClassOrObject) specifier.getParent();
|
||||
LazyClassDescriptor descriptor = (LazyClassDescriptor) resolveSession.resolveToDescriptor(classOrObject);
|
||||
|
||||
// Activate resolving of supertypes
|
||||
descriptor.getTypeConstructor().getSupertypes();
|
||||
|
||||
BodyResolver bodyResolver = createBodyResolver(resolveSession, trace, file);
|
||||
bodyResolver.resolveDelegationSpecifierList(createEmptyContext(resolveSession), classOrObject, descriptor,
|
||||
descriptor.getUnsubstitutedPrimaryConstructor(),
|
||||
descriptor.getScopeForClassHeaderResolution(),
|
||||
descriptor.getScopeForMemberDeclarationResolution());
|
||||
}
|
||||
|
||||
private static void propertyAdditionalResolve(final ResolveSession resolveSession, final JetProperty jetProperty, BindingTrace trace, JetFile file) {
|
||||
JetScope propertyResolutionScope = resolveSession.getScopeProvider().getResolutionScopeForDeclaration(jetProperty);
|
||||
|
||||
BodyResolveContextForLazy bodyResolveContext = new BodyResolveContextForLazy(
|
||||
createParameters(resolveSession),
|
||||
new Function<JetDeclaration, JetScope>() {
|
||||
@Override
|
||||
public JetScope apply(JetDeclaration declaration) {
|
||||
assert declaration.getParent() == jetProperty : "Must be called only for property accessors, but called for " +
|
||||
declaration;
|
||||
return resolveSession.getScopeProvider().getResolutionScopeForDeclaration(declaration);
|
||||
}
|
||||
});
|
||||
BodyResolver bodyResolver = createBodyResolver(resolveSession, trace, file);
|
||||
PropertyDescriptor descriptor = (PropertyDescriptor) resolveSession.resolveToDescriptor(jetProperty);
|
||||
|
||||
JetExpression propertyInitializer = jetProperty.getInitializer();
|
||||
if (propertyInitializer != null) {
|
||||
bodyResolver.resolvePropertyInitializer(bodyResolveContext, jetProperty, descriptor, propertyInitializer, propertyResolutionScope);
|
||||
}
|
||||
|
||||
JetExpression propertyDelegate = jetProperty.getDelegateExpression();
|
||||
if (propertyDelegate != null) {
|
||||
bodyResolver.resolvePropertyDelegate(bodyResolveContext, jetProperty, descriptor, propertyDelegate, propertyResolutionScope, propertyResolutionScope);
|
||||
}
|
||||
|
||||
bodyResolver.resolvePropertyAccessors(bodyResolveContext, jetProperty, descriptor);
|
||||
|
||||
for (JetPropertyAccessor accessor : jetProperty.getAccessors()) {
|
||||
new JetFlowInformationProvider(accessor, trace).checkDeclaration();
|
||||
}
|
||||
}
|
||||
|
||||
private static void functionAdditionalResolve(
|
||||
ResolveSession resolveSession,
|
||||
JetNamedFunction namedFunction,
|
||||
BindingTrace trace,
|
||||
JetFile file
|
||||
) {
|
||||
JetScope scope = resolveSession.getScopeProvider().getResolutionScopeForDeclaration(namedFunction);
|
||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) resolveSession.resolveToDescriptor(namedFunction);
|
||||
|
||||
BodyResolver bodyResolver = createBodyResolver(resolveSession, trace, file);
|
||||
bodyResolver.resolveFunctionBody(createEmptyContext(resolveSession), trace, namedFunction, functionDescriptor, scope);
|
||||
}
|
||||
|
||||
private static void constructorAdditionalResolve(
|
||||
ResolveSession resolveSession,
|
||||
JetClass klass,
|
||||
BindingTrace trace,
|
||||
JetFile file
|
||||
) {
|
||||
JetScope scope = resolveSession.getScopeProvider().getResolutionScopeForDeclaration(klass);
|
||||
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) resolveSession.resolveToDescriptor(klass);
|
||||
ConstructorDescriptor constructorDescriptor = classDescriptor.getUnsubstitutedPrimaryConstructor();
|
||||
assert constructorDescriptor != null;
|
||||
|
||||
BodyResolver bodyResolver = createBodyResolver(resolveSession, trace, file);
|
||||
bodyResolver.resolveConstructorParameterDefaultValuesAndAnnotations(createEmptyContext(resolveSession), trace, klass,
|
||||
constructorDescriptor, scope);
|
||||
}
|
||||
|
||||
private static boolean initializerAdditionalResolve(
|
||||
ResolveSession resolveSession,
|
||||
JetClassInitializer classInitializer,
|
||||
BindingTrace trace,
|
||||
JetFile file
|
||||
) {
|
||||
JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(classInitializer, JetClassOrObject.class);
|
||||
LazyClassDescriptor classOrObjectDescriptor = (LazyClassDescriptor) resolveSession.resolveToDescriptor(classOrObject);
|
||||
|
||||
BodyResolver bodyResolver = createBodyResolver(resolveSession, trace, file);
|
||||
bodyResolver.resolveAnonymousInitializer(createEmptyContext(resolveSession), classInitializer, classOrObjectDescriptor);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static BodyResolver createBodyResolver(ResolveSession resolveSession, BindingTrace trace, JetFile file) {
|
||||
InjectorForBodyResolve bodyResolve = new InjectorForBodyResolve(
|
||||
file.getProject(),
|
||||
createParameters(resolveSession),
|
||||
trace,
|
||||
resolveSession.getModuleDescriptor()
|
||||
);
|
||||
return bodyResolve.getBodyResolver();
|
||||
}
|
||||
|
||||
private static TopDownAnalysisParameters createParameters(@NotNull ResolveSession resolveSession) {
|
||||
return TopDownAnalysisParameters.createForLocalDeclarations(
|
||||
resolveSession.getStorageManager(), resolveSession.getExceptionTracker(),
|
||||
Predicates.<PsiFile>alwaysTrue());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static BodyResolveContextForLazy createEmptyContext(@NotNull ResolveSession resolveSession) {
|
||||
return new BodyResolveContextForLazy(createParameters(resolveSession), Functions.<JetScope>constant(null));
|
||||
}
|
||||
|
||||
private static JetScope getExpressionResolutionScope(@NotNull ResolveSession resolveSession, @NotNull JetExpression expression) {
|
||||
ScopeProvider provider = resolveSession.getScopeProvider();
|
||||
JetDeclaration parentDeclaration = PsiTreeUtil.getParentOfType(expression, JetDeclaration.class);
|
||||
if (parentDeclaration == null) {
|
||||
return provider.getFileScope(expression.getContainingJetFile());
|
||||
}
|
||||
return provider.getResolutionScopeForDeclaration(parentDeclaration);
|
||||
}
|
||||
|
||||
private static JetScope getExpressionMemberScope(@NotNull ResolveSession resolveSession, @NotNull JetExpression expression) {
|
||||
BindingTrace trace = resolveSession.getStorageManager().createSafeTrace(new DelegatingBindingTrace(
|
||||
resolveSession.getBindingContext(), "trace to resolve a member scope of expression", expression));
|
||||
|
||||
if (BindingContextUtils.isExpressionWithValidReference(expression, resolveSession.getBindingContext())) {
|
||||
QualifiedExpressionResolver qualifiedExpressionResolver = resolveSession.getQualifiedExpressionResolver();
|
||||
|
||||
// In some type declaration
|
||||
if (expression.getParent() instanceof JetUserType) {
|
||||
JetUserType qualifier = ((JetUserType) expression.getParent()).getQualifier();
|
||||
if (qualifier != null) {
|
||||
Collection<? extends DeclarationDescriptor> descriptors = qualifiedExpressionResolver
|
||||
.lookupDescriptorsForUserType(qualifier, getExpressionResolutionScope(resolveSession, expression), trace);
|
||||
|
||||
for (DeclarationDescriptor descriptor : descriptors) {
|
||||
if (descriptor instanceof LazyPackageDescriptor) {
|
||||
return ((LazyPackageDescriptor) descriptor).getMemberScope();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Inside import
|
||||
if (PsiTreeUtil.getParentOfType(expression, JetImportDirective.class, false) != null) {
|
||||
PackageViewDescriptor rootPackage = resolveSession.getModuleDescriptor().getPackage(FqName.ROOT);
|
||||
assert rootPackage != null;
|
||||
|
||||
if (expression.getParent() instanceof JetDotQualifiedExpression) {
|
||||
JetExpression element = ((JetDotQualifiedExpression) expression.getParent()).getReceiverExpression();
|
||||
FqName fqName = expression.getContainingJetFile().getPackageFqName();
|
||||
|
||||
PackageViewDescriptor filePackage = resolveSession.getModuleDescriptor().getPackage(fqName);
|
||||
assert filePackage != null : "File package should be already resolved and be found";
|
||||
|
||||
JetScope scope = filePackage.getMemberScope();
|
||||
Collection<? extends DeclarationDescriptor> descriptors;
|
||||
|
||||
if (element instanceof JetDotQualifiedExpression) {
|
||||
descriptors = qualifiedExpressionResolver.lookupDescriptorsForQualifiedExpression(
|
||||
(JetDotQualifiedExpression) element, rootPackage.getMemberScope(), scope, trace,
|
||||
QualifiedExpressionResolver.LookupMode.EVERYTHING, false);
|
||||
}
|
||||
else {
|
||||
descriptors = qualifiedExpressionResolver.lookupDescriptorsForSimpleNameReference(
|
||||
(JetSimpleNameExpression) element, rootPackage.getMemberScope(), scope, trace,
|
||||
QualifiedExpressionResolver.LookupMode.EVERYTHING, false, false);
|
||||
}
|
||||
|
||||
for (DeclarationDescriptor descriptor : descriptors) {
|
||||
if (descriptor instanceof PackageViewDescriptor) {
|
||||
return ((PackageViewDescriptor) descriptor).getMemberScope();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
return rootPackage.getMemberScope();
|
||||
}
|
||||
}
|
||||
|
||||
// Inside package declaration
|
||||
JetPackageDirective packageDirective = PsiTreeUtil.getParentOfType(expression, JetPackageDirective.class, false);
|
||||
if (packageDirective != null) {
|
||||
PackageViewDescriptor packageDescriptor = resolveSession.getModuleDescriptor().getPackage(
|
||||
packageDirective.getFqName((JetSimpleNameExpression) expression).parent());
|
||||
if (packageDescriptor != null) {
|
||||
return packageDescriptor.getMemberScope();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static class BodyResolveContextForLazy implements BodiesResolveContext {
|
||||
|
||||
private final Function<? super JetDeclaration, JetScope> declaringScopes;
|
||||
private final TopDownAnalysisParameters topDownAnalysisParameters;
|
||||
|
||||
private BodyResolveContextForLazy(
|
||||
@NotNull TopDownAnalysisParameters parameters,
|
||||
@NotNull Function<? super JetDeclaration, JetScope> declaringScopes
|
||||
) {
|
||||
this.topDownAnalysisParameters = parameters;
|
||||
this.declaringScopes = declaringScopes;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public StorageManager getStorageManager() {
|
||||
return topDownAnalysisParameters.getStorageManager();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ExceptionTracker getExceptionTracker() {
|
||||
return topDownAnalysisParameters.getExceptionTracker();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<JetFile> getFiles() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<JetClassOrObject, ClassDescriptorWithResolutionScopes> getDeclaredClasses() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<JetClassInitializer, ClassDescriptorWithResolutionScopes> getAnonymousInitializers() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<JetProperty, PropertyDescriptor> getProperties() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<JetNamedFunction, SimpleFunctionDescriptor> getFunctions() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<JetDeclaration, JetScope> getDeclaringScopes() {
|
||||
//noinspection unchecked
|
||||
return (Function<JetDeclaration, JetScope>) declaringScopes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<JetScript, ScriptDescriptor> getScripts() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataFlowInfo getOuterDataFlowInfo() {
|
||||
return DataFlowInfo.EMPTY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public TopDownAnalysisParameters getTopDownAnalysisParameters() {
|
||||
return topDownAnalysisParameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean completeAnalysisNeeded(@NotNull PsiElement element) {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public BindingContext getElementAdditionalResolve(@NotNull JetElement jetElement) {
|
||||
return additionalResolveCache.getValue().invoke(jetElement);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user