Rename module: ide-lazy-resolve -> ide-common

This commit is contained in:
Nikolay Krasko
2014-10-29 17:59:20 +03:00
parent 4e99572dbc
commit 3a10416192
7 changed files with 14 additions and 16 deletions
+25
View File
@@ -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="guava" level="project" />
<orderEntry type="module" module-name="util" />
<orderEntry type="library" name="intellij-core" level="project" />
<orderEntry type="module" module-name="frontend.java" />
</component>
</module>
@@ -0,0 +1,559 @@
/*
* 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.descriptors.annotations.Annotations;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.calls.smartcasts.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;
import static org.jetbrains.jet.lang.resolve.bindingContextUtil.BindingContextUtilPackage.getDataFlowInfo;
public abstract 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 = getDataFlowInfo(contextForElement, contextExpression);
AnalyzerPackage.computeTypeInContext(
(JetExpression) codeFragmentExpression,
chainedScope,
trace,
dataFlowInfoForContextElement,
TypeUtils.NO_EXPECTED_TYPE,
resolveSession.getModuleDescriptor()
);
}
}
private static void annotationAdditionalResolve(ResolveSession resolveSession, JetAnnotationEntry jetAnnotationEntry) {
Annotations annotations = null;
JetModifierList modifierList = PsiTreeUtil.getParentOfType(jetAnnotationEntry, JetModifierList.class);
JetDeclaration declaration = PsiTreeUtil.getParentOfType(modifierList, JetDeclaration.class);
if (declaration != null) {
annotations = getAnnotationsByDeclaration(resolveSession, modifierList, declaration);
}
else {
JetFileAnnotationList fileAnnotationList = PsiTreeUtil.getParentOfType(jetAnnotationEntry, JetFileAnnotationList.class);
if (fileAnnotationList != null) {
annotations = resolveSession.getFileAnnotations(fileAnnotationList.getContainingJetFile());
}
}
if (annotations != null) {
AnnotationResolver.resolveAnnotationsArguments(annotations, resolveSession.getTrace());
ForceResolveUtil.forceResolveAllContents(annotations);
}
}
private static Annotations getAnnotationsByDeclaration(
ResolveSession resolveSession,
JetModifierList modifierList,
JetDeclaration declaration
) {
Annotations annotations;Annotated descriptor = resolveSession.resolveToDescriptor(declaration);
if (declaration instanceof JetClass && modifierList == ((JetClass) declaration).getPrimaryConstructorModifierList()) {
descriptor = ((ClassDescriptor)descriptor).getUnsubstitutedPrimaryConstructor();
assert descriptor != null : "No constructor found: " + declaration.getText();
}
annotations = descriptor.getAnnotations();
return annotations;
}
private static void typeParameterAdditionalResolve(KotlinCodeAnalyzer analyzer, JetTypeParameter typeParameter) {
DeclarationDescriptor descriptor = analyzer.resolveToDescriptor(typeParameter);
assert descriptor instanceof LazyEntity;
LazyEntity parameterDescriptor = (LazyEntity) descriptor;
parameterDescriptor.forceResolveAllContents();
}
private 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 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 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 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 :
String.format("Can't get primary constructor for descriptor '%s' in from class '%s'",
classDescriptor,
JetPsiUtil.getElementTextWithContext(klass));
BodyResolver bodyResolver = createBodyResolver(resolveSession, trace, file);
bodyResolver.resolveConstructorParameterDefaultValuesAndAnnotations(createEmptyContext(resolveSession), trace, klass,
constructorDescriptor, scope);
}
private 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 BodyResolver createBodyResolver(ResolveSession resolveSession, BindingTrace trace, JetFile file) {
InjectorForBodyResolve bodyResolve = new InjectorForBodyResolve(
file.getProject(),
createParameters(resolveSession),
trace,
resolveSession.getModuleDescriptor(),
getAdditionalCheckerProvider(file)
);
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) {
JetScope resolutionScope = getExpressionResolutionScope(resolveSession, expression);
Collection<DeclarationDescriptor> descriptors =
qualifiedExpressionResolver.lookupDescriptorsForUserType(qualifier, resolutionScope, 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;
}
@NotNull
protected abstract AdditionalCheckerProvider getAdditionalCheckerProvider(@NotNull JetFile jetFile);
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;
}
}
}