提交 c54d235d 编写于 作者: A Andrey Breslav

Working on type inference for recursive definitions

上级 d40bec3e
...@@ -3,6 +3,7 @@ package org.jetbrains.jet.lang; ...@@ -3,6 +3,7 @@ package org.jetbrains.jet.lang;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider; import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
...@@ -11,22 +12,28 @@ import org.jetbrains.jet.lang.types.*; ...@@ -11,22 +12,28 @@ import org.jetbrains.jet.lang.types.*;
*/ */
public class JetSemanticServices { public class JetSemanticServices {
public static JetSemanticServices createSemanticServices(JetStandardLibrary standardLibrary) { public static JetSemanticServices createSemanticServices(JetStandardLibrary standardLibrary) {
return new JetSemanticServices(standardLibrary); return new JetSemanticServices(standardLibrary, JetControlFlowDataTraceFactory.EMPTY);
} }
public static JetSemanticServices createSemanticServices(Project project) { public static JetSemanticServices createSemanticServices(Project project) {
return new JetSemanticServices(JetStandardLibrary.getJetStandardLibrary(project)); return new JetSemanticServices(JetStandardLibrary.getJetStandardLibrary(project), JetControlFlowDataTraceFactory.EMPTY);
}
public static JetSemanticServices createSemanticServices(Project project, JetControlFlowDataTraceFactory flowDataTraceFactory) {
return new JetSemanticServices(JetStandardLibrary.getJetStandardLibrary(project), flowDataTraceFactory);
} }
private final JetStandardLibrary standardLibrary; private final JetStandardLibrary standardLibrary;
private final JetTypeChecker typeChecker; private final JetTypeChecker typeChecker;
private final OverloadResolver overloadResolver; private final OverloadResolver overloadResolver;
private final JetControlFlowDataTraceFactory flowDataTraceFactory;
private JetSemanticServices(JetStandardLibrary standardLibrary) { private JetSemanticServices(JetStandardLibrary standardLibrary, JetControlFlowDataTraceFactory flowDataTraceFactory) {
this.standardLibrary = standardLibrary; this.standardLibrary = standardLibrary;
this.typeChecker = new JetTypeChecker(standardLibrary); this.typeChecker = new JetTypeChecker(standardLibrary);
this.overloadResolver = new OverloadResolver(typeChecker); this.overloadResolver = new OverloadResolver(typeChecker);
this.flowDataTraceFactory = flowDataTraceFactory;
} }
@NotNull @NotNull
...@@ -36,7 +43,7 @@ public class JetSemanticServices { ...@@ -36,7 +43,7 @@ public class JetSemanticServices {
@NotNull @NotNull
public ClassDescriptorResolver getClassDescriptorResolver(BindingTrace trace) { public ClassDescriptorResolver getClassDescriptorResolver(BindingTrace trace) {
return new ClassDescriptorResolver(this, trace); return new ClassDescriptorResolver(this, trace, flowDataTraceFactory);
} }
@NotNull @NotNull
......
...@@ -47,6 +47,7 @@ public class JetLineMarkerProvider implements LineMarkerProvider { ...@@ -47,6 +47,7 @@ public class JetLineMarkerProvider implements LineMarkerProvider {
assert file != null; assert file != null;
final BindingContext bindingContext = AnalyzingUtils.analyzeFileWithCache(file); final BindingContext bindingContext = AnalyzingUtils.analyzeFileWithCache(file);
FunctionDescriptor functionDescriptor = bindingContext.getFunctionDescriptor(jetFunction); FunctionDescriptor functionDescriptor = bindingContext.getFunctionDescriptor(jetFunction);
if (functionDescriptor == null) return null;
final Set<? extends FunctionDescriptor> overriddenFunctions = functionDescriptor.getOverriddenFunctions(); final Set<? extends FunctionDescriptor> overriddenFunctions = functionDescriptor.getOverriddenFunctions();
if (!overriddenFunctions.isEmpty()) { if (!overriddenFunctions.isEmpty()) {
return new LineMarkerInfo<JetFunction>( return new LineMarkerInfo<JetFunction>(
......
...@@ -23,33 +23,26 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme ...@@ -23,33 +23,26 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
private TypeConstructor typeConstructor; private TypeConstructor typeConstructor;
private final WritableScope classHeaderScope; private final WritableScope scopeForMemberResolution;
private final WritableScope writableMemberScope; private final WritableScope scopeForMemberLookup;
private JetScope unsubstitutedMemberScope;
public MutableClassDescriptor(@NotNull BindingTrace trace, @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope outerScope) { public MutableClassDescriptor(@NotNull BindingTrace trace, @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope outerScope) {
super(containingDeclaration); super(containingDeclaration);
this.classHeaderScope = new WritableScopeImpl(outerScope, this, trace.getErrorHandler(), null); this.scopeForMemberResolution = new WritableScopeImpl(outerScope, this, trace.getErrorHandler(), null);
this.writableMemberScope = new WritableScopeImpl(classHeaderScope, this, trace.getErrorHandler(), new DeclarationDescriptorVisitor<Void, WritableScope>() { this.scopeForMemberLookup = new WritableScopeImpl(scopeForMemberResolution, this, trace.getErrorHandler(), null);
@Override // this.scopeForMemberLookup = new WritableScopeImpl(scopeForMemberResolution, this, trace.getErrorHandler(), new DeclarationDescriptorVisitor<Void, WritableScope>() {
public Void visitPropertyDescriptor(PropertyDescriptor descriptor, WritableScope data) { // @Override
properties.add(descriptor); // public Void visitPropertyDescriptor(PropertyDescriptor descriptor, WritableScope data) {
return null; // properties.add(descriptor);
} // return null;
// }
@Override //
public Void visitFunctionDescriptor(FunctionDescriptor descriptor, WritableScope data) { // @Override
functions.add(descriptor); // public Void visitFunctionDescriptor(FunctionDescriptor descriptor, WritableScope data) {
return null; // functions.add(descriptor);
} // return null;
}); // }
this.unsubstitutedMemberScope = this.writableMemberScope; // });
}
public MutableClassDescriptor(@NotNull DeclarationDescriptor containingDeclaration) {
super(containingDeclaration);
this.classHeaderScope = null;
this.writableMemberScope = null;
} }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
...@@ -74,6 +67,8 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme ...@@ -74,6 +67,8 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
@Override @Override
public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) { public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) {
properties.add(propertyDescriptor); properties.add(propertyDescriptor);
scopeForMemberLookup.addVariableDescriptor(propertyDescriptor);
scopeForMemberResolution.addVariableDescriptor(propertyDescriptor);
} }
@NotNull @NotNull
...@@ -84,6 +79,8 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme ...@@ -84,6 +79,8 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
@Override @Override
public void addFunctionDescriptor(@NotNull FunctionDescriptor functionDescriptor) { public void addFunctionDescriptor(@NotNull FunctionDescriptor functionDescriptor) {
functions.add(functionDescriptor); functions.add(functionDescriptor);
scopeForMemberLookup.addFunctionDescriptor(functionDescriptor);
scopeForMemberResolution.addFunctionDescriptor(functionDescriptor);
} }
@NotNull @NotNull
...@@ -104,15 +101,12 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme ...@@ -104,15 +101,12 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
@Override @Override
public void addClassifierDescriptor(@NotNull MutableClassDescriptor classDescriptor) { public void addClassifierDescriptor(@NotNull MutableClassDescriptor classDescriptor) {
classes.add(classDescriptor); classes.add(classDescriptor);
scopeForMemberLookup.addClassifierDescriptor(classDescriptor);
scopeForMemberResolution.addClassifierDescriptor(classDescriptor);
} }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public void setUnsubstitutedMemberScope(@NotNull JetScope unsubstitutedMemberScope) {
assert writableMemberScope == null;
this.unsubstitutedMemberScope = unsubstitutedMemberScope;
}
@NotNull @NotNull
@Override @Override
public TypeConstructor getTypeConstructor() { public TypeConstructor getTypeConstructor() {
...@@ -128,18 +122,17 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme ...@@ -128,18 +122,17 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
@Override @Override
public JetScope getMemberScope(List<TypeProjection> typeArguments) { public JetScope getMemberScope(List<TypeProjection> typeArguments) {
assert typeArguments.size() == typeConstructor.getParameters().size(); assert typeArguments.size() == typeConstructor.getParameters().size();
assert unsubstitutedMemberScope != null; if (typeArguments.isEmpty()) return scopeForMemberLookup;
if (typeArguments.isEmpty()) return unsubstitutedMemberScope;
List<TypeParameterDescriptor> typeParameters = getTypeConstructor().getParameters(); List<TypeParameterDescriptor> typeParameters = getTypeConstructor().getParameters();
Map<TypeConstructor, TypeProjection> substitutionContext = TypeUtils.buildSubstitutionContext(typeParameters, typeArguments); Map<TypeConstructor, TypeProjection> substitutionContext = TypeUtils.buildSubstitutionContext(typeParameters, typeArguments);
return new SubstitutingScope(unsubstitutedMemberScope, TypeSubstitutor.create(substitutionContext)); return new SubstitutingScope(scopeForMemberLookup, TypeSubstitutor.create(substitutionContext));
} }
@NotNull @NotNull
@Override @Override
public JetType getDefaultType() { public JetType getDefaultType() {
return TypeUtils.makeUnsubstitutedType(this, unsubstitutedMemberScope); return TypeUtils.makeUnsubstitutedType(this, scopeForMemberLookup);
} }
@NotNull @NotNull
...@@ -156,13 +149,13 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme ...@@ -156,13 +149,13 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
} }
@NotNull @NotNull
public WritableScope getWritableUnsubstitutedMemberScope() { public WritableScope getScopeForMemberLookup() {
return writableMemberScope; return scopeForMemberLookup;
} }
@NotNull @NotNull
public WritableScope getClassHeaderScope() { public WritableScope getScopeForMemberResolution() {
return classHeaderScope; return scopeForMemberResolution;
} }
@NotNull @NotNull
......
package org.jetbrains.jet.lang.resolve; package org.jetbrains.jet.lang.resolve;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Key;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
...@@ -29,16 +30,29 @@ import java.util.Collections; ...@@ -29,16 +30,29 @@ import java.util.Collections;
public class AnalyzingUtils { public class AnalyzingUtils {
private final static Key<CachedValue<BindingContext>> BINDING_CONTEXT = Key.create("BINDING_CONTEXT"); private final static Key<CachedValue<BindingContext>> BINDING_CONTEXT = Key.create("BINDING_CONTEXT");
synchronized // TODO
public static BindingContext analyzeFileWithCache(@NotNull final JetFile file) { public static BindingContext analyzeFileWithCache(@NotNull final JetFile file) {
// TODO : Synchronization? // TODO : Synchronization?
CachedValue<BindingContext> bindingContextCachedValue = file.getUserData(BINDING_CONTEXT); CachedValue<BindingContext> bindingContextCachedValue = file.getUserData(BINDING_CONTEXT);
if (bindingContextCachedValue == null) { if (bindingContextCachedValue == null) {
bindingContextCachedValue = CachedValuesManager.getManager(file.getProject()).createCachedValue(new CachedValueProvider<BindingContext>() { bindingContextCachedValue = CachedValuesManager.getManager(file.getProject()).createCachedValue(new CachedValueProvider<BindingContext>() {
@Override @Override
synchronized // TODO : make it more granular
public Result<BindingContext> compute() { public Result<BindingContext> compute() {
JetNamespace rootNamespace = file.getRootNamespace(); try {
BindingContext bindingContext = analyzeNamespace(rootNamespace, JetControlFlowDataTraceFactory.EMPTY); JetNamespace rootNamespace = file.getRootNamespace();
return new Result<BindingContext>(bindingContext, PsiModificationTracker.MODIFICATION_COUNT); BindingContext bindingContext = analyzeNamespace(rootNamespace, JetControlFlowDataTraceFactory.EMPTY);
return new Result<BindingContext>(bindingContext, PsiModificationTracker.MODIFICATION_COUNT);
}
catch (ProcessCanceledException e) {
throw e;
}
catch (Throwable e) {
e.printStackTrace();
BindingTraceContext bindingTraceContext = new BindingTraceContext();
bindingTraceContext.getErrorHandler().genericError(file.getNode(), e.getClass().getSimpleName() + ": " + e.getMessage());
return new Result<BindingContext>(bindingTraceContext, PsiModificationTracker.MODIFICATION_COUNT);
}
} }
}, false); }, false);
file.putUserData(BINDING_CONTEXT, bindingContextCachedValue); file.putUserData(BINDING_CONTEXT, bindingContextCachedValue);
...@@ -50,7 +64,7 @@ public class AnalyzingUtils { ...@@ -50,7 +64,7 @@ public class AnalyzingUtils {
Project project = namespace.getProject(); Project project = namespace.getProject();
BindingTraceContext bindingTraceContext = new BindingTraceContext(); BindingTraceContext bindingTraceContext = new BindingTraceContext();
JetSemanticServices semanticServices = JetSemanticServices.createSemanticServices(project); JetSemanticServices semanticServices = JetSemanticServices.createSemanticServices(project, flowDataTraceFactory);
JavaSemanticServices javaSemanticServices = new JavaSemanticServices(project, semanticServices, bindingTraceContext); JavaSemanticServices javaSemanticServices = new JavaSemanticServices(project, semanticServices, bindingTraceContext);
JetScope libraryScope = semanticServices.getStandardLibrary().getLibraryScope(); JetScope libraryScope = semanticServices.getStandardLibrary().getLibraryScope();
...@@ -61,7 +75,7 @@ public class AnalyzingUtils { ...@@ -61,7 +75,7 @@ public class AnalyzingUtils {
scope.importScope(new JavaPackageScope("", null, javaSemanticServices)); scope.importScope(new JavaPackageScope("", null, javaSemanticServices));
scope.importScope(new JavaPackageScope("java.lang", null, javaSemanticServices)); scope.importScope(new JavaPackageScope("java.lang", null, javaSemanticServices));
TopDownAnalyzer topDownAnalyzer = new TopDownAnalyzer(semanticServices, bindingTraceContext, flowDataTraceFactory); TopDownAnalyzer topDownAnalyzer = new TopDownAnalyzer(semanticServices, bindingTraceContext);
// topDownAnalyzer.process(scope, Collections.<JetDeclaration>singletonList(namespace)); // topDownAnalyzer.process(scope, Collections.<JetDeclaration>singletonList(namespace));
// if (false) // if (false)
topDownAnalyzer.process(scope, new NamespaceLike.Adapter(owner) { topDownAnalyzer.process(scope, new NamespaceLike.Adapter(owner) {
......
...@@ -5,16 +5,15 @@ import com.intellij.lang.ASTNode; ...@@ -5,16 +5,15 @@ import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.cfg.JetControlFlowProcessor;
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider; import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
import org.jetbrains.jet.lang.cfg.pseudocode.*;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
import java.util.ArrayList; import java.util.*;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/** /**
* @author abreslav * @author abreslav
...@@ -27,12 +26,14 @@ public class ClassDescriptorResolver { ...@@ -27,12 +26,14 @@ public class ClassDescriptorResolver {
private final TypeResolver typeResolver; private final TypeResolver typeResolver;
private final TypeResolver typeResolverNotCheckingBounds; private final TypeResolver typeResolverNotCheckingBounds;
private final BindingTrace trace; private final BindingTrace trace;
private final JetControlFlowDataTraceFactory flowDataTraceFactory;
public ClassDescriptorResolver(JetSemanticServices semanticServices, BindingTrace trace) { public ClassDescriptorResolver(JetSemanticServices semanticServices, BindingTrace trace, JetControlFlowDataTraceFactory flowDataTraceFactory) {
this.semanticServices = semanticServices; this.semanticServices = semanticServices;
this.typeResolver = new TypeResolver(semanticServices, trace, true); this.typeResolver = new TypeResolver(semanticServices, trace, true);
this.typeResolverNotCheckingBounds = new TypeResolver(semanticServices, trace, false); this.typeResolverNotCheckingBounds = new TypeResolver(semanticServices, trace, false);
this.trace = trace; this.trace = trace;
this.flowDataTraceFactory = flowDataTraceFactory;
} }
@Nullable @Nullable
...@@ -78,9 +79,9 @@ public class ClassDescriptorResolver { ...@@ -78,9 +79,9 @@ public class ClassDescriptorResolver {
public void resolveMutableClassDescriptor(@NotNull JetClass classElement, @NotNull MutableClassDescriptor descriptor) { public void resolveMutableClassDescriptor(@NotNull JetClass classElement, @NotNull MutableClassDescriptor descriptor) {
descriptor.setName(JetPsiUtil.safeName(classElement.getName())); descriptor.setName(JetPsiUtil.safeName(classElement.getName()));
descriptor.getClassHeaderScope().addLabeledDeclaration(descriptor); descriptor.getScopeForMemberResolution().addLabeledDeclaration(descriptor);
WritableScope parameterScope = descriptor.getClassHeaderScope(); WritableScope scopeForMemberResolution = descriptor.getScopeForMemberResolution();
// TODO : Where-clause // TODO : Where-clause
List<TypeParameterDescriptor> typeParameters = Lists.newArrayList(); List<TypeParameterDescriptor> typeParameters = Lists.newArrayList();
...@@ -91,7 +92,7 @@ public class ClassDescriptorResolver { ...@@ -91,7 +92,7 @@ public class ClassDescriptorResolver {
typeParameter.getVariance(), typeParameter.getVariance(),
JetPsiUtil.safeName(typeParameter.getName()) JetPsiUtil.safeName(typeParameter.getName())
); );
parameterScope.addTypeParameterDescriptor(typeParameterDescriptor); scopeForMemberResolution.addTypeParameterDescriptor(typeParameterDescriptor);
trace.recordDeclarationResolution(typeParameter, typeParameterDescriptor); trace.recordDeclarationResolution(typeParameter, typeParameterDescriptor);
typeParameters.add(typeParameterDescriptor); typeParameters.add(typeParameterDescriptor);
} }
...@@ -109,7 +110,7 @@ public class ClassDescriptorResolver { ...@@ -109,7 +110,7 @@ public class ClassDescriptorResolver {
typeConstructor typeConstructor
); );
descriptor.getClassHeaderScope().setThisType(descriptor.getDefaultType()); descriptor.getScopeForMemberResolution().setThisType(descriptor.getDefaultType());
trace.recordDeclarationResolution(classElement, descriptor); trace.recordDeclarationResolution(classElement, descriptor);
} }
...@@ -122,7 +123,7 @@ public class ClassDescriptorResolver { ...@@ -122,7 +123,7 @@ public class ClassDescriptorResolver {
TypeParameterDescriptor typeParameterDescriptor = parameters.get(i); TypeParameterDescriptor typeParameterDescriptor = parameters.get(i);
JetTypeReference extendsBound = jetTypeParameter.getExtendsBound(); JetTypeReference extendsBound = jetTypeParameter.getExtendsBound();
if (extendsBound != null) { if (extendsBound != null) {
typeParameterDescriptor.addUpperBound(typeResolverNotCheckingBounds.resolveType(classDescriptor.getClassHeaderScope(), extendsBound)); typeParameterDescriptor.addUpperBound(typeResolverNotCheckingBounds.resolveType(classDescriptor.getScopeForMemberResolution(), extendsBound));
} }
else { else {
typeParameterDescriptor.addUpperBound(JetStandardClasses.getDefaultBound()); typeParameterDescriptor.addUpperBound(JetStandardClasses.getDefaultBound());
...@@ -136,15 +137,21 @@ public class ClassDescriptorResolver { ...@@ -136,15 +137,21 @@ public class ClassDescriptorResolver {
// TODO : assuming that the hierarchy is acyclic // TODO : assuming that the hierarchy is acyclic
Collection<? extends JetType> superclasses = delegationSpecifiers.isEmpty() Collection<? extends JetType> superclasses = delegationSpecifiers.isEmpty()
? Collections.singleton(JetStandardClasses.getAnyType()) ? Collections.singleton(JetStandardClasses.getAnyType())
: resolveDelegationSpecifiers(descriptor.getClassHeaderScope(), delegationSpecifiers, typeResolverNotCheckingBounds); : resolveDelegationSpecifiers(descriptor.getScopeForMemberResolution(), delegationSpecifiers, typeResolverNotCheckingBounds);
((TypeConstructorImpl) descriptor.getTypeConstructor()).getSupertypes().addAll(superclasses); ((TypeConstructorImpl) descriptor.getTypeConstructor()).getSupertypes().addAll(superclasses);
// TODO : remove the importing
for (JetType superclass : superclasses) {
descriptor.getScopeForMemberResolution().importScope(superclass.getMemberScope());
}
} }
public void resolveMutableClassDescriptor(@NotNull JetScope scope, @NotNull JetClass classElement, @NotNull MutableClassDescriptor descriptor) { public void resolveMutableClassDescriptor(@NotNull JetScope scope, @NotNull JetClass classElement, @NotNull MutableClassDescriptor descriptor) {
descriptor.setName(JetPsiUtil.safeName(classElement.getName())); descriptor.setName(JetPsiUtil.safeName(classElement.getName()));
descriptor.getClassHeaderScope().addLabeledDeclaration(descriptor); descriptor.getScopeForMemberResolution().addLabeledDeclaration(descriptor);
WritableScope parameterScope = descriptor.getClassHeaderScope(); WritableScope parameterScope = descriptor.getScopeForMemberResolution();
// This call has side-effects on the parameterScope (fills it in) // This call has side-effects on the parameterScope (fills it in)
List<TypeParameterDescriptor> typeParameters List<TypeParameterDescriptor> typeParameters
...@@ -179,7 +186,7 @@ public class ClassDescriptorResolver { ...@@ -179,7 +186,7 @@ public class ClassDescriptorResolver {
parameterScope.importScope(supertype.getMemberScope()); parameterScope.importScope(supertype.getMemberScope());
} }
descriptor.getClassHeaderScope().setThisType(descriptor.getDefaultType()); descriptor.getScopeForMemberResolution().setThisType(descriptor.getDefaultType());
trace.recordDeclarationResolution(classElement, descriptor); trace.recordDeclarationResolution(classElement, descriptor);
} }
...@@ -228,8 +235,8 @@ public class ClassDescriptorResolver { ...@@ -228,8 +235,8 @@ public class ClassDescriptorResolver {
} }
@NotNull @NotNull
public FunctionDescriptorImpl resolveFunctionDescriptor(DeclarationDescriptor containingDescriptor, JetScope scope, JetFunction function) { public FunctionDescriptorImpl resolveFunctionDescriptor(DeclarationDescriptor containingDescriptor, final JetScope scope, final JetFunction function) {
FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl( final FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl(
containingDescriptor, containingDescriptor,
AnnotationResolver.INSTANCE.resolveAnnotations(function.getModifierList()), AnnotationResolver.INSTANCE.resolveAnnotations(function.getModifierList()),
JetPsiUtil.safeName(function.getName()) JetPsiUtil.safeName(function.getName())
...@@ -246,6 +253,18 @@ public class ClassDescriptorResolver { ...@@ -246,6 +253,18 @@ public class ClassDescriptorResolver {
if (returnTypeRef != null) { if (returnTypeRef != null) {
returnType = typeResolver.resolveType(innerScope, returnTypeRef); returnType = typeResolver.resolveType(innerScope, returnTypeRef);
} }
else {
final JetExpression bodyExpression = function.getBodyExpression();
if (bodyExpression != null) {
returnType = new DeferredType(new LazyValue<JetType>() {
@Override
protected JetType compute() {
JetFlowInformationProvider flowInformationProvider = computeFlowData(function.asElement(), bodyExpression);
return semanticServices.getTypeInferrer(trace, flowInformationProvider).getFunctionReturnType(scope, function, functionDescriptor);
}
});
}
}
functionDescriptor.initialize( functionDescriptor.initialize(
typeParameterDescriptors, typeParameterDescriptors,
...@@ -625,4 +644,158 @@ public class ClassDescriptorResolver { ...@@ -625,4 +644,158 @@ public class ClassDescriptorResolver {
} }
} }
} }
public JetFlowInformationProvider computeFlowData(@NotNull JetElement declaration, @NotNull JetExpression bodyExpression) {
final JetPseudocodeTrace pseudocodeTrace = flowDataTraceFactory.createTrace(declaration);
final Map<JetElement, Pseudocode> pseudocodeMap = new HashMap<JetElement, Pseudocode>();
final Map<JetElement, Instruction> representativeInstructions = new HashMap<JetElement, Instruction>();
JetPseudocodeTrace wrappedTrace = new JetPseudocodeTrace() {
@Override
public void recordControlFlowData(@NotNull JetElement element, @NotNull Pseudocode pseudocode) {
pseudocodeTrace.recordControlFlowData(element, pseudocode);
pseudocodeMap.put(element, pseudocode);
}
@Override
public void recordRepresentativeInstruction(@NotNull JetElement element, @NotNull Instruction instruction) {
Instruction oldValue = representativeInstructions.put(element, instruction);
// assert oldValue == null : element.getText();
}
@Override
public void close() {
pseudocodeTrace.close();
for (Pseudocode pseudocode : pseudocodeMap.values()) {
pseudocode.postProcess();
}
}
};
JetControlFlowInstructionsGenerator instructionsGenerator = new JetControlFlowInstructionsGenerator(wrappedTrace);
new JetControlFlowProcessor(semanticServices, trace, instructionsGenerator).generate(declaration, bodyExpression);
wrappedTrace.close();
return new JetFlowInformationProvider() {
@Override
public void collectReturnedInformation(@NotNull JetElement subroutine, @NotNull Collection<JetExpression> returnedExpressions, @NotNull Collection<JetElement> elementsReturningUnit) {
Pseudocode pseudocode = pseudocodeMap.get(subroutine);
assert pseudocode != null;
SubroutineExitInstruction exitInstruction = pseudocode.getExitInstruction();
processPreviousInstructions(exitInstruction, new HashSet<Instruction>(), returnedExpressions, elementsReturningUnit);
}
@Override
public void collectUnreachableExpressions(@NotNull JetElement subroutine, @NotNull Collection<JetElement> unreachableElements) {
Pseudocode pseudocode = pseudocodeMap.get(subroutine);
assert pseudocode != null;
SubroutineEnterInstruction enterInstruction = pseudocode.getEnterInstruction();
Set<Instruction> visited = new HashSet<Instruction>();
collectReachable(enterInstruction, visited);
for (Instruction instruction : pseudocode.getInstructions()) {
if (!visited.contains(instruction) &&
instruction instanceof JetElementInstruction &&
// TODO : do {return} while (1 > a)
!(instruction instanceof ReadUnitValueInstruction)) {
unreachableElements.add(((JetElementInstruction) instruction).getElement());
}
}
}
@Override
public void collectDominatedExpressions(@NotNull JetExpression dominator, @NotNull Collection<JetElement> dominated) {
Instruction dominatorInstruction = representativeInstructions.get(dominator);
if (dominatorInstruction == null) {
return;
}
SubroutineEnterInstruction enterInstruction = dominatorInstruction.getOwner().getEnterInstruction();
Set<Instruction> reachable = new HashSet<Instruction>();
collectReachable(enterInstruction, reachable);
Set<Instruction> reachableWithDominatorProhibited = new HashSet<Instruction>();
reachableWithDominatorProhibited.add(dominatorInstruction);
collectReachable(enterInstruction, reachableWithDominatorProhibited);
for (Instruction instruction : reachable) {
if (instruction instanceof JetElementInstruction
&& reachable.contains(instruction)
&& !reachableWithDominatorProhibited.contains(instruction)) {
JetElementInstruction elementInstruction = (JetElementInstruction) instruction;
dominated.add(elementInstruction.getElement());
}
}
}
};
}
private void collectReachable(Instruction current, Set<Instruction> visited) {
if (!visited.add(current)) return;
for (Instruction nextInstruction : current.getNextInstructions()) {
collectReachable(nextInstruction, visited);
}
}
private void processPreviousInstructions(Instruction previousFor, final Set<Instruction> visited, final Collection<JetExpression> returnedExpressions, final Collection<JetElement> elementsReturningUnit) {
if (!visited.add(previousFor)) return;
Collection<Instruction> previousInstructions = previousFor.getPreviousInstructions();
InstructionVisitor visitor = new InstructionVisitor() {
@Override
public void visitReadValue(ReadValueInstruction instruction) {
returnedExpressions.add((JetExpression) instruction.getElement());
}
@Override
public void visitReturnValue(ReturnValueInstruction instruction) {
processPreviousInstructions(instruction, visited, returnedExpressions, elementsReturningUnit);
}
@Override
public void visitReturnNoValue(ReturnNoValueInstruction instruction) {
elementsReturningUnit.add(instruction.getElement());
}
@Override
public void visitSubroutineEnter(SubroutineEnterInstruction instruction) {
elementsReturningUnit.add(instruction.getSubroutine());
}
@Override
public void visitUnsupportedElementInstruction(UnsupportedElementInstruction instruction) {
trace.getErrorHandler().genericError(instruction.getElement().getNode(), "Unsupported by control-flow builder " + instruction.getElement());
}
@Override
public void visitWriteValue(WriteValueInstruction writeValueInstruction) {
elementsReturningUnit.add(writeValueInstruction.getElement());
}
@Override
public void visitJump(AbstractJumpInstruction instruction) {
processPreviousInstructions(instruction, visited, returnedExpressions, elementsReturningUnit);
}
@Override
public void visitReadUnitValue(ReadUnitValueInstruction instruction) {
returnedExpressions.add((JetExpression) instruction.getElement());
}
@Override
public void visitInstruction(Instruction instruction) {
if (instruction instanceof JetElementInstructionImpl) {
JetElementInstructionImpl elementInstruction = (JetElementInstructionImpl) instruction;
trace.getErrorHandler().genericError(elementInstruction.getElement().getNode(), "Unsupported by control-flow builder " + elementInstruction.getElement());
}
else {
throw new UnsupportedOperationException(instruction.toString());
}
}
};
for (Instruction previousInstruction : previousInstructions) {
previousInstruction.accept(visitor);
}
}
} }
package org.jetbrains.jet.lang.resolve.java;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.JetScope;
import org.jetbrains.jet.lang.resolve.SubstitutingScope;
import org.jetbrains.jet.lang.types.*;
import java.util.List;
import java.util.Map;
/**
* @author abreslav
*/
public class JavaClassDescriptor extends MutableDeclarationDescriptor implements ClassDescriptor {
private TypeConstructor typeConstructor;
private JavaClassMembersScope unsubstitutedMemberScope;
private final WritableFunctionGroup constructors = new WritableFunctionGroup("<init>");
public JavaClassDescriptor(DeclarationDescriptor containingDeclaration) {
super(containingDeclaration);
}
public void setTypeConstructor(TypeConstructor typeConstructor) {
this.typeConstructor = typeConstructor;
}
public void setUnsubstitutedMemberScope(JavaClassMembersScope memberScope) {
this.unsubstitutedMemberScope = memberScope;
}
public void addConstructor(ConstructorDescriptor constructorDescriptor) {
this.constructors.addFunction(constructorDescriptor);
}
private TypeSubstitutor createTypeSubstitutor(List<TypeProjection> typeArguments) {
List<TypeParameterDescriptor> parameters = getTypeConstructor().getParameters();
Map<TypeConstructor, TypeProjection> context = TypeUtils.buildSubstitutionContext(parameters, typeArguments);
return TypeSubstitutor.create(context);
}
@NotNull
@Override
public JetScope getMemberScope(List<TypeProjection> typeArguments) {
assert typeArguments.size() == typeConstructor.getParameters().size();
if (typeArguments.isEmpty()) return unsubstitutedMemberScope;
TypeSubstitutor substitutor = createTypeSubstitutor(typeArguments);
return new SubstitutingScope(unsubstitutedMemberScope, substitutor);
}
@NotNull
@Override
public FunctionGroup getConstructors(List<TypeProjection> typeArguments) {
assert typeArguments.size() == typeConstructor.getParameters().size();
if (typeArguments.isEmpty()) return constructors;
return new LazySubstitutingFunctionGroup(createTypeSubstitutor(typeArguments), constructors);
}
@Override
public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
return null;
}
@Override
public boolean hasConstructors() {
return constructors.isEmpty();
}
@NotNull
@Override
public TypeConstructor getTypeConstructor() {
return typeConstructor;
}
@NotNull
@Override
public JetType getDefaultType() {
return TypeUtils.makeUnsubstitutedType(this, unsubstitutedMemberScope);
}
@NotNull
@Override
public ClassDescriptor substitute(TypeSubstitutor substitutor) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
return visitor.visitClassDescriptor(this, data);
}
}
...@@ -73,7 +73,7 @@ public class JavaDescriptorResolver { ...@@ -73,7 +73,7 @@ public class JavaDescriptorResolver {
String name = psiClass.getName(); String name = psiClass.getName();
PsiModifierList modifierList = psiClass.getModifierList(); PsiModifierList modifierList = psiClass.getModifierList();
MutableClassDescriptor classDescriptor = new MutableClassDescriptor( JavaClassDescriptor classDescriptor = new JavaClassDescriptor(
JAVA_ROOT JAVA_ROOT
); );
classDescriptor.setName(name); classDescriptor.setName(name);
......
...@@ -81,7 +81,7 @@ public class ExpectedResolveData { ...@@ -81,7 +81,7 @@ public class ExpectedResolveData {
text = document.getText(); text = document.getText();
} }
// System.out.println("text = " + text); System.out.println("text = " + text);
} }
public void checkResult(JetFile file) { public void checkResult(JetFile file) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册