diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java index c0594fc2eb0..39862f0051e 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java @@ -17,6 +17,9 @@ import org.jetbrains.jet.lang.types.JetStandardLibrary; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.commons.Method; +import java.util.Collections; +import java.util.List; + public class GenerationState { private final ClassFileFactory factory; private final Project project; @@ -85,14 +88,31 @@ public class GenerationState { public void compile(JetFile psiFile) { final JetNamespace namespace = psiFile.getRootNamespace(); - NamespaceCodegen codegen = forNamespace(namespace); final BindingContext bindingContext = AnalyzingUtils.getInstance(JavaDefaultImports.JAVA_DEFAULT_IMPORTS).analyzeNamespace(namespace, JetControlFlowDataTraceFactory.EMPTY); - bindingContexts.push(bindingContext); - typeMapper = new JetTypeMapper(standardLibrary, bindingContext); - try { - AnalyzingUtils.throwExceptionOnErrors(bindingContext); + AnalyzingUtils.throwExceptionOnErrors(bindingContext); + compileCorrectNamespaces(bindingContext, Collections.singletonList(namespace)); +// NamespaceCodegen codegen = forNamespace(namespace); +// 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 namespaces) { + typeMapper = new JetTypeMapper(standardLibrary, bindingContext); + bindingContexts.push(bindingContext); + try { + for (JetNamespace namespace : namespaces) { + NamespaceCodegen codegen = forNamespace(namespace); + codegen.generate(namespace); + } } finally { bindingContexts.pop(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetObjectDeclaration.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetObjectDeclaration.java index fae5958f7d2..e3b91196931 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetObjectDeclaration.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetObjectDeclaration.java @@ -22,7 +22,7 @@ public class JetObjectDeclaration extends JetNamedDeclaration implements JetClas @Override public String getName() { JetObjectDeclarationName nameAsDeclaration = getNameAsDeclaration(); - return nameAsDeclaration == null ? "ClassObj" : nameAsDeclaration.getName(); + return nameAsDeclaration == null ? null : nameAsDeclaration.getName(); } @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java index 94e330a7756..7b39810143c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java @@ -23,6 +23,7 @@ import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; import java.util.Collections; +import java.util.List; //import org.jetbrains.jet.lang.resolve.java.JavaPackageScope; //import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices; @@ -66,7 +67,12 @@ public class AnalyzingUtils { public BindingContext analyzeNamespace(@NotNull JetNamespace namespace, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) { Project project = namespace.getProject(); + List declarations = Collections.singletonList(namespace); + return analyzeNamespaces(project, declarations, flowDataTraceFactory); + } + + public BindingContext analyzeNamespaces(@NotNull Project project, @NotNull List declarations, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) { BindingTraceContext bindingTraceContext = new BindingTraceContext(); JetSemanticServices semanticServices = JetSemanticServices.createSemanticServices(project, flowDataTraceFactory); @@ -105,7 +111,7 @@ public class AnalyzingUtils { public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) { throw new IllegalStateException("Must be guaranteed not to happen by the parser"); } - }, Collections.singletonList(namespace)); + }, declarations); return bindingTraceContext.getBindingContext(); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java index 01c4cb717ad..c4b719d139a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java @@ -9,7 +9,9 @@ import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.scopes.JetScope; 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.util.CommonSuppliers; import org.jetbrains.jet.util.slicedmap.*; import java.util.Collection; @@ -41,6 +43,10 @@ public interface BindingContext { WritableSlice PROCESSED = Slices.createSimpleSetSlice("PROCESSED"); WritableSlice STATEMENT = Slices.createRemovableSetSlice("STATEMENT"); WritableSlice DELEGATED = Slices.createRemovableSetSlice("DELEGATED"); + + enum DeferredTypeKey {DEFERRED_TYPE_KEY} + WritableSlice> DEFERRED_TYPES = Slices.createSimpleSlice("DEFERRED_TYPES"); + WritableSlice DEFERRED_TYPE = new CollectionSliceWrapper(DEFERRED_TYPES, CommonSuppliers.getArrayListSupplier()); WritableSlice BACKING_FIELD_REQUIRED = new Slices.SetSlice("BACKING_FIELD_REQUIRED", RewritePolicy.DO_NOTHING) { @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java index cd98216b91b..c38be41fffb 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java @@ -4,6 +4,7 @@ import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.intellij.lang.ASTNode; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.containers.Queue; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider; 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.util.slicedmap.WritableSlice; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; 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; /** - * @author abreslav - */ +* @author abreslav +*/ public class BodyResolver { private final TopDownAnalysisContext context; - private final BindingTraceAdapter traceForConstructors; - private final BindingTraceAdapter traceForMembers; + private final ObservableBindingTrace traceForConstructors; + private final ObservableBindingTrace traceForMembers; public BodyResolver(TopDownAnalysisContext context) { this.context = context; // This allows access to backing fields - this.traceForConstructors = new BindingTraceAdapter(context.getTrace()).addHandler(BindingContext.REFERENCE_TARGET, new BindingTraceAdapter.RecordHandler() { + this.traceForConstructors = new ObservableBindingTrace(context.getTrace()).addHandler(BindingContext.REFERENCE_TARGET, new ObservableBindingTrace.RecordHandler() { @Override public void handleRecord(WritableSlice slice, JetReferenceExpression expression, DeclarationDescriptor descriptor) { 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.traceForMembers = new BindingTraceAdapter(context.getTrace()).addHandler(BindingContext.REFERENCE_TARGET, new BindingTraceAdapter.RecordHandler() { + this.traceForMembers = new ObservableBindingTrace(context.getTrace()).addHandler(BindingContext.REFERENCE_TARGET, new ObservableBindingTrace.RecordHandler() { @Override public void handleRecord(WritableSlice slice, JetReferenceExpression expression, DeclarationDescriptor descriptor) { if (descriptor instanceof PropertyDescriptor) { @@ -78,7 +79,34 @@ public class BodyResolver { resolveSecondaryConstructorBodies(); resolveFunctionBodies(); - + computeDeferredTypes(); + } + + private void computeDeferredTypes() { + Collection deferredTypes = context.getTrace().get(DEFERRED_TYPES, DEFERRED_TYPE_KEY); + if (deferredTypes != null) { + final Queue queue = new Queue(deferredTypes.size()); + context.getTrace().addHandler(DEFERRED_TYPE, new ObservableBindingTrace.RecordHandler() { + @Override + public void handleRecord(WritableSlice 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) { final ConstructorDescriptor primaryConstructor = descriptor.getUnsubstitutedPrimaryConstructor(); final JetScope scopeForConstructor = primaryConstructor == null - ? null - : getInnerScopeForConstructor(primaryConstructor, descriptor.getScopeForMemberResolution(), true); + ? null + : getInnerScopeForConstructor(primaryConstructor, descriptor.getScopeForMemberResolution(), true); final JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(traceForConstructors, JetFlowInformationProvider.NONE); // TODO : flow final Map supertypes = Maps.newLinkedHashMap(); @@ -317,8 +345,8 @@ public class BodyResolver { ClassDescriptor classDescriptor = descriptor.getContainingDeclaration(); typeInferrerForInitializers.getCallResolver().resolveCall(context.getTrace(), - functionInnerScope, - ReceiverDescriptor.NO_RECEIVER, call, NO_EXPECTED_TYPE); + functionInnerScope, + ReceiverDescriptor.NO_RECEIVER, call, NO_EXPECTED_TYPE); // call.getThisReference(), // classDescriptor, // classDescriptor.getDefaultType(), @@ -436,7 +464,7 @@ public class BodyResolver { } 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"); accessorScope.addPropertyDescriptorByFieldName("$" + propertyDescriptor.getName(), propertyDescriptor); @@ -454,8 +482,8 @@ public class BodyResolver { } } - private BindingTraceAdapter createFieldTrackingTrace(final PropertyDescriptor propertyDescriptor) { - return new BindingTraceAdapter(traceForMembers).addHandler(BindingContext.REFERENCE_TARGET, new BindingTraceAdapter.RecordHandler() { + private ObservableBindingTrace createFieldTrackingTrace(final PropertyDescriptor propertyDescriptor) { + return new ObservableBindingTrace(traceForMembers).addHandler(BindingContext.REFERENCE_TARGET, new ObservableBindingTrace.RecordHandler() { @Override public void handleRecord(WritableSlice slice, JetReferenceExpression expression, DeclarationDescriptor descriptor) { if (expression instanceof JetSimpleNameExpression) { @@ -471,8 +499,8 @@ public class BodyResolver { }); } - private BindingTraceAdapter createFieldAssignTrackingTrace() { - return new BindingTraceAdapter(traceForConstructors).addHandler(BindingContext.VARIABLE_ASSIGNMENT, new BindingTraceAdapter.RecordHandler() { + private ObservableBindingTrace createFieldAssignTrackingTrace() { + return new ObservableBindingTrace(traceForConstructors).addHandler(BindingContext.VARIABLE_ASSIGNMENT, new ObservableBindingTrace.RecordHandler() { @Override public void handleRecord(WritableSlice jetExpressionBooleanWritableSlice, JetExpression expression, DeclarationDescriptor descriptor) { if (expression instanceof JetSimpleNameExpression) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java index 0cd5ea93978..ad9595825b5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java @@ -175,7 +175,7 @@ public class ClassDescriptorResolver { else { final JetExpression bodyExpression = function.getBodyExpression(); if (bodyExpression != null) { - returnType = new DeferredType(new LazyValue() { + returnType = DeferredType.create(trace, new LazyValueWithDefault(ErrorUtils.createErrorType("Recursive dependency")) { @Override protected JetType compute() { JetFlowInformationProvider flowInformationProvider = computeFlowData(function, bodyExpression); @@ -530,7 +530,7 @@ public class ClassDescriptorResolver { return ErrorUtils.createErrorType("No type, no body"); } else { // TODO : a risk of a memory leak - LazyValue lazyValue = new LazyValue() { + LazyValue lazyValue = new LazyValueWithDefault(ErrorUtils.createErrorType("Recursive dependency")) { @Override protected JetType compute() { JetFlowInformationProvider flowInformationProvider = computeFlowData(property, initializer); @@ -538,7 +538,7 @@ public class ClassDescriptorResolver { } }; if (allowDeferred) { - return new DeferredType(lazyValue); + return DeferredType.create(trace, lazyValue); } else { return lazyValue.get(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingTraceAdapter.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ObservableBindingTrace.java similarity index 85% rename from compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingTraceAdapter.java rename to compiler/frontend/src/org/jetbrains/jet/lang/resolve/ObservableBindingTrace.java index fd44d0231ab..928c463217b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingTraceAdapter.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ObservableBindingTrace.java @@ -11,7 +11,7 @@ import java.util.Map; /** * @author abreslav */ -public class BindingTraceAdapter implements BindingTrace { +public class ObservableBindingTrace implements BindingTrace { public interface RecordHandler { void handleRecord(WritableSlice slice, K key, V value); @@ -19,7 +19,7 @@ public class BindingTraceAdapter implements BindingTrace { private final BindingTrace originalTrace; private Map handlers = Maps.newHashMap(); - public BindingTraceAdapter(BindingTrace originalTrace) { + public ObservableBindingTrace(BindingTrace originalTrace) { this.originalTrace = originalTrace; } @@ -52,7 +52,7 @@ public class BindingTraceAdapter implements BindingTrace { return originalTrace.get(slice, key); } - public BindingTraceAdapter addHandler(@NotNull WritableSlice slice, @NotNull RecordHandler handler) { + public ObservableBindingTrace addHandler(@NotNull WritableSlice slice, @NotNull RecordHandler handler) { handlers.put(slice, handler); return this; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisContext.java index 225a7069436..5847cf61cfd 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisContext.java @@ -16,7 +16,7 @@ import java.util.Set; */ /*package*/ class TopDownAnalysisContext { - private final BindingTrace trace; + private final ObservableBindingTrace trace; private final JetSemanticServices semanticServices; private final ClassDescriptorResolver classDescriptorResolver; @@ -32,12 +32,12 @@ import java.util.Set; private final Map declaringScopes = Maps.newHashMap(); public TopDownAnalysisContext(JetSemanticServices semanticServices, BindingTrace trace) { - this.trace = trace; + this.trace = new ObservableBindingTrace(trace); this.semanticServices = semanticServices; this.classDescriptorResolver = semanticServices.getClassDescriptorResolver(trace); } - public BindingTrace getTrace() { + public ObservableBindingTrace getTrace() { return trace; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index b486dd556c2..42762dd3c5b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -61,7 +61,7 @@ public class TopDownAnalyzer { public static void process( @NotNull JetSemanticServices semanticServices, @NotNull BindingTrace trace, - @NotNull JetScope outerScope, NamespaceLike owner, @NotNull List declarations) { + @NotNull JetScope outerScope, NamespaceLike owner, @NotNull List declarations) { TopDownAnalysisContext context = new TopDownAnalysisContext(semanticServices, trace); new TypeHierarchyResolver(context).process(outerScope, owner, declarations); new DeclarationResolver(context).process(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java index 9d860516b34..1a5d519e22c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java @@ -37,7 +37,7 @@ public class TypeHierarchyResolver { this.context = context; } - public void process(@NotNull JetScope outerScope, NamespaceLike owner, @NotNull List declarations) { + public void process(@NotNull JetScope outerScope, NamespaceLike owner, @NotNull List declarations) { collectNamespacesAndClassifiers(outerScope, owner, declarations); // namespaceScopes, classes createTypeConstructors(); // create type constructors for classes and generic parameters, supertypes are not filled in @@ -62,7 +62,7 @@ public class TypeHierarchyResolver { private void collectNamespacesAndClassifiers( @NotNull final JetScope outerScope, @NotNull final NamespaceLike owner, - @NotNull Collection declarations) { + @NotNull Collection declarations) { for (JetDeclaration declaration : declarations) { declaration.accept(new JetVisitorVoid() { @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java index f0423457999..ec4ce7e7ee9 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java @@ -48,8 +48,12 @@ public class CallResolver { @NotNull ReceiverDescriptor receiver, @NotNull final JetSimpleNameExpression nameExpression, @NotNull JetType expectedType) { + String referencedName = nameExpression.getReferencedName(); + if (referencedName == null) { + return null; + } Call call = CallMaker.makePropertyCall(nameExpression); - List> prioritizedTasks = PROPERTY_TASK_PRIORITIZER.computePrioritizedTasks(scope, receiver, call, nameExpression.getReferencedName()); + List> prioritizedTasks = PROPERTY_TASK_PRIORITIZER.computePrioritizedTasks(scope, receiver, call, referencedName); return resolveCallToDescriptor(trace, scope, call, nameExpression.getNode(), expectedType, prioritizedTasks, nameExpression); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/DeferredType.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/DeferredType.java index b405df67340..d97ae1c5a64 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/DeferredType.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/DeferredType.java @@ -2,17 +2,28 @@ package org.jetbrains.jet.lang.types; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.scopes.JetScope; 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 */ public class DeferredType implements JetType { + + public static DeferredType create(BindingTrace trace, LazyValue lazyValue) { + DeferredType deferredType = new DeferredType(lazyValue); + trace.record(DEFERRED_TYPE, DEFERRED_TYPE_KEY, deferredType); + return deferredType; + } + private final LazyValue lazyValue; - public DeferredType(LazyValue lazyValue) { + private DeferredType(LazyValue lazyValue) { this.lazyValue = lazyValue; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index 7da4d79b325..bc1770da090 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -432,13 +432,13 @@ public class JetTypeInferrer { // This implements coercion to Unit TemporaryBindingTrace temporaryTraceExpectingUnit = TemporaryBindingTrace.create(trace); 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); result = blockLevelVisitor.getType(statementExpression, newContext); if (mismatch[0]) { TemporaryBindingTrace temporaryTraceNoExpectedType = TemporaryBindingTrace.create(trace); 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); result = blockLevelVisitor.getType(statementExpression, newContext); if (mismatch[0]) { @@ -474,8 +474,8 @@ public class JetTypeInferrer { return result; } - private BindingTraceAdapter makeTraceInterceptingTypeMismatch(final BindingTrace trace, final JetExpression expressionToWatch, final boolean[] mismatchFound) { - return new BindingTraceAdapter(trace) { + private ObservableBindingTrace makeTraceInterceptingTypeMismatch(final BindingTrace trace, final JetExpression expressionToWatch, final boolean[] mismatchFound) { + return new ObservableBindingTrace(trace) { @Override public void report(@NotNull Diagnostic diagnostic) { @@ -875,12 +875,12 @@ public class JetTypeInferrer { @Override public JetType visitObjectLiteralExpression(final JetObjectLiteralExpression expression, final TypeInferenceContext context) { final JetType[] result = new JetType[1]; - BindingTraceAdapter.RecordHandler handler = new BindingTraceAdapter.RecordHandler() { + ObservableBindingTrace.RecordHandler handler = new ObservableBindingTrace.RecordHandler() { @Override public void handleRecord(WritableSlice slice, PsiElement declaration, final ClassDescriptor descriptor) { if (slice == CLASS && declaration == expression.getObjectDeclaration()) { - JetType defaultType = new DeferredType(new LazyValue() { + JetType defaultType = DeferredType.create(context.trace, new LazyValueWithDefault(ErrorUtils.createErrorType("Recursive dependency")) { @Override protected JetType compute() { 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); TopDownAnalyzer.processObject(semanticServices, traceAdapter, context.scope, context.scope.getContainingDeclaration(), expression.getObjectDeclaration()); return context.services.checkType(result[0], expression, context); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/LazyValue.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/LazyValue.java index 482df0533c3..ef310e545cc 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/LazyValue.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/LazyValue.java @@ -17,6 +17,10 @@ public abstract class LazyValue { protected abstract T compute(); + protected T getValueOnErrorReentry() { + throw new ReenteringLazyValueComputationException(); + } + public boolean isComputed() { return state == State.ERROR || state == State.COMPUTED; } @@ -34,7 +38,7 @@ public abstract class LazyValue { case COMPUTED: return value; case ERROR: - throw new ReenteringLazyValueComputationException(); + return getValueOnErrorReentry(); } throw new IllegalStateException("Unreachable"); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/LazyValueWithDefault.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/LazyValueWithDefault.java new file mode 100644 index 00000000000..bd9f15fa26c --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/LazyValueWithDefault.java @@ -0,0 +1,17 @@ +package org.jetbrains.jet.lang.types; + +/** + * @author abreslav + */ +public abstract class LazyValueWithDefault extends LazyValue { + private final T defaultValue; + + protected LazyValueWithDefault(T defaultValue) { + this.defaultValue = defaultValue; + } + + @Override + protected T getValueOnErrorReentry() { + return defaultValue; + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/ReenteringLazyValueComputationException.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/ReenteringLazyValueComputationException.java index 36847c3ea4c..1005fb72df7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/ReenteringLazyValueComputationException.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/ReenteringLazyValueComputationException.java @@ -7,15 +7,8 @@ public class ReenteringLazyValueComputationException extends RuntimeException { public ReenteringLazyValueComputationException() { } - public ReenteringLazyValueComputationException(String message) { - super(message); - } - - public ReenteringLazyValueComputationException(String message, Throwable cause) { - super(message, cause); - } - - public ReenteringLazyValueComputationException(Throwable cause) { - super(cause); + @Override + public synchronized Throwable fillInStackTrace() { + return this; } } diff --git a/compiler/frontend/src/org/jetbrains/jet/util/slicedmap/CollectionSliceWrapper.java b/compiler/frontend/src/org/jetbrains/jet/util/slicedmap/CollectionSliceWrapper.java new file mode 100644 index 00000000000..faded385ac3 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/util/slicedmap/CollectionSliceWrapper.java @@ -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 implements WritableSlice { + + private final WritableSlice> wrapped; + private final SlicedMapKey myKey; + private final Supplier> supplier; + + public CollectionSliceWrapper(WritableSlice> wrapped, Supplier> supplier) { + this.wrapped = wrapped; + this.supplier = supplier; + this.myKey = new SlicedMapKey(this, null); + } + + @Override + public SlicedMapKey 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 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 makeRawValueVersion() { + return this; + } +} \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/jet/util/slicedmap/SlicedMapImpl.java b/compiler/frontend/src/org/jetbrains/jet/util/slicedmap/SlicedMapImpl.java index 0aebe1aa744..36dbf297929 100644 --- a/compiler/frontend/src/org/jetbrains/jet/util/slicedmap/SlicedMapImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/util/slicedmap/SlicedMapImpl.java @@ -34,10 +34,11 @@ public class SlicedMapImpl implements MutableSlicedMap { return; } SlicedMapKey slicedMapKey = slice.makeKey(key); - if (slice.getRewritePolicy().rewriteProcessingNeeded(key)) { + RewritePolicy rewritePolicy = slice.getRewritePolicy(); + if (rewritePolicy.rewriteProcessingNeeded(key)) { if (map.containsKey(slicedMapKey)) { //noinspection unchecked - if (!slice.getRewritePolicy().processRewrite(slice, key, (V) map.get(slicedMapKey), value)) { + if (!rewritePolicy.processRewrite(slice, key, (V) map.get(slicedMapKey), value)) { return; } } @@ -70,4 +71,4 @@ public class SlicedMapImpl implements MutableSlicedMap { //noinspection unchecked return (Iterator) map.entrySet().iterator(); } -} +} \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/jet/util/slicedmap/Slices.java b/compiler/frontend/src/org/jetbrains/jet/util/slicedmap/Slices.java index 9108f0a07f2..c5bbb7c135d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/util/slicedmap/Slices.java +++ b/compiler/frontend/src/org/jetbrains/jet/util/slicedmap/Slices.java @@ -160,10 +160,10 @@ public class Slices { public static class SetSlice extends BasicRemovableSlice { - protected SetSlice(String debugName, RewritePolicy rewritePolicy) { super(debugName, rewritePolicy); } + @Override public Boolean computeValue(SlicedMap map, K key, Boolean value, boolean valueNotFound) { if (valueNotFound) return false; diff --git a/idea/src/org/jetbrains/jet/plugin/compiler/JetCompiler.java b/idea/src/org/jetbrains/jet/plugin/compiler/JetCompiler.java index 9c12a4b27d3..c29a35c2ea3 100644 --- a/idea/src/org/jetbrains/jet/plugin/compiler/JetCompiler.java +++ b/idea/src/org/jetbrains/jet/plugin/compiler/JetCompiler.java @@ -1,12 +1,14 @@ package org.jetbrains.jet.plugin.compiler; +import com.google.common.collect.Lists; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.compiler.CompileContext; import com.intellij.openapi.compiler.CompileScope; import com.intellij.openapi.compiler.CompilerMessageCategory; import com.intellij.openapi.compiler.TranslatingCompiler; +import com.intellij.openapi.editor.Document; 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.vfs.VirtualFile; import com.intellij.psi.PsiFile; @@ -15,14 +17,20 @@ import com.intellij.util.Chunk; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.codegen.ClassFileFactory; 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.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 java.io.File; import java.io.IOException; -import java.util.HashMap; import java.util.List; -import java.util.Map; + +import static com.intellij.openapi.compiler.CompilerMessageCategory.ERROR; /** * @author yole @@ -45,67 +53,148 @@ public class JetCompiler implements TranslatingCompiler { } @Override - public void compile(CompileContext compileContext, Chunk moduleChunk, VirtualFile[] virtualFiles, OutputSink outputSink) { - Map moduleMap = new HashMap(); + public void compile(final CompileContext compileContext, Chunk moduleChunk, final VirtualFile[] virtualFiles, OutputSink outputSink) { + if (virtualFiles.length == 0) return; - 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); + Module module = compileContext.getModuleByFile(virtualFiles[0]); + final VirtualFile outputDir = compileContext.getModuleOutputDirectory(module); + if (outputDir == null) { + compileContext.addMessage(ERROR, "[Internal Error] No output directory", "", -1, -1); + return; } - for (ModuleCompileState state : moduleMap.values()) { - state.done(); - } - - } - - 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() { - @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); + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + GenerationState generationState = new GenerationState(compileContext.getProject(), false); + List namespaces = Lists.newArrayList(); + for (VirtualFile virtualFile : virtualFiles) { + PsiFile psiFile = PsiManager.getInstance(compileContext.getProject()).findFile(virtualFile); if (psiFile instanceof JetFile) { - state.compile((JetFile) psiFile); + namespaces.add(((JetFile) psiFile).getRootNamespace()); } } - }); - } - public void done() { - VirtualFile outputDir = compileContext.getModuleOutputDirectory(module); - final ClassFileFactory factory = state.getFactory(); - List 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(CompilerMessageCategory.ERROR, e.getMessage(), null, 0, 0); + BindingContext bindingContext = AnalyzingUtils.getInstance(JavaDefaultImports.JAVA_DEFAULT_IMPORTS).analyzeNamespaces(compileContext.getProject(), namespaces, JetControlFlowDataTraceFactory.EMPTY); + + boolean errors = false; + for (Diagnostic diagnostic : bindingContext.getDiagnostics()) { + switch (diagnostic.getSeverity()) { + case ERROR: + errors = true; + report(diagnostic, CompilerMessageCategory.ERROR, compileContext); + break; + 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 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 moduleMap = new HashMap(); +// +// 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() { +// @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 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); +// } +// } +// } +// } } diff --git a/idea/testData/checker/regression/Jet81.jet b/idea/testData/checker/regression/Jet81.jet index cafc4840db7..f6b382d86da 100644 --- a/idea/testData/checker/regression/Jet81.jet +++ b/idea/testData/checker/regression/Jet81.jet @@ -14,9 +14,9 @@ val a = object { { b + 1 } - val x = b + val x = b val y = 1 } -val b = a.x +val b = a.x val c = a.y diff --git a/idea/testData/checkerWithErrorTypes/full/regression/Jet81.jet b/idea/testData/checkerWithErrorTypes/full/regression/Jet81.jet index c3df9ba023f..a3ff4596172 100644 --- a/idea/testData/checkerWithErrorTypes/full/regression/Jet81.jet +++ b/idea/testData/checkerWithErrorTypes/full/regression/Jet81.jet @@ -14,9 +14,9 @@ val a = object { { b + 1 } - val x = b + val x = b val y = 1 } -val b = a.x +val b = a.x val c = a.y diff --git a/idea/testData/checkerWithErrorTypes/quick/DeferredTypes.jet b/idea/testData/checkerWithErrorTypes/quick/DeferredTypes.jet new file mode 100644 index 00000000000..8125ddbc904 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/quick/DeferredTypes.jet @@ -0,0 +1,3 @@ +trait T { + val a = Foo.bar() +}