Merge branch 'master' of ssh://git.labs.intellij.net/jet
This commit is contained in:
@@ -17,6 +17,9 @@ import org.jetbrains.jet.lang.types.JetStandardLibrary;
|
|||||||
import org.objectweb.asm.ClassVisitor;
|
import org.objectweb.asm.ClassVisitor;
|
||||||
import org.objectweb.asm.commons.Method;
|
import org.objectweb.asm.commons.Method;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class GenerationState {
|
public class GenerationState {
|
||||||
private final ClassFileFactory factory;
|
private final ClassFileFactory factory;
|
||||||
private final Project project;
|
private final Project project;
|
||||||
@@ -85,14 +88,31 @@ public class GenerationState {
|
|||||||
|
|
||||||
public void compile(JetFile psiFile) {
|
public void compile(JetFile psiFile) {
|
||||||
final JetNamespace namespace = psiFile.getRootNamespace();
|
final JetNamespace namespace = psiFile.getRootNamespace();
|
||||||
NamespaceCodegen codegen = forNamespace(namespace);
|
|
||||||
final BindingContext bindingContext = AnalyzingUtils.getInstance(JavaDefaultImports.JAVA_DEFAULT_IMPORTS).analyzeNamespace(namespace, JetControlFlowDataTraceFactory.EMPTY);
|
final BindingContext bindingContext = AnalyzingUtils.getInstance(JavaDefaultImports.JAVA_DEFAULT_IMPORTS).analyzeNamespace(namespace, JetControlFlowDataTraceFactory.EMPTY);
|
||||||
bindingContexts.push(bindingContext);
|
AnalyzingUtils.throwExceptionOnErrors(bindingContext);
|
||||||
typeMapper = new JetTypeMapper(standardLibrary, bindingContext);
|
compileCorrectNamespaces(bindingContext, Collections.singletonList(namespace));
|
||||||
try {
|
// NamespaceCodegen codegen = forNamespace(namespace);
|
||||||
AnalyzingUtils.throwExceptionOnErrors(bindingContext);
|
// bindingContexts.push(bindingContext);
|
||||||
|
// typeMapper = new JetTypeMapper(standardLibrary, bindingContext);
|
||||||
|
// try {
|
||||||
|
// AnalyzingUtils.throwExceptionOnErrors(bindingContext);
|
||||||
|
//
|
||||||
|
// codegen.generate(namespace);
|
||||||
|
// }
|
||||||
|
// finally {
|
||||||
|
// bindingContexts.pop();
|
||||||
|
// typeMapper = null;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
codegen.generate(namespace);
|
public void compileCorrectNamespaces(BindingContext bindingContext, List<JetNamespace> namespaces) {
|
||||||
|
typeMapper = new JetTypeMapper(standardLibrary, bindingContext);
|
||||||
|
bindingContexts.push(bindingContext);
|
||||||
|
try {
|
||||||
|
for (JetNamespace namespace : namespaces) {
|
||||||
|
NamespaceCodegen codegen = forNamespace(namespace);
|
||||||
|
codegen.generate(namespace);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
bindingContexts.pop();
|
bindingContexts.pop();
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public class JetObjectDeclaration extends JetNamedDeclaration implements JetClas
|
|||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
JetObjectDeclarationName nameAsDeclaration = getNameAsDeclaration();
|
JetObjectDeclarationName nameAsDeclaration = getNameAsDeclaration();
|
||||||
return nameAsDeclaration == null ? "ClassObj" : nameAsDeclaration.getName();
|
return nameAsDeclaration == null ? null : nameAsDeclaration.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
|||||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
|
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
//import org.jetbrains.jet.lang.resolve.java.JavaPackageScope;
|
//import org.jetbrains.jet.lang.resolve.java.JavaPackageScope;
|
||||||
//import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices;
|
//import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices;
|
||||||
@@ -66,7 +67,12 @@ public class AnalyzingUtils {
|
|||||||
|
|
||||||
public BindingContext analyzeNamespace(@NotNull JetNamespace namespace, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) {
|
public BindingContext analyzeNamespace(@NotNull JetNamespace namespace, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) {
|
||||||
Project project = namespace.getProject();
|
Project project = namespace.getProject();
|
||||||
|
List<JetDeclaration> declarations = Collections.<JetDeclaration>singletonList(namespace);
|
||||||
|
|
||||||
|
return analyzeNamespaces(project, declarations, flowDataTraceFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BindingContext analyzeNamespaces(@NotNull Project project, @NotNull List<? extends JetDeclaration> declarations, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) {
|
||||||
BindingTraceContext bindingTraceContext = new BindingTraceContext();
|
BindingTraceContext bindingTraceContext = new BindingTraceContext();
|
||||||
JetSemanticServices semanticServices = JetSemanticServices.createSemanticServices(project, flowDataTraceFactory);
|
JetSemanticServices semanticServices = JetSemanticServices.createSemanticServices(project, flowDataTraceFactory);
|
||||||
|
|
||||||
@@ -105,7 +111,7 @@ public class AnalyzingUtils {
|
|||||||
public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) {
|
public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) {
|
||||||
throw new IllegalStateException("Must be guaranteed not to happen by the parser");
|
throw new IllegalStateException("Must be guaranteed not to happen by the parser");
|
||||||
}
|
}
|
||||||
}, Collections.<JetDeclaration>singletonList(namespace));
|
}, declarations);
|
||||||
return bindingTraceContext.getBindingContext();
|
return bindingTraceContext.getBindingContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ import org.jetbrains.jet.lang.psi.*;
|
|||||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.types.DeferredType;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
import org.jetbrains.jet.util.CommonSuppliers;
|
||||||
import org.jetbrains.jet.util.slicedmap.*;
|
import org.jetbrains.jet.util.slicedmap.*;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -42,6 +44,10 @@ public interface BindingContext {
|
|||||||
WritableSlice<JetElement, Boolean> STATEMENT = Slices.createRemovableSetSlice("STATEMENT");
|
WritableSlice<JetElement, Boolean> STATEMENT = Slices.createRemovableSetSlice("STATEMENT");
|
||||||
WritableSlice<CallableMemberDescriptor, Boolean> DELEGATED = Slices.createRemovableSetSlice("DELEGATED");
|
WritableSlice<CallableMemberDescriptor, Boolean> DELEGATED = Slices.createRemovableSetSlice("DELEGATED");
|
||||||
|
|
||||||
|
enum DeferredTypeKey {DEFERRED_TYPE_KEY}
|
||||||
|
WritableSlice<DeferredTypeKey, Collection<DeferredType>> DEFERRED_TYPES = Slices.createSimpleSlice("DEFERRED_TYPES");
|
||||||
|
WritableSlice<DeferredTypeKey, DeferredType> DEFERRED_TYPE = new CollectionSliceWrapper<DeferredTypeKey, DeferredType>(DEFERRED_TYPES, CommonSuppliers.<DeferredType>getArrayListSupplier());
|
||||||
|
|
||||||
WritableSlice<PropertyDescriptor, Boolean> BACKING_FIELD_REQUIRED = new Slices.SetSlice<PropertyDescriptor>("BACKING_FIELD_REQUIRED", RewritePolicy.DO_NOTHING) {
|
WritableSlice<PropertyDescriptor, Boolean> BACKING_FIELD_REQUIRED = new Slices.SetSlice<PropertyDescriptor>("BACKING_FIELD_REQUIRED", RewritePolicy.DO_NOTHING) {
|
||||||
@Override
|
@Override
|
||||||
public Boolean computeValue(SlicedMap map, PropertyDescriptor propertyDescriptor, Boolean backingFieldRequired, boolean valueNotFound) {
|
public Boolean computeValue(SlicedMap map, PropertyDescriptor propertyDescriptor, Boolean backingFieldRequired, boolean valueNotFound) {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.google.common.collect.Maps;
|
|||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.intellij.lang.ASTNode;
|
import com.intellij.lang.ASTNode;
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
|
import com.intellij.util.containers.Queue;
|
||||||
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.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
@@ -16,28 +17,28 @@ import org.jetbrains.jet.lang.types.*;
|
|||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
import org.jetbrains.jet.util.slicedmap.WritableSlice;
|
import org.jetbrains.jet.util.slicedmap.WritableSlice;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.BindingContext.DEFERRED_TYPE;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.BindingContext.DEFERRED_TYPES;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.BindingContext.DeferredTypeKey.DEFERRED_TYPE_KEY;
|
||||||
import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE;
|
import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
public class BodyResolver {
|
public class BodyResolver {
|
||||||
private final TopDownAnalysisContext context;
|
private final TopDownAnalysisContext context;
|
||||||
|
|
||||||
private final BindingTraceAdapter traceForConstructors;
|
private final ObservableBindingTrace traceForConstructors;
|
||||||
private final BindingTraceAdapter traceForMembers;
|
private final ObservableBindingTrace traceForMembers;
|
||||||
|
|
||||||
public BodyResolver(TopDownAnalysisContext context) {
|
public BodyResolver(TopDownAnalysisContext context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
|
||||||
// This allows access to backing fields
|
// This allows access to backing fields
|
||||||
this.traceForConstructors = new BindingTraceAdapter(context.getTrace()).addHandler(BindingContext.REFERENCE_TARGET, new BindingTraceAdapter.RecordHandler<JetReferenceExpression, DeclarationDescriptor>() {
|
this.traceForConstructors = new ObservableBindingTrace(context.getTrace()).addHandler(BindingContext.REFERENCE_TARGET, new ObservableBindingTrace.RecordHandler<JetReferenceExpression, DeclarationDescriptor>() {
|
||||||
@Override
|
@Override
|
||||||
public void handleRecord(WritableSlice<JetReferenceExpression, DeclarationDescriptor> slice, JetReferenceExpression expression, DeclarationDescriptor descriptor) {
|
public void handleRecord(WritableSlice<JetReferenceExpression, DeclarationDescriptor> slice, JetReferenceExpression expression, DeclarationDescriptor descriptor) {
|
||||||
if (expression instanceof JetSimpleNameExpression) {
|
if (expression instanceof JetSimpleNameExpression) {
|
||||||
@@ -52,7 +53,7 @@ public class BodyResolver {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// This tracks access to properties in order to register primary constructor parameters that yield real fields (JET-9)
|
// This tracks access to properties in order to register primary constructor parameters that yield real fields (JET-9)
|
||||||
this.traceForMembers = new BindingTraceAdapter(context.getTrace()).addHandler(BindingContext.REFERENCE_TARGET, new BindingTraceAdapter.RecordHandler<JetReferenceExpression, DeclarationDescriptor>() {
|
this.traceForMembers = new ObservableBindingTrace(context.getTrace()).addHandler(BindingContext.REFERENCE_TARGET, new ObservableBindingTrace.RecordHandler<JetReferenceExpression, DeclarationDescriptor>() {
|
||||||
@Override
|
@Override
|
||||||
public void handleRecord(WritableSlice<JetReferenceExpression, DeclarationDescriptor> slice, JetReferenceExpression expression, DeclarationDescriptor descriptor) {
|
public void handleRecord(WritableSlice<JetReferenceExpression, DeclarationDescriptor> slice, JetReferenceExpression expression, DeclarationDescriptor descriptor) {
|
||||||
if (descriptor instanceof PropertyDescriptor) {
|
if (descriptor instanceof PropertyDescriptor) {
|
||||||
@@ -78,7 +79,34 @@ public class BodyResolver {
|
|||||||
resolveSecondaryConstructorBodies();
|
resolveSecondaryConstructorBodies();
|
||||||
resolveFunctionBodies();
|
resolveFunctionBodies();
|
||||||
|
|
||||||
|
computeDeferredTypes();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void computeDeferredTypes() {
|
||||||
|
Collection<DeferredType> deferredTypes = context.getTrace().get(DEFERRED_TYPES, DEFERRED_TYPE_KEY);
|
||||||
|
if (deferredTypes != null) {
|
||||||
|
final Queue<DeferredType> queue = new Queue<DeferredType>(deferredTypes.size());
|
||||||
|
context.getTrace().addHandler(DEFERRED_TYPE, new ObservableBindingTrace.RecordHandler<BindingContext.DeferredTypeKey, DeferredType>() {
|
||||||
|
@Override
|
||||||
|
public void handleRecord(WritableSlice<BindingContext.DeferredTypeKey, DeferredType> deferredTypeKeyDeferredTypeWritableSlice, BindingContext.DeferredTypeKey key, DeferredType value) {
|
||||||
|
queue.addLast(value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
for (DeferredType deferredType : deferredTypes) {
|
||||||
|
queue.addLast(deferredType);
|
||||||
|
}
|
||||||
|
while (!queue.isEmpty()) {
|
||||||
|
DeferredType deferredType = queue.pullFirst();
|
||||||
|
if (!deferredType.isComputed()) {
|
||||||
|
try {
|
||||||
|
deferredType.getActualType(); // to compute
|
||||||
|
}
|
||||||
|
catch (ReenteringLazyValueComputationException e) {
|
||||||
|
// A problem should be reported while computing the type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -95,8 +123,8 @@ public class BodyResolver {
|
|||||||
private void resolveDelegationSpecifierList(final JetClassOrObject jetClass, final MutableClassDescriptor descriptor) {
|
private void resolveDelegationSpecifierList(final JetClassOrObject jetClass, final MutableClassDescriptor descriptor) {
|
||||||
final ConstructorDescriptor primaryConstructor = descriptor.getUnsubstitutedPrimaryConstructor();
|
final ConstructorDescriptor primaryConstructor = descriptor.getUnsubstitutedPrimaryConstructor();
|
||||||
final JetScope scopeForConstructor = primaryConstructor == null
|
final JetScope scopeForConstructor = primaryConstructor == null
|
||||||
? null
|
? null
|
||||||
: getInnerScopeForConstructor(primaryConstructor, descriptor.getScopeForMemberResolution(), true);
|
: getInnerScopeForConstructor(primaryConstructor, descriptor.getScopeForMemberResolution(), true);
|
||||||
final JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(traceForConstructors, JetFlowInformationProvider.NONE); // TODO : flow
|
final JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(traceForConstructors, JetFlowInformationProvider.NONE); // TODO : flow
|
||||||
|
|
||||||
final Map<JetTypeReference, JetType> supertypes = Maps.newLinkedHashMap();
|
final Map<JetTypeReference, JetType> supertypes = Maps.newLinkedHashMap();
|
||||||
@@ -317,8 +345,8 @@ public class BodyResolver {
|
|||||||
ClassDescriptor classDescriptor = descriptor.getContainingDeclaration();
|
ClassDescriptor classDescriptor = descriptor.getContainingDeclaration();
|
||||||
|
|
||||||
typeInferrerForInitializers.getCallResolver().resolveCall(context.getTrace(),
|
typeInferrerForInitializers.getCallResolver().resolveCall(context.getTrace(),
|
||||||
functionInnerScope,
|
functionInnerScope,
|
||||||
ReceiverDescriptor.NO_RECEIVER, call, NO_EXPECTED_TYPE);
|
ReceiverDescriptor.NO_RECEIVER, call, NO_EXPECTED_TYPE);
|
||||||
// call.getThisReference(),
|
// call.getThisReference(),
|
||||||
// classDescriptor,
|
// classDescriptor,
|
||||||
// classDescriptor.getDefaultType(),
|
// classDescriptor.getDefaultType(),
|
||||||
@@ -436,7 +464,7 @@ public class BodyResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void resolvePropertyAccessors(JetProperty property, PropertyDescriptor propertyDescriptor, JetScope declaringScope) {
|
private void resolvePropertyAccessors(JetProperty property, PropertyDescriptor propertyDescriptor, JetScope declaringScope) {
|
||||||
BindingTraceAdapter fieldAccessTrackingTrace = createFieldTrackingTrace(propertyDescriptor);
|
ObservableBindingTrace fieldAccessTrackingTrace = createFieldTrackingTrace(propertyDescriptor);
|
||||||
|
|
||||||
WritableScope accessorScope = new WritableScopeImpl(getPropertyDeclarationInnerScope(declaringScope, propertyDescriptor), declaringScope.getContainingDeclaration(), new TraceBasedRedeclarationHandler(context.getTrace())).setDebugName("Accessor scope");
|
WritableScope accessorScope = new WritableScopeImpl(getPropertyDeclarationInnerScope(declaringScope, propertyDescriptor), declaringScope.getContainingDeclaration(), new TraceBasedRedeclarationHandler(context.getTrace())).setDebugName("Accessor scope");
|
||||||
accessorScope.addPropertyDescriptorByFieldName("$" + propertyDescriptor.getName(), propertyDescriptor);
|
accessorScope.addPropertyDescriptorByFieldName("$" + propertyDescriptor.getName(), propertyDescriptor);
|
||||||
@@ -454,8 +482,8 @@ public class BodyResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private BindingTraceAdapter createFieldTrackingTrace(final PropertyDescriptor propertyDescriptor) {
|
private ObservableBindingTrace createFieldTrackingTrace(final PropertyDescriptor propertyDescriptor) {
|
||||||
return new BindingTraceAdapter(traceForMembers).addHandler(BindingContext.REFERENCE_TARGET, new BindingTraceAdapter.RecordHandler<JetReferenceExpression, DeclarationDescriptor>() {
|
return new ObservableBindingTrace(traceForMembers).addHandler(BindingContext.REFERENCE_TARGET, new ObservableBindingTrace.RecordHandler<JetReferenceExpression, DeclarationDescriptor>() {
|
||||||
@Override
|
@Override
|
||||||
public void handleRecord(WritableSlice<JetReferenceExpression, DeclarationDescriptor> slice, JetReferenceExpression expression, DeclarationDescriptor descriptor) {
|
public void handleRecord(WritableSlice<JetReferenceExpression, DeclarationDescriptor> slice, JetReferenceExpression expression, DeclarationDescriptor descriptor) {
|
||||||
if (expression instanceof JetSimpleNameExpression) {
|
if (expression instanceof JetSimpleNameExpression) {
|
||||||
@@ -471,8 +499,8 @@ public class BodyResolver {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private BindingTraceAdapter createFieldAssignTrackingTrace() {
|
private ObservableBindingTrace createFieldAssignTrackingTrace() {
|
||||||
return new BindingTraceAdapter(traceForConstructors).addHandler(BindingContext.VARIABLE_ASSIGNMENT, new BindingTraceAdapter.RecordHandler<JetExpression, DeclarationDescriptor>() {
|
return new ObservableBindingTrace(traceForConstructors).addHandler(BindingContext.VARIABLE_ASSIGNMENT, new ObservableBindingTrace.RecordHandler<JetExpression, DeclarationDescriptor>() {
|
||||||
@Override
|
@Override
|
||||||
public void handleRecord(WritableSlice<JetExpression, DeclarationDescriptor> jetExpressionBooleanWritableSlice, JetExpression expression, DeclarationDescriptor descriptor) {
|
public void handleRecord(WritableSlice<JetExpression, DeclarationDescriptor> jetExpressionBooleanWritableSlice, JetExpression expression, DeclarationDescriptor descriptor) {
|
||||||
if (expression instanceof JetSimpleNameExpression) {
|
if (expression instanceof JetSimpleNameExpression) {
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ public class ClassDescriptorResolver {
|
|||||||
else {
|
else {
|
||||||
final JetExpression bodyExpression = function.getBodyExpression();
|
final JetExpression bodyExpression = function.getBodyExpression();
|
||||||
if (bodyExpression != null) {
|
if (bodyExpression != null) {
|
||||||
returnType = new DeferredType(new LazyValue<JetType>() {
|
returnType = DeferredType.create(trace, new LazyValueWithDefault<JetType>(ErrorUtils.createErrorType("Recursive dependency")) {
|
||||||
@Override
|
@Override
|
||||||
protected JetType compute() {
|
protected JetType compute() {
|
||||||
JetFlowInformationProvider flowInformationProvider = computeFlowData(function, bodyExpression);
|
JetFlowInformationProvider flowInformationProvider = computeFlowData(function, bodyExpression);
|
||||||
@@ -530,7 +530,7 @@ public class ClassDescriptorResolver {
|
|||||||
return ErrorUtils.createErrorType("No type, no body");
|
return ErrorUtils.createErrorType("No type, no body");
|
||||||
} else {
|
} else {
|
||||||
// TODO : a risk of a memory leak
|
// TODO : a risk of a memory leak
|
||||||
LazyValue<JetType> lazyValue = new LazyValue<JetType>() {
|
LazyValue<JetType> lazyValue = new LazyValueWithDefault<JetType>(ErrorUtils.createErrorType("Recursive dependency")) {
|
||||||
@Override
|
@Override
|
||||||
protected JetType compute() {
|
protected JetType compute() {
|
||||||
JetFlowInformationProvider flowInformationProvider = computeFlowData(property, initializer);
|
JetFlowInformationProvider flowInformationProvider = computeFlowData(property, initializer);
|
||||||
@@ -538,7 +538,7 @@ public class ClassDescriptorResolver {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (allowDeferred) {
|
if (allowDeferred) {
|
||||||
return new DeferredType(lazyValue);
|
return DeferredType.create(trace, lazyValue);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return lazyValue.get();
|
return lazyValue.get();
|
||||||
|
|||||||
+3
-3
@@ -11,7 +11,7 @@ import java.util.Map;
|
|||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
public class BindingTraceAdapter implements BindingTrace {
|
public class ObservableBindingTrace implements BindingTrace {
|
||||||
public interface RecordHandler<K, V> {
|
public interface RecordHandler<K, V> {
|
||||||
|
|
||||||
void handleRecord(WritableSlice<K, V> slice, K key, V value);
|
void handleRecord(WritableSlice<K, V> slice, K key, V value);
|
||||||
@@ -19,7 +19,7 @@ public class BindingTraceAdapter implements BindingTrace {
|
|||||||
private final BindingTrace originalTrace;
|
private final BindingTrace originalTrace;
|
||||||
|
|
||||||
private Map<WritableSlice, RecordHandler> handlers = Maps.newHashMap();
|
private Map<WritableSlice, RecordHandler> handlers = Maps.newHashMap();
|
||||||
public BindingTraceAdapter(BindingTrace originalTrace) {
|
public ObservableBindingTrace(BindingTrace originalTrace) {
|
||||||
this.originalTrace = originalTrace;
|
this.originalTrace = originalTrace;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ public class BindingTraceAdapter implements BindingTrace {
|
|||||||
return originalTrace.get(slice, key);
|
return originalTrace.get(slice, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <K, V> BindingTraceAdapter addHandler(@NotNull WritableSlice<K, V> slice, @NotNull RecordHandler<K, V> handler) {
|
public <K, V> ObservableBindingTrace addHandler(@NotNull WritableSlice<K, V> slice, @NotNull RecordHandler<K, V> handler) {
|
||||||
handlers.put(slice, handler);
|
handlers.put(slice, handler);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -16,7 +16,7 @@ import java.util.Set;
|
|||||||
*/
|
*/
|
||||||
/*package*/ class TopDownAnalysisContext {
|
/*package*/ class TopDownAnalysisContext {
|
||||||
|
|
||||||
private final BindingTrace trace;
|
private final ObservableBindingTrace trace;
|
||||||
private final JetSemanticServices semanticServices;
|
private final JetSemanticServices semanticServices;
|
||||||
private final ClassDescriptorResolver classDescriptorResolver;
|
private final ClassDescriptorResolver classDescriptorResolver;
|
||||||
|
|
||||||
@@ -32,12 +32,12 @@ import java.util.Set;
|
|||||||
private final Map<JetDeclaration, JetScope> declaringScopes = Maps.newHashMap();
|
private final Map<JetDeclaration, JetScope> declaringScopes = Maps.newHashMap();
|
||||||
|
|
||||||
public TopDownAnalysisContext(JetSemanticServices semanticServices, BindingTrace trace) {
|
public TopDownAnalysisContext(JetSemanticServices semanticServices, BindingTrace trace) {
|
||||||
this.trace = trace;
|
this.trace = new ObservableBindingTrace(trace);
|
||||||
this.semanticServices = semanticServices;
|
this.semanticServices = semanticServices;
|
||||||
this.classDescriptorResolver = semanticServices.getClassDescriptorResolver(trace);
|
this.classDescriptorResolver = semanticServices.getClassDescriptorResolver(trace);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BindingTrace getTrace() {
|
public ObservableBindingTrace getTrace() {
|
||||||
return trace;
|
return trace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ public class TopDownAnalyzer {
|
|||||||
public static void process(
|
public static void process(
|
||||||
@NotNull JetSemanticServices semanticServices,
|
@NotNull JetSemanticServices semanticServices,
|
||||||
@NotNull BindingTrace trace,
|
@NotNull BindingTrace trace,
|
||||||
@NotNull JetScope outerScope, NamespaceLike owner, @NotNull List<JetDeclaration> declarations) {
|
@NotNull JetScope outerScope, NamespaceLike owner, @NotNull List<? extends JetDeclaration> declarations) {
|
||||||
TopDownAnalysisContext context = new TopDownAnalysisContext(semanticServices, trace);
|
TopDownAnalysisContext context = new TopDownAnalysisContext(semanticServices, trace);
|
||||||
new TypeHierarchyResolver(context).process(outerScope, owner, declarations);
|
new TypeHierarchyResolver(context).process(outerScope, owner, declarations);
|
||||||
new DeclarationResolver(context).process();
|
new DeclarationResolver(context).process();
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public class TypeHierarchyResolver {
|
|||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void process(@NotNull JetScope outerScope, NamespaceLike owner, @NotNull List<JetDeclaration> declarations) {
|
public void process(@NotNull JetScope outerScope, NamespaceLike owner, @NotNull List<? extends JetDeclaration> declarations) {
|
||||||
collectNamespacesAndClassifiers(outerScope, owner, declarations); // namespaceScopes, classes
|
collectNamespacesAndClassifiers(outerScope, owner, declarations); // namespaceScopes, classes
|
||||||
|
|
||||||
createTypeConstructors(); // create type constructors for classes and generic parameters, supertypes are not filled in
|
createTypeConstructors(); // create type constructors for classes and generic parameters, supertypes are not filled in
|
||||||
@@ -62,7 +62,7 @@ public class TypeHierarchyResolver {
|
|||||||
private void collectNamespacesAndClassifiers(
|
private void collectNamespacesAndClassifiers(
|
||||||
@NotNull final JetScope outerScope,
|
@NotNull final JetScope outerScope,
|
||||||
@NotNull final NamespaceLike owner,
|
@NotNull final NamespaceLike owner,
|
||||||
@NotNull Collection<JetDeclaration> declarations) {
|
@NotNull Collection<? extends JetDeclaration> declarations) {
|
||||||
for (JetDeclaration declaration : declarations) {
|
for (JetDeclaration declaration : declarations) {
|
||||||
declaration.accept(new JetVisitorVoid() {
|
declaration.accept(new JetVisitorVoid() {
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -48,8 +48,12 @@ public class CallResolver {
|
|||||||
@NotNull ReceiverDescriptor receiver,
|
@NotNull ReceiverDescriptor receiver,
|
||||||
@NotNull final JetSimpleNameExpression nameExpression,
|
@NotNull final JetSimpleNameExpression nameExpression,
|
||||||
@NotNull JetType expectedType) {
|
@NotNull JetType expectedType) {
|
||||||
|
String referencedName = nameExpression.getReferencedName();
|
||||||
|
if (referencedName == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
Call call = CallMaker.makePropertyCall(nameExpression);
|
Call call = CallMaker.makePropertyCall(nameExpression);
|
||||||
List<ResolutionTask<VariableDescriptor>> prioritizedTasks = PROPERTY_TASK_PRIORITIZER.computePrioritizedTasks(scope, receiver, call, nameExpression.getReferencedName());
|
List<ResolutionTask<VariableDescriptor>> prioritizedTasks = PROPERTY_TASK_PRIORITIZER.computePrioritizedTasks(scope, receiver, call, referencedName);
|
||||||
return resolveCallToDescriptor(trace, scope, call, nameExpression.getNode(), expectedType, prioritizedTasks, nameExpression);
|
return resolveCallToDescriptor(trace, scope, call, nameExpression.getNode(), expectedType, prioritizedTasks, nameExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,17 +2,28 @@ package org.jetbrains.jet.lang.types;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.jetbrains.jet.lang.resolve.BindingContext.DEFERRED_TYPE;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.BindingContext.DeferredTypeKey.DEFERRED_TYPE_KEY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
public class DeferredType implements JetType {
|
public class DeferredType implements JetType {
|
||||||
|
|
||||||
|
public static DeferredType create(BindingTrace trace, LazyValue<JetType> lazyValue) {
|
||||||
|
DeferredType deferredType = new DeferredType(lazyValue);
|
||||||
|
trace.record(DEFERRED_TYPE, DEFERRED_TYPE_KEY, deferredType);
|
||||||
|
return deferredType;
|
||||||
|
}
|
||||||
|
|
||||||
private final LazyValue<JetType> lazyValue;
|
private final LazyValue<JetType> lazyValue;
|
||||||
|
|
||||||
public DeferredType(LazyValue<JetType> lazyValue) {
|
private DeferredType(LazyValue<JetType> lazyValue) {
|
||||||
this.lazyValue = lazyValue;
|
this.lazyValue = lazyValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -432,13 +432,13 @@ public class JetTypeInferrer {
|
|||||||
// This implements coercion to Unit
|
// This implements coercion to Unit
|
||||||
TemporaryBindingTrace temporaryTraceExpectingUnit = TemporaryBindingTrace.create(trace);
|
TemporaryBindingTrace temporaryTraceExpectingUnit = TemporaryBindingTrace.create(trace);
|
||||||
final boolean[] mismatch = new boolean[1];
|
final boolean[] mismatch = new boolean[1];
|
||||||
BindingTraceAdapter errorInterceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceExpectingUnit, statementExpression, mismatch);
|
ObservableBindingTrace errorInterceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceExpectingUnit, statementExpression, mismatch);
|
||||||
newContext = newContext(errorInterceptingTrace, scope, newContext.dataFlowInfo, context.expectedType, context.expectedReturnType);
|
newContext = newContext(errorInterceptingTrace, scope, newContext.dataFlowInfo, context.expectedType, context.expectedReturnType);
|
||||||
result = blockLevelVisitor.getType(statementExpression, newContext);
|
result = blockLevelVisitor.getType(statementExpression, newContext);
|
||||||
if (mismatch[0]) {
|
if (mismatch[0]) {
|
||||||
TemporaryBindingTrace temporaryTraceNoExpectedType = TemporaryBindingTrace.create(trace);
|
TemporaryBindingTrace temporaryTraceNoExpectedType = TemporaryBindingTrace.create(trace);
|
||||||
mismatch[0] = false;
|
mismatch[0] = false;
|
||||||
BindingTraceAdapter interceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceNoExpectedType, statementExpression, mismatch);
|
ObservableBindingTrace interceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceNoExpectedType, statementExpression, mismatch);
|
||||||
newContext = newContext(interceptingTrace, scope, newContext.dataFlowInfo, NO_EXPECTED_TYPE, context.expectedReturnType);
|
newContext = newContext(interceptingTrace, scope, newContext.dataFlowInfo, NO_EXPECTED_TYPE, context.expectedReturnType);
|
||||||
result = blockLevelVisitor.getType(statementExpression, newContext);
|
result = blockLevelVisitor.getType(statementExpression, newContext);
|
||||||
if (mismatch[0]) {
|
if (mismatch[0]) {
|
||||||
@@ -474,8 +474,8 @@ public class JetTypeInferrer {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private BindingTraceAdapter makeTraceInterceptingTypeMismatch(final BindingTrace trace, final JetExpression expressionToWatch, final boolean[] mismatchFound) {
|
private ObservableBindingTrace makeTraceInterceptingTypeMismatch(final BindingTrace trace, final JetExpression expressionToWatch, final boolean[] mismatchFound) {
|
||||||
return new BindingTraceAdapter(trace) {
|
return new ObservableBindingTrace(trace) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void report(@NotNull Diagnostic diagnostic) {
|
public void report(@NotNull Diagnostic diagnostic) {
|
||||||
@@ -875,12 +875,12 @@ public class JetTypeInferrer {
|
|||||||
@Override
|
@Override
|
||||||
public JetType visitObjectLiteralExpression(final JetObjectLiteralExpression expression, final TypeInferenceContext context) {
|
public JetType visitObjectLiteralExpression(final JetObjectLiteralExpression expression, final TypeInferenceContext context) {
|
||||||
final JetType[] result = new JetType[1];
|
final JetType[] result = new JetType[1];
|
||||||
BindingTraceAdapter.RecordHandler<PsiElement, ClassDescriptor> handler = new BindingTraceAdapter.RecordHandler<PsiElement, ClassDescriptor>() {
|
ObservableBindingTrace.RecordHandler<PsiElement, ClassDescriptor> handler = new ObservableBindingTrace.RecordHandler<PsiElement, ClassDescriptor>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleRecord(WritableSlice<PsiElement, ClassDescriptor> slice, PsiElement declaration, final ClassDescriptor descriptor) {
|
public void handleRecord(WritableSlice<PsiElement, ClassDescriptor> slice, PsiElement declaration, final ClassDescriptor descriptor) {
|
||||||
if (slice == CLASS && declaration == expression.getObjectDeclaration()) {
|
if (slice == CLASS && declaration == expression.getObjectDeclaration()) {
|
||||||
JetType defaultType = new DeferredType(new LazyValue<JetType>() {
|
JetType defaultType = DeferredType.create(context.trace, new LazyValueWithDefault<JetType>(ErrorUtils.createErrorType("Recursive dependency")) {
|
||||||
@Override
|
@Override
|
||||||
protected JetType compute() {
|
protected JetType compute() {
|
||||||
return descriptor.getDefaultType();
|
return descriptor.getDefaultType();
|
||||||
@@ -894,7 +894,7 @@ public class JetTypeInferrer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
BindingTraceAdapter traceAdapter = new BindingTraceAdapter(context.trace);
|
ObservableBindingTrace traceAdapter = new ObservableBindingTrace(context.trace);
|
||||||
traceAdapter.addHandler(CLASS, handler);
|
traceAdapter.addHandler(CLASS, handler);
|
||||||
TopDownAnalyzer.processObject(semanticServices, traceAdapter, context.scope, context.scope.getContainingDeclaration(), expression.getObjectDeclaration());
|
TopDownAnalyzer.processObject(semanticServices, traceAdapter, context.scope, context.scope.getContainingDeclaration(), expression.getObjectDeclaration());
|
||||||
return context.services.checkType(result[0], expression, context);
|
return context.services.checkType(result[0], expression, context);
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ public abstract class LazyValue<T> {
|
|||||||
|
|
||||||
protected abstract T compute();
|
protected abstract T compute();
|
||||||
|
|
||||||
|
protected T getValueOnErrorReentry() {
|
||||||
|
throw new ReenteringLazyValueComputationException();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isComputed() {
|
public boolean isComputed() {
|
||||||
return state == State.ERROR || state == State.COMPUTED;
|
return state == State.ERROR || state == State.COMPUTED;
|
||||||
}
|
}
|
||||||
@@ -34,7 +38,7 @@ public abstract class LazyValue<T> {
|
|||||||
case COMPUTED:
|
case COMPUTED:
|
||||||
return value;
|
return value;
|
||||||
case ERROR:
|
case ERROR:
|
||||||
throw new ReenteringLazyValueComputationException();
|
return getValueOnErrorReentry();
|
||||||
}
|
}
|
||||||
throw new IllegalStateException("Unreachable");
|
throw new IllegalStateException("Unreachable");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package org.jetbrains.jet.lang.types;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author abreslav
|
||||||
|
*/
|
||||||
|
public abstract class LazyValueWithDefault<T> extends LazyValue<T> {
|
||||||
|
private final T defaultValue;
|
||||||
|
|
||||||
|
protected LazyValueWithDefault(T defaultValue) {
|
||||||
|
this.defaultValue = defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected T getValueOnErrorReentry() {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-10
@@ -7,15 +7,8 @@ public class ReenteringLazyValueComputationException extends RuntimeException {
|
|||||||
public ReenteringLazyValueComputationException() {
|
public ReenteringLazyValueComputationException() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReenteringLazyValueComputationException(String message) {
|
@Override
|
||||||
super(message);
|
public synchronized Throwable fillInStackTrace() {
|
||||||
}
|
return this;
|
||||||
|
|
||||||
public ReenteringLazyValueComputationException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReenteringLazyValueComputationException(Throwable cause) {
|
|
||||||
super(cause);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package org.jetbrains.jet.util.slicedmap;
|
||||||
|
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author abreslav
|
||||||
|
*/
|
||||||
|
public class CollectionSliceWrapper<K, V> implements WritableSlice<K, V> {
|
||||||
|
|
||||||
|
private final WritableSlice<K, Collection<V>> wrapped;
|
||||||
|
private final SlicedMapKey<K, V> myKey;
|
||||||
|
private final Supplier<? extends Collection<V>> supplier;
|
||||||
|
|
||||||
|
public CollectionSliceWrapper(WritableSlice<K, Collection<V>> wrapped, Supplier<? extends Collection<V>> supplier) {
|
||||||
|
this.wrapped = wrapped;
|
||||||
|
this.supplier = supplier;
|
||||||
|
this.myKey = new SlicedMapKey<K, V>(this, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SlicedMapKey<K, V> makeKey(K key) {
|
||||||
|
return myKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean check(K key, V value) {
|
||||||
|
assert value != null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPut(MutableSlicedMap map, K key, V value) {
|
||||||
|
Collection<V> collection = map.get(wrapped, key);
|
||||||
|
if (collection == null) {
|
||||||
|
collection = supplier.get();
|
||||||
|
map.put(wrapped, key, collection);
|
||||||
|
}
|
||||||
|
collection.add(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RewritePolicy getRewritePolicy() {
|
||||||
|
return RewritePolicy.DO_NOTHING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V computeValue(SlicedMap map, K key, V value, boolean valueNotFound) {
|
||||||
|
throw new UnsupportedOperationException("Don't read by this slice, use the wrapped one");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ReadOnlySlice<K, V> makeRawValueVersion() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,10 +34,11 @@ public class SlicedMapImpl implements MutableSlicedMap {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SlicedMapKey<K, V> slicedMapKey = slice.makeKey(key);
|
SlicedMapKey<K, V> slicedMapKey = slice.makeKey(key);
|
||||||
if (slice.getRewritePolicy().rewriteProcessingNeeded(key)) {
|
RewritePolicy rewritePolicy = slice.getRewritePolicy();
|
||||||
|
if (rewritePolicy.rewriteProcessingNeeded(key)) {
|
||||||
if (map.containsKey(slicedMapKey)) {
|
if (map.containsKey(slicedMapKey)) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
if (!slice.getRewritePolicy().processRewrite(slice, key, (V) map.get(slicedMapKey), value)) {
|
if (!rewritePolicy.processRewrite(slice, key, (V) map.get(slicedMapKey), value)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -160,10 +160,10 @@ public class Slices {
|
|||||||
|
|
||||||
public static class SetSlice<K> extends BasicRemovableSlice<K, Boolean> {
|
public static class SetSlice<K> extends BasicRemovableSlice<K, Boolean> {
|
||||||
|
|
||||||
|
|
||||||
protected SetSlice(String debugName, RewritePolicy rewritePolicy) {
|
protected SetSlice(String debugName, RewritePolicy rewritePolicy) {
|
||||||
super(debugName, rewritePolicy);
|
super(debugName, rewritePolicy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Boolean computeValue(SlicedMap map, K key, Boolean value, boolean valueNotFound) {
|
public Boolean computeValue(SlicedMap map, K key, Boolean value, boolean valueNotFound) {
|
||||||
if (valueNotFound) return false;
|
if (valueNotFound) return false;
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
package org.jetbrains.jet.plugin.compiler;
|
package org.jetbrains.jet.plugin.compiler;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
import com.intellij.openapi.application.ApplicationManager;
|
import com.intellij.openapi.application.ApplicationManager;
|
||||||
import com.intellij.openapi.compiler.CompileContext;
|
import com.intellij.openapi.compiler.CompileContext;
|
||||||
import com.intellij.openapi.compiler.CompileScope;
|
import com.intellij.openapi.compiler.CompileScope;
|
||||||
import com.intellij.openapi.compiler.CompilerMessageCategory;
|
import com.intellij.openapi.compiler.CompilerMessageCategory;
|
||||||
import com.intellij.openapi.compiler.TranslatingCompiler;
|
import com.intellij.openapi.compiler.TranslatingCompiler;
|
||||||
|
import com.intellij.openapi.editor.Document;
|
||||||
import com.intellij.openapi.module.Module;
|
import com.intellij.openapi.module.Module;
|
||||||
import com.intellij.openapi.util.Computable;
|
import com.intellij.openapi.util.TextRange;
|
||||||
import com.intellij.openapi.util.io.FileUtil;
|
import com.intellij.openapi.util.io.FileUtil;
|
||||||
import com.intellij.openapi.vfs.VirtualFile;
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
import com.intellij.psi.PsiFile;
|
import com.intellij.psi.PsiFile;
|
||||||
@@ -15,14 +17,20 @@ import com.intellij.util.Chunk;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.codegen.ClassFileFactory;
|
import org.jetbrains.jet.codegen.ClassFileFactory;
|
||||||
import org.jetbrains.jet.codegen.GenerationState;
|
import org.jetbrains.jet.codegen.GenerationState;
|
||||||
|
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||||
|
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
|
||||||
import org.jetbrains.jet.lang.psi.JetFile;
|
import org.jetbrains.jet.lang.psi.JetFile;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetNamespace;
|
||||||
|
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
||||||
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
|
import org.jetbrains.jet.lang.resolve.java.JavaDefaultImports;
|
||||||
import org.jetbrains.jet.plugin.JetFileType;
|
import org.jetbrains.jet.plugin.JetFileType;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
import static com.intellij.openapi.compiler.CompilerMessageCategory.ERROR;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author yole
|
* @author yole
|
||||||
@@ -45,67 +53,148 @@ public class JetCompiler implements TranslatingCompiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void compile(CompileContext compileContext, Chunk<Module> moduleChunk, VirtualFile[] virtualFiles, OutputSink outputSink) {
|
public void compile(final CompileContext compileContext, Chunk<Module> moduleChunk, final VirtualFile[] virtualFiles, OutputSink outputSink) {
|
||||||
Map<Module, ModuleCompileState> moduleMap = new HashMap<Module, ModuleCompileState>();
|
if (virtualFiles.length == 0) return;
|
||||||
|
|
||||||
for (VirtualFile virtualFile : virtualFiles) {
|
Module module = compileContext.getModuleByFile(virtualFiles[0]);
|
||||||
Module module = compileContext.getModuleByFile(virtualFile);
|
final VirtualFile outputDir = compileContext.getModuleOutputDirectory(module);
|
||||||
ModuleCompileState state = moduleMap.get(module);
|
if (outputDir == null) {
|
||||||
if (state == null) {
|
compileContext.addMessage(ERROR, "[Internal Error] No output directory", "", -1, -1);
|
||||||
state = new ModuleCompileState(compileContext, module, outputSink);
|
return;
|
||||||
moduleMap.put(module, state);
|
|
||||||
}
|
|
||||||
state.compile(virtualFile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ModuleCompileState state : moduleMap.values()) {
|
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||||
state.done();
|
@Override
|
||||||
}
|
public void run() {
|
||||||
|
GenerationState generationState = new GenerationState(compileContext.getProject(), false);
|
||||||
}
|
List<JetNamespace> namespaces = Lists.newArrayList();
|
||||||
|
for (VirtualFile virtualFile : virtualFiles) {
|
||||||
private static class ModuleCompileState {
|
PsiFile psiFile = PsiManager.getInstance(compileContext.getProject()).findFile(virtualFile);
|
||||||
private final GenerationState state;
|
|
||||||
private final CompileContext compileContext;
|
|
||||||
private final Module module;
|
|
||||||
private final OutputSink outputSink;
|
|
||||||
|
|
||||||
public ModuleCompileState(final CompileContext compileContext, Module module, OutputSink outputSink) {
|
|
||||||
this.compileContext = compileContext;
|
|
||||||
this.module = module;
|
|
||||||
this.outputSink = outputSink;
|
|
||||||
state = ApplicationManager.getApplication().runReadAction(new Computable<GenerationState>() {
|
|
||||||
@Override
|
|
||||||
public GenerationState compute() {
|
|
||||||
return new GenerationState(compileContext.getProject(), false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void compile(final VirtualFile virtualFile) {
|
|
||||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
PsiFile psiFile = PsiManager.getInstance(module.getProject()).findFile(virtualFile);
|
|
||||||
if (psiFile instanceof JetFile) {
|
if (psiFile instanceof JetFile) {
|
||||||
state.compile((JetFile) psiFile);
|
namespaces.add(((JetFile) psiFile).getRootNamespace());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void done() {
|
BindingContext bindingContext = AnalyzingUtils.getInstance(JavaDefaultImports.JAVA_DEFAULT_IMPORTS).analyzeNamespaces(compileContext.getProject(), namespaces, JetControlFlowDataTraceFactory.EMPTY);
|
||||||
VirtualFile outputDir = compileContext.getModuleOutputDirectory(module);
|
|
||||||
final ClassFileFactory factory = state.getFactory();
|
boolean errors = false;
|
||||||
List<String> files = factory.files();
|
for (Diagnostic diagnostic : bindingContext.getDiagnostics()) {
|
||||||
for (String file : files) {
|
switch (diagnostic.getSeverity()) {
|
||||||
File target = new File(outputDir.getPath(), file);
|
case ERROR:
|
||||||
try {
|
errors = true;
|
||||||
FileUtil.writeToFile(target, factory.asBytes(file));
|
report(diagnostic, CompilerMessageCategory.ERROR, compileContext);
|
||||||
} catch (IOException e) {
|
break;
|
||||||
compileContext.addMessage(CompilerMessageCategory.ERROR, e.getMessage(), null, 0, 0);
|
case INFO:
|
||||||
|
report(diagnostic, CompilerMessageCategory.INFORMATION, compileContext);
|
||||||
|
break;
|
||||||
|
case WARNING:
|
||||||
|
report(diagnostic, CompilerMessageCategory.WARNING, compileContext);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!errors) {
|
||||||
|
generationState.compileCorrectNamespaces(bindingContext, namespaces);
|
||||||
|
|
||||||
|
final ClassFileFactory factory = generationState.getFactory();
|
||||||
|
List<String> files = factory.files();
|
||||||
|
for (String file : files) {
|
||||||
|
File target = new File(outputDir.getPath(), file);
|
||||||
|
try {
|
||||||
|
FileUtil.writeToFile(target, factory.asBytes(file));
|
||||||
|
} catch (IOException e) {
|
||||||
|
compileContext.addMessage(ERROR, e.getMessage(), null, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Map<Module, ModuleCompileState> moduleMap = new HashMap<Module, ModuleCompileState>();
|
||||||
|
//
|
||||||
|
// for (VirtualFile virtualFile : virtualFiles) {
|
||||||
|
// Module module = compileContext.getModuleByFile(virtualFile);
|
||||||
|
// ModuleCompileState state = moduleMap.get(module);
|
||||||
|
// if (state == null) {
|
||||||
|
// state = new ModuleCompileState(compileContext, module, outputSink);
|
||||||
|
// moduleMap.put(module, state);
|
||||||
|
// }
|
||||||
|
// state.compile(virtualFile);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// for (ModuleCompileState state : moduleMap.values()) {
|
||||||
|
// state.done();
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void report(Diagnostic diagnostic, CompilerMessageCategory severity, CompileContext compileContext) {
|
||||||
|
PsiFile psiFile = diagnostic.getFactory().getPsiFile(diagnostic);
|
||||||
|
TextRange textRange = diagnostic.getFactory().getTextRange(diagnostic);
|
||||||
|
Document document = psiFile.getViewProvider().getDocument();
|
||||||
|
int line;
|
||||||
|
int col;
|
||||||
|
if (document != null) {
|
||||||
|
line = document.getLineNumber(textRange.getStartOffset());
|
||||||
|
col = textRange.getStartOffset() - document.getLineStartOffset(line) + 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
line = -1;
|
||||||
|
col = -1;
|
||||||
|
}
|
||||||
|
VirtualFile virtualFile = psiFile.getVirtualFile();
|
||||||
|
if (virtualFile == null) {
|
||||||
|
compileContext.addMessage(ERROR, "[Internal Error] No virtual file for PsiFile. Diagnostic: " + diagnostic.getMessage(), "", -1, -1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
compileContext.addMessage(severity, diagnostic.getMessage(), virtualFile.getUrl(), line + 1, col);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// private static class ModuleCompileState {
|
||||||
|
// private final GenerationState state;
|
||||||
|
// private final CompileContext compileContext;
|
||||||
|
// private final Module module;
|
||||||
|
// private final OutputSink outputSink;
|
||||||
|
//
|
||||||
|
// public ModuleCompileState(final CompileContext compileContext, Module module, OutputSink outputSink) {
|
||||||
|
// this.compileContext = compileContext;
|
||||||
|
// this.module = module;
|
||||||
|
// this.outputSink = outputSink;
|
||||||
|
// state = ApplicationManager.getApplication().runReadAction(new Computable<GenerationState>() {
|
||||||
|
// @Override
|
||||||
|
// public GenerationState compute() {
|
||||||
|
// return new GenerationState(compileContext.getProject(), false);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// public void compile(final VirtualFile virtualFile) {
|
||||||
|
// ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||||
|
// @Override
|
||||||
|
// public void run() {
|
||||||
|
// PsiFile psiFile = PsiManager.getInstance(module.getProject()).findFile(virtualFile);
|
||||||
|
// if (psiFile instanceof JetFile) {
|
||||||
|
// state.compile((JetFile) psiFile);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public void done() {
|
||||||
|
// VirtualFile outputDir = compileContext.getModuleOutputDirectory(module);
|
||||||
|
// final ClassFileFactory factory = state.getFactory();
|
||||||
|
// List<String> files = factory.files();
|
||||||
|
// for (String file : files) {
|
||||||
|
// File target = new File(outputDir.getPath(), file);
|
||||||
|
// try {
|
||||||
|
// FileUtil.writeToFile(target, factory.asBytes(file));
|
||||||
|
// } catch (IOException e) {
|
||||||
|
// compileContext.addMessage(ERROR, e.getMessage(), null, 0, 0);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ val a = object {
|
|||||||
{
|
{
|
||||||
b + 1
|
b + 1
|
||||||
}
|
}
|
||||||
val x = <error>b</error>
|
val x = b
|
||||||
val y = 1
|
val y = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
val b = a.x
|
val b = <error>a</error>.x
|
||||||
val c = a.y
|
val c = a.y
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ val a = object {
|
|||||||
{
|
{
|
||||||
b + 1
|
b + 1
|
||||||
}
|
}
|
||||||
val x = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>b<!>
|
val x = b
|
||||||
val y = 1
|
val y = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
val b = a.x
|
val b = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>a<!>.x
|
||||||
val c = a.y
|
val c = a.y
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
trait T {
|
||||||
|
val a = <!PROPERTY_INITIALIZER_IN_TRAIT!><!UNRESOLVED_REFERENCE!>Foo<!>.bar()<!>
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user