Merge branch 'master' of github.com:JetBrains/kotlin

This commit is contained in:
James Strachan
2012-05-28 17:16:23 +01:00
105 changed files with 2364 additions and 2037 deletions
+3
View File
@@ -410,6 +410,9 @@
<inspection_tool class="UtilityClassWithPublicConstructor" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="UtilityClassWithPublicConstructor" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="UtilityClassWithoutPrivateConstructor" enabled="true" level="WARNING" enabled_by_default="true"> <inspection_tool class="UtilityClassWithoutPrivateConstructor" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoreClassesWithOnlyMain" value="false" /> <option name="ignoreClassesWithOnlyMain" value="false" />
<option name="ignorableAnnotations">
<value />
</option>
</inspection_tool> </inspection_tool>
<inspection_tool class="VolatileLongOrDoubleField" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="VolatileLongOrDoubleField" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="WaitNotInLoop" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="WaitNotInLoop" enabled="true" level="WARNING" enabled_by_default="true" />
+1 -3
View File
@@ -26,8 +26,6 @@
<RunnerSettings RunnerId="Run" /> <RunnerSettings RunnerId="Run" />
<ConfigurationWrapper RunnerId="Debug" /> <ConfigurationWrapper RunnerId="Debug" />
<ConfigurationWrapper RunnerId="Run" /> <ConfigurationWrapper RunnerId="Run" />
<method> <method />
<option name="AntTarget" enabled="false" antfile="file://$PROJECT_DIR$/js_backend_tests.xml" target="copy_lib" />
</method>
</configuration> </configuration>
</component> </component>
@@ -198,7 +198,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
private Type generateBody(FunctionDescriptor funDescriptor, ClassBuilder cv, JetDeclarationWithBody body) { private Type generateBody(FunctionDescriptor funDescriptor, ClassBuilder cv, JetDeclarationWithBody body) {
ClassDescriptor function = state.getInjector().getJetTypeMapper().getClosureAnnotator().classDescriptorForFunctionDescriptor(funDescriptor, name); ClassDescriptor function = state.getInjector().getJetTypeMapper().getClosureAnnotator().classDescriptorForFunctionDescriptor(funDescriptor, name);
final CodegenContext.ClosureContext closureContext = context.intoClosure( final CodegenContexts.ClosureContext closureContext = context.intoClosure(
funDescriptor, function, name.getInternalName(), this, state.getInjector().getJetTypeMapper()); funDescriptor, function, name.getInternalName(), this, state.getInjector().getJetTypeMapper());
FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state); FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state);
JvmMethodSignature jvmMethodSignature = invokeSignature(funDescriptor); JvmMethodSignature jvmMethodSignature = invokeSignature(funDescriptor);
@@ -35,25 +35,6 @@ import java.util.LinkedHashMap;
* @author alex.tkachman * @author alex.tkachman
*/ */
public abstract class CodegenContext { public abstract class CodegenContext {
public static final CodegenContext STATIC = new CodegenContext(null, OwnerKind.NAMESPACE, null, null) {
@Override
protected ClassDescriptor getThisDescriptor() {
return null;
}
@Override
public boolean isStatic() {
return true;
}
@Override
public String toString() {
return "ROOT";
}
};
protected static final StackValue local0 = StackValue.local(0, JetTypeMapper.TYPE_OBJECT);
protected static final StackValue local1 = StackValue.local(1, JetTypeMapper.TYPE_OBJECT);
private final DeclarationDescriptor contextType; private final DeclarationDescriptor contextType;
@@ -121,31 +102,31 @@ public abstract class CodegenContext {
} }
public CodegenContext intoNamespace(NamespaceDescriptor descriptor) { public CodegenContext intoNamespace(NamespaceDescriptor descriptor) {
return new NamespaceContext(descriptor, this); return new CodegenContexts.NamespaceContext(descriptor, this);
} }
public CodegenContext intoClass(ClassDescriptor descriptor, OwnerKind kind, JetTypeMapper typeMapper) { public CodegenContext intoClass(ClassDescriptor descriptor, OwnerKind kind, JetTypeMapper typeMapper) {
return new ClassContext(descriptor, kind, this, typeMapper); return new CodegenContexts.ClassContext(descriptor, kind, this, typeMapper);
} }
public CodegenContext intoAnonymousClass(@NotNull ObjectOrClosureCodegen closure, ClassDescriptor descriptor, OwnerKind kind, JetTypeMapper typeMapper) { public CodegenContext intoAnonymousClass(@NotNull ObjectOrClosureCodegen closure, ClassDescriptor descriptor, OwnerKind kind, JetTypeMapper typeMapper) {
return new AnonymousClassContext(descriptor, kind, this, closure, typeMapper); return new CodegenContexts.AnonymousClassContext(descriptor, kind, this, closure, typeMapper);
} }
public MethodContext intoFunction(FunctionDescriptor descriptor) { public CodegenContexts.MethodContext intoFunction(FunctionDescriptor descriptor) {
return new MethodContext(descriptor, getContextKind(), this); return new CodegenContexts.MethodContext(descriptor, getContextKind(), this);
} }
public ConstructorContext intoConstructor(ConstructorDescriptor descriptor, JetTypeMapper typeMapper) { public CodegenContexts.ConstructorContext intoConstructor(ConstructorDescriptor descriptor, JetTypeMapper typeMapper) {
if(descriptor == null) { if(descriptor == null) {
descriptor = new ConstructorDescriptorImpl(getThisDescriptor(), Collections.<AnnotationDescriptor>emptyList(), true) descriptor = new ConstructorDescriptorImpl(getThisDescriptor(), Collections.<AnnotationDescriptor>emptyList(), true)
.initialize(Collections.<TypeParameterDescriptor>emptyList(), Collections.<ValueParameterDescriptor>emptyList(), Visibilities.PUBLIC); .initialize(Collections.<TypeParameterDescriptor>emptyList(), Collections.<ValueParameterDescriptor>emptyList(), Visibilities.PUBLIC);
} }
return new ConstructorContext(descriptor, getContextKind(), this, typeMapper); return new CodegenContexts.ConstructorContext(descriptor, getContextKind(), this, typeMapper);
} }
public ClosureContext intoClosure(FunctionDescriptor funDescriptor, ClassDescriptor classDescriptor, String internalClassName, ClosureCodegen closureCodegen, JetTypeMapper typeMapper) { public CodegenContexts.ClosureContext intoClosure(FunctionDescriptor funDescriptor, ClassDescriptor classDescriptor, String internalClassName, ClosureCodegen closureCodegen, JetTypeMapper typeMapper) {
return new ClosureContext(funDescriptor, classDescriptor, this, closureCodegen, internalClassName, typeMapper); return new CodegenContexts.ClosureContext(funDescriptor, classDescriptor, this, closureCodegen, internalClassName, typeMapper);
} }
public FrameMap prepareFrame(JetTypeMapper mapper) { public FrameMap prepareFrame(JetTypeMapper mapper) {
@@ -190,7 +171,7 @@ public abstract class CodegenContext {
} }
public int getTypeInfoConstantIndex(JetType type) { public int getTypeInfoConstantIndex(JetType type) {
if (parentContext != STATIC) { return parentContext.getTypeInfoConstantIndex(type); } if (parentContext != CodegenContexts.STATIC) { return parentContext.getTypeInfoConstantIndex(type); }
if(typeInfoConstants == null) { if(typeInfoConstants == null) {
typeInfoConstants = new LinkedHashMap<JetType, Integer>(); typeInfoConstants = new LinkedHashMap<JetType, Integer>();
@@ -242,7 +223,7 @@ public abstract class CodegenContext {
CallableMemberDescriptor.Kind.DECLARATION CallableMemberDescriptor.Kind.DECLARATION
); );
JetType receiverType = pd.getReceiverParameter().exists() ? pd.getReceiverParameter().getType() : null; JetType receiverType = pd.getReceiverParameter().exists() ? pd.getReceiverParameter().getType() : null;
myAccessor.setType(pd.getType(), Collections.<TypeParameterDescriptor>emptyList(), pd.getExpectedThisObject(), receiverType); myAccessor.setType(pd.getType(), Collections.<TypeParameterDescriptorImpl>emptyList(), pd.getExpectedThisObject(), receiverType);
PropertyGetterDescriptor pgd = new PropertyGetterDescriptor( PropertyGetterDescriptor pgd = new PropertyGetterDescriptor(
myAccessor, Collections.<AnnotationDescriptor>emptyList(), myAccessor.getModality(), myAccessor, Collections.<AnnotationDescriptor>emptyList(), myAccessor.getModality(),
@@ -280,174 +261,4 @@ public abstract class CodegenContext {
this.accessors.putAll(accessors); this.accessors.putAll(accessors);
} }
} }
public abstract static class ReceiverContext extends CodegenContext {
final CallableDescriptor receiverDescriptor;
public ReceiverContext(CallableDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, @Nullable ObjectOrClosureCodegen closureCodegen) {
super(contextType, contextKind, parentContext, closureCodegen);
receiverDescriptor = contextType.getReceiverParameter().exists() ? contextType : null;
}
@Override
protected CallableDescriptor getReceiverDescriptor() {
return receiverDescriptor;
}
}
public static class MethodContext extends ReceiverContext {
public MethodContext(FunctionDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext) {
super(contextType instanceof PropertyAccessorDescriptor ? ((PropertyAccessorDescriptor)contextType).getCorrespondingProperty() : contextType, contextKind, parentContext, null);
}
@Override
protected ClassDescriptor getThisDescriptor() {
return getParentContext().getThisDescriptor();
}
public StackValue lookupInContext(DeclarationDescriptor d, InstructionAdapter v, StackValue result) {
return getParentContext().lookupInContext(d, v, result);
}
public Type enclosingClassType(JetTypeMapper typeMapper) {
return getParentContext().enclosingClassType(typeMapper);
}
@Override
public boolean isStatic() {
return getParentContext().isStatic();
}
protected StackValue getOuterExpression(StackValue prefix) {
return getParentContext().getOuterExpression(prefix);
}
@Override
public String toString() {
return "Method: " + getContextDescriptor();
}
}
public static class ConstructorContext extends MethodContext {
public ConstructorContext(ConstructorDescriptor contextType, OwnerKind kind, CodegenContext parent, JetTypeMapper typeMapper) {
super(contextType, kind, parent);
final Type type = enclosingClassType(typeMapper);
outerExpression = type != null
? local1
: null;
}
protected StackValue getOuterExpression(StackValue prefix) {
return outerExpression;
}
@Override
public String toString() {
return "Constructor: " + getContextDescriptor().getName();
}
}
public static class ClassContext extends CodegenContext {
public ClassContext(ClassDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, JetTypeMapper typeMapper) {
super(contextType, contextKind, parentContext, null);
final Type type = enclosingClassType(typeMapper);
outerExpression = type != null
? StackValue.field(type, typeMapper.getFQName(contextType), "this$0", false)
: null;
}
@Override
protected ClassDescriptor getThisDescriptor() {
return (ClassDescriptor) getContextDescriptor();
}
@Override
public boolean isStatic() {
return false;
}
}
public static class AnonymousClassContext extends CodegenContext {
public AnonymousClassContext(ClassDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, @NotNull ObjectOrClosureCodegen closure, JetTypeMapper typeMapper) {
super(contextType, contextKind, parentContext, closure);
final Type type = enclosingClassType(typeMapper);
Type owner = closure.state.getInjector().getJetTypeMapper().mapType(contextType.getDefaultType(), MapTypeMode.IMPL);
outerExpression = type != null
? StackValue.field(type, owner.getInternalName(), "this$0", false)
: null;
}
@Override
protected ClassDescriptor getThisDescriptor() {
return (ClassDescriptor) getContextDescriptor();
}
@Override
public boolean isStatic() {
return false;
}
@Override
public String toString() {
return "Anonymous: " + getThisDescriptor();
}
}
public static class ClosureContext extends ReceiverContext {
private ClassDescriptor classDescriptor;
public ClosureContext(FunctionDescriptor contextType, ClassDescriptor classDescriptor, CodegenContext parentContext, @NotNull ObjectOrClosureCodegen closureCodegen, String internalClassName, JetTypeMapper typeMapper) {
super(contextType, OwnerKind.IMPLEMENTATION, parentContext, closureCodegen);
this.classDescriptor = classDescriptor;
final Type type = enclosingClassType(typeMapper);
outerExpression = type != null
? StackValue.field(type, internalClassName, "this$0", false)
: null;
}
@Override
protected ClassDescriptor getThisDescriptor() {
return classDescriptor;
}
@Override
public DeclarationDescriptor getContextDescriptor() {
return classDescriptor;
}
@Override
public boolean isStatic() {
return false;
}
@Override
public String toString() {
return "Closure: " + classDescriptor;
}
}
public static class NamespaceContext extends CodegenContext {
public NamespaceContext(NamespaceDescriptor contextType, CodegenContext parent) {
super(contextType, OwnerKind.NAMESPACE, parent, null);
}
@Override
protected ClassDescriptor getThisDescriptor() {
return null;
}
@Override
public boolean isStatic() {
return true;
}
@Override
public String toString() {
return "Namespace: " + getContextDescriptor().getName();
}
}
} }
@@ -0,0 +1,223 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.codegen;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyAccessorDescriptor;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
/**
* @author Stepan Koltsov
*/
public class CodegenContexts {
public static final CodegenContext STATIC = new CodegenContext(null, OwnerKind.NAMESPACE, null, null) {
@Override
protected ClassDescriptor getThisDescriptor() {
return null;
}
@Override
public boolean isStatic() {
return true;
}
@Override
public String toString() {
return "ROOT";
}
};
protected static final StackValue local0 = StackValue.local(0, JetTypeMapper.TYPE_OBJECT);
protected static final StackValue local1 = StackValue.local(1, JetTypeMapper.TYPE_OBJECT);
public abstract static class ReceiverContext extends CodegenContext {
final CallableDescriptor receiverDescriptor;
public ReceiverContext(CallableDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, @Nullable ObjectOrClosureCodegen closureCodegen) {
super(contextType, contextKind, parentContext, closureCodegen);
receiverDescriptor = contextType.getReceiverParameter().exists() ? contextType : null;
}
@Override
protected CallableDescriptor getReceiverDescriptor() {
return receiverDescriptor;
}
}
public static class MethodContext extends ReceiverContext {
public MethodContext(FunctionDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext) {
super(contextType instanceof PropertyAccessorDescriptor ? ((PropertyAccessorDescriptor)contextType).getCorrespondingProperty() : contextType, contextKind, parentContext, null);
}
@Override
protected ClassDescriptor getThisDescriptor() {
return getParentContext().getThisDescriptor();
}
public StackValue lookupInContext(DeclarationDescriptor d, InstructionAdapter v, StackValue result) {
return getParentContext().lookupInContext(d, v, result);
}
public Type enclosingClassType(JetTypeMapper typeMapper) {
return getParentContext().enclosingClassType(typeMapper);
}
@Override
public boolean isStatic() {
return getParentContext().isStatic();
}
protected StackValue getOuterExpression(StackValue prefix) {
return getParentContext().getOuterExpression(prefix);
}
@Override
public String toString() {
return "Method: " + getContextDescriptor();
}
}
public static class ConstructorContext extends MethodContext {
public ConstructorContext(ConstructorDescriptor contextType, OwnerKind kind, CodegenContext parent, JetTypeMapper typeMapper) {
super(contextType, kind, parent);
final Type type = enclosingClassType(typeMapper);
outerExpression = type != null
? local1
: null;
}
protected StackValue getOuterExpression(StackValue prefix) {
return outerExpression;
}
@Override
public String toString() {
return "Constructor: " + getContextDescriptor().getName();
}
}
public static class ClassContext extends CodegenContext {
public ClassContext(ClassDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, JetTypeMapper typeMapper) {
super(contextType, contextKind, parentContext, null);
final Type type = enclosingClassType(typeMapper);
outerExpression = type != null
? StackValue.field(type, typeMapper.getFQName(contextType), "this$0", false)
: null;
}
@Override
protected ClassDescriptor getThisDescriptor() {
return (ClassDescriptor) getContextDescriptor();
}
@Override
public boolean isStatic() {
return false;
}
}
public static class AnonymousClassContext extends CodegenContext {
public AnonymousClassContext(ClassDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, @NotNull ObjectOrClosureCodegen closure, JetTypeMapper typeMapper) {
super(contextType, contextKind, parentContext, closure);
final Type type = enclosingClassType(typeMapper);
Type owner = closure.state.getInjector().getJetTypeMapper().mapType(contextType.getDefaultType(), MapTypeMode.IMPL);
outerExpression = type != null
? StackValue.field(type, owner.getInternalName(), "this$0", false)
: null;
}
@Override
protected ClassDescriptor getThisDescriptor() {
return (ClassDescriptor) getContextDescriptor();
}
@Override
public boolean isStatic() {
return false;
}
@Override
public String toString() {
return "Anonymous: " + getThisDescriptor();
}
}
public static class ClosureContext extends ReceiverContext {
private ClassDescriptor classDescriptor;
public ClosureContext(FunctionDescriptor contextType, ClassDescriptor classDescriptor, CodegenContext parentContext, @NotNull ObjectOrClosureCodegen closureCodegen, String internalClassName, JetTypeMapper typeMapper) {
super(contextType, OwnerKind.IMPLEMENTATION, parentContext, closureCodegen);
this.classDescriptor = classDescriptor;
final Type type = enclosingClassType(typeMapper);
outerExpression = type != null
? StackValue.field(type, internalClassName, "this$0", false)
: null;
}
@Override
protected ClassDescriptor getThisDescriptor() {
return classDescriptor;
}
@Override
public DeclarationDescriptor getContextDescriptor() {
return classDescriptor;
}
@Override
public boolean isStatic() {
return false;
}
@Override
public String toString() {
return "Closure: " + classDescriptor;
}
}
public static class NamespaceContext extends CodegenContext {
public NamespaceContext(NamespaceDescriptor contextType, CodegenContext parent) {
super(contextType, OwnerKind.NAMESPACE, parent, null);
}
@Override
protected ClassDescriptor getThisDescriptor() {
return null;
}
@Override
public boolean isStatic() {
return true;
}
@Override
public String toString() {
return "Namespace: " + getContextDescriptor().getName();
}
}
}
@@ -54,7 +54,7 @@ public class CodegenUtil {
invokeDescriptor.initialize(fd.getReceiverParameter().exists() ? fd.getReceiverParameter().getType() : null, invokeDescriptor.initialize(fd.getReceiverParameter().exists() ? fd.getReceiverParameter().getType() : null,
fd.getExpectedThisObject(), fd.getExpectedThisObject(),
Collections.<TypeParameterDescriptor>emptyList(), Collections.<TypeParameterDescriptorImpl>emptyList(),
fd.getValueParameters(), fd.getValueParameters(),
fd.getReturnType(), fd.getReturnType(),
Modality.FINAL, Modality.FINAL,
@@ -1093,7 +1093,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
} }
if (descriptor instanceof TypeParameterDescriptor) { if (descriptor instanceof TypeParameterDescriptorImpl) {
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor; TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) descriptor;
v.invokevirtual("jet/TypeInfo", "getClassObject", "()Ljava/lang/Object;"); v.invokevirtual("jet/TypeInfo", "getClassObject", "()Ljava/lang/Object;");
v.checkcast(asmType(typeParameterDescriptor.getClassObjectType())); v.checkcast(asmType(typeParameterDescriptor.getClassObjectType()));
@@ -1162,7 +1162,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
boolean isStatic = containingDeclaration instanceof NamespaceDescriptor; boolean isStatic = containingDeclaration instanceof NamespaceDescriptor;
propertyDescriptor = propertyDescriptor.getOriginal(); propertyDescriptor = propertyDescriptor.getOriginal();
boolean isInsideClass = ((containingDeclaration == context.getThisDescriptor()) || boolean isInsideClass = ((containingDeclaration == context.getThisDescriptor()) ||
(context.getParentContext() instanceof CodegenContext.NamespaceContext) && context.getParentContext().getContextDescriptor() == containingDeclaration) (context.getParentContext() instanceof CodegenContexts.NamespaceContext) && context.getParentContext().getContextDescriptor() == containingDeclaration)
&& contextKind() != OwnerKind.TRAIT_IMPL; && contextKind() != OwnerKind.TRAIT_IMPL;
Method getter; Method getter;
Method setter; Method setter;
@@ -1438,8 +1438,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
private StackValue generateReceiver(DeclarationDescriptor provided) { private StackValue generateReceiver(DeclarationDescriptor provided) {
assert context instanceof CodegenContext.ReceiverContext; assert context instanceof CodegenContexts.ReceiverContext;
CodegenContext.ReceiverContext cur = (CodegenContext.ReceiverContext) context; CodegenContexts.ReceiverContext cur = (CodegenContexts.ReceiverContext) context;
if (cur.getReceiverDescriptor() == provided) { if (cur.getReceiverDescriptor() == provided) {
StackValue result = cur.getReceiverExpression(typeMapper); StackValue result = cur.getReceiverExpression(typeMapper);
return castToRequiredTypeOfInterfaceIfNeeded(result, provided, null); return castToRequiredTypeOfInterfaceIfNeeded(result, provided, null);
@@ -1458,7 +1458,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
cur = context; cur = context;
StackValue result = StackValue.local(0, TYPE_OBJECT); StackValue result = StackValue.local(0, TYPE_OBJECT);
while (cur != null) { while (cur != null) {
if(cur instanceof CodegenContext.MethodContext && !(cur instanceof CodegenContext.ConstructorContext)) if(cur instanceof CodegenContexts.MethodContext && !(cur instanceof CodegenContexts.ConstructorContext))
cur = cur.getParentContext(); cur = cur.getParentContext();
if (DescriptorUtils.isSubclass(cur.getThisDescriptor(), calleeContainingClass)) { if (DescriptorUtils.isSubclass(cur.getThisDescriptor(), calleeContainingClass)) {
@@ -1474,7 +1474,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
result = cur.getOuterExpression(result); result = cur.getOuterExpression(result);
if(cur instanceof CodegenContext.ConstructorContext) { if(cur instanceof CodegenContexts.ConstructorContext) {
cur = cur.getParentContext(); cur = cur.getParentContext();
} }
cur = cur.getParentContext(); cur = cur.getParentContext();
@@ -2614,7 +2614,7 @@ If finally block is present, its last expression is the value of try expression.
JetExpression left = expression.getLeft(); JetExpression left = expression.getLeft();
JetType leftType = bindingContext.get(BindingContext.EXPRESSION_TYPE, left); JetType leftType = bindingContext.get(BindingContext.EXPRESSION_TYPE, left);
DeclarationDescriptor descriptor = rightType.getConstructor().getDeclarationDescriptor(); DeclarationDescriptor descriptor = rightType.getConstructor().getDeclarationDescriptor();
if (descriptor instanceof ClassDescriptor || descriptor instanceof TypeParameterDescriptor) { if (descriptor instanceof ClassDescriptor || descriptor instanceof TypeParameterDescriptorImpl) {
StackValue value = genQualified(receiver, left); StackValue value = genQualified(receiver, left);
value.put(JetTypeMapper.boxType(value.type), v); value.put(JetTypeMapper.boxType(value.type), v);
assert leftType != null; assert leftType != null;
@@ -69,7 +69,7 @@ public class FunctionCodegen {
JvmMethodSignature jvmMethod, boolean needJetAnnotations, JvmMethodSignature jvmMethod, boolean needJetAnnotations,
@Nullable String propertyTypeSignature, FunctionDescriptor functionDescriptor) { @Nullable String propertyTypeSignature, FunctionDescriptor functionDescriptor) {
CodegenContext.MethodContext funContext = owner.intoFunction(functionDescriptor); CodegenContexts.MethodContext funContext = owner.intoFunction(functionDescriptor);
final JetExpression bodyExpression = f.getBodyExpression(); final JetExpression bodyExpression = f.getBodyExpression();
generatedMethod(bodyExpression, jvmMethod, needJetAnnotations, propertyTypeSignature, funContext, functionDescriptor, f); generatedMethod(bodyExpression, jvmMethod, needJetAnnotations, propertyTypeSignature, funContext, functionDescriptor, f);
@@ -78,7 +78,7 @@ public class FunctionCodegen {
private void generatedMethod(JetExpression bodyExpressions, private void generatedMethod(JetExpression bodyExpressions,
JvmMethodSignature jvmSignature, JvmMethodSignature jvmSignature,
boolean needJetAnnotations, @Nullable String propertyTypeSignature, boolean needJetAnnotations, @Nullable String propertyTypeSignature,
CodegenContext.MethodContext context, CodegenContexts.MethodContext context,
FunctionDescriptor functionDescriptor, FunctionDescriptor functionDescriptor,
JetDeclarationWithBody fun JetDeclarationWithBody fun
) )
@@ -301,7 +301,7 @@ public class FunctionCodegen {
} }
} }
static void generateDefaultIfNeeded(CodegenContext.MethodContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, @Nullable FunctionDescriptor functionDescriptor, OwnerKind kind) { static void generateDefaultIfNeeded(CodegenContexts.MethodContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, @Nullable FunctionDescriptor functionDescriptor, OwnerKind kind) {
DeclarationDescriptor contextClass = owner.getContextDescriptor().getContainingDeclaration(); DeclarationDescriptor contextClass = owner.getContextDescriptor().getContainingDeclaration();
if(kind != OwnerKind.TRAIT_IMPL) { if(kind != OwnerKind.TRAIT_IMPL) {
@@ -449,7 +449,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, myClass); ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, myClass);
CodegenContext.ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor, typeMapper); CodegenContexts.ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor, typeMapper);
JvmMethodSignature constructorMethod; JvmMethodSignature constructorMethod;
CallableMethod callableMethod; CallableMethod callableMethod;
@@ -463,7 +463,7 @@ public class JetTypeMapper {
return asmType; return asmType;
} }
if (descriptor instanceof TypeParameterDescriptor) { if (descriptor instanceof TypeParameterDescriptorImpl) {
Type type = mapType(((TypeParameterDescriptor) descriptor).getUpperBoundsAsType(), kind); Type type = mapType(((TypeParameterDescriptor) descriptor).getUpperBoundsAsType(), kind);
if (signatureVisitor != null) { if (signatureVisitor != null) {
@@ -722,7 +722,7 @@ public class JetTypeMapper {
signatureVisitor.writeInterfaceBoundEnd(); signatureVisitor.writeInterfaceBoundEnd();
} }
} }
if (jetType.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) { if (jetType.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptorImpl) {
signatureVisitor.writeInterfaceBound(); signatureVisitor.writeInterfaceBound();
mapType(jetType, signatureVisitor, MapTypeMode.TYPE_PARAMETER); mapType(jetType, signatureVisitor, MapTypeMode.TYPE_PARAMETER);
signatureVisitor.writeInterfaceBoundEnd(); signatureVisitor.writeInterfaceBoundEnd();
@@ -966,7 +966,7 @@ public class JetTypeMapper {
public boolean isGenericsArray(JetType type) { public boolean isGenericsArray(JetType type) {
DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor(); DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor();
if(declarationDescriptor instanceof TypeParameterDescriptor) if(declarationDescriptor instanceof TypeParameterDescriptorImpl)
return true; return true;
if(standardLibrary.getArray().equals(declarationDescriptor)) if(standardLibrary.getArray().equals(declarationDescriptor))
@@ -23,7 +23,6 @@ import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver;
import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.java.JvmClassName; import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
@@ -57,7 +56,7 @@ public class NamespaceCodegen {
public void generate(JetFile file) { public void generate(JetFile file) {
NamespaceDescriptor descriptor = state.getBindingContext().get(BindingContext.FILE_TO_NAMESPACE, file); NamespaceDescriptor descriptor = state.getBindingContext().get(BindingContext.FILE_TO_NAMESPACE, file);
final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor); final CodegenContext context = CodegenContexts.STATIC.intoNamespace(descriptor);
final FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state); final FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state);
final PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, state); final PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, state);
@@ -100,7 +99,7 @@ public class NamespaceCodegen {
mv.visitCode(); mv.visitCode();
FrameMap frameMap = new FrameMap(); FrameMap frameMap = new FrameMap();
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, CodegenContext.STATIC, state); ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, CodegenContexts.STATIC, state);
for (JetDeclaration declaration : namespace.getDeclarations()) { for (JetDeclaration declaration : namespace.getDeclarations()) {
if (declaration instanceof JetProperty) { if (declaration instanceof JetProperty) {
@@ -106,9 +106,9 @@ public class ObjectOrClosureCodegen {
FunctionDescriptor fd = (FunctionDescriptor) d; FunctionDescriptor fd = (FunctionDescriptor) d;
// we generate method // we generate method
assert context instanceof CodegenContext.ReceiverContext; assert context instanceof CodegenContexts.ReceiverContext;
CodegenContext.ReceiverContext fcontext = (CodegenContext.ReceiverContext) context; CodegenContexts.ReceiverContext fcontext = (CodegenContexts.ReceiverContext) context;
if(fcontext.getReceiverDescriptor() != fd) if(fcontext.getReceiverDescriptor() != fd)
return null; return null;
@@ -34,7 +34,6 @@ import org.jetbrains.jet.codegen.*;
import org.jetbrains.jet.cli.common.messages.AnalyzerWithCompilerReport; import org.jetbrains.jet.cli.common.messages.AnalyzerWithCompilerReport;
import org.jetbrains.jet.cli.common.messages.CompilerMessageLocation; import org.jetbrains.jet.cli.common.messages.CompilerMessageLocation;
import org.jetbrains.jet.cli.common.messages.CompilerMessageSeverity; import org.jetbrains.jet.cli.common.messages.CompilerMessageSeverity;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetPsiUtil; import org.jetbrains.jet.lang.psi.JetPsiUtil;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
@@ -246,7 +245,6 @@ public class KotlinToJVMBytecodeCompiler {
public AnalyzeExhaust invoke() { public AnalyzeExhaust invoke() {
return AnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration( return AnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
environment.getProject(), environment.getSourceFiles(), filesToAnalyzeCompletely, environment.getProject(), environment.getSourceFiles(), filesToAnalyzeCompletely,
JetControlFlowDataTraceFactory.EMPTY,
configuration.getEnvironment().getCompilerDependencies()); configuration.getEnvironment().getCompilerDependencies());
} }
}, environment.getSourceFiles() }, environment.getSourceFiles()
@@ -17,16 +17,42 @@
package org.jetbrains.jet.di; package org.jetbrains.jet.di;
import org.jetbrains.jet.lang.resolve.TopDownAnalyzer;
import org.jetbrains.jet.lang.resolve.TopDownAnalysisContext;
import org.jetbrains.jet.lang.resolve.BodyResolver;
import org.jetbrains.jet.lang.resolve.ControlFlowAnalyzer;
import org.jetbrains.jet.lang.resolve.DeclarationsChecker;
import org.jetbrains.jet.lang.resolve.DescriptorResolver;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.resolve.TopDownAnalysisParameters;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.resolve.ObservableBindingTrace;
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.java.CompilerDependencies;
import org.jetbrains.jet.lang.resolve.java.CompilerSpecialMode;
import org.jetbrains.jet.lang.resolve.java.JavaBridgeConfiguration;
import org.jetbrains.jet.lang.resolve.java.PsiClassFinderForJvm;
import org.jetbrains.jet.lang.resolve.DeclarationResolver;
import org.jetbrains.jet.lang.resolve.AnnotationResolver;
import org.jetbrains.jet.lang.resolve.calls.CallResolver; import org.jetbrains.jet.lang.resolve.calls.CallResolver;
import org.jetbrains.jet.lang.resolve.calls.OverloadingConflictResolver;
import org.jetbrains.jet.lang.resolve.java.*;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
import org.jetbrains.jet.lang.resolve.TypeResolver;
import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver;
import org.jetbrains.jet.lang.resolve.calls.OverloadingConflictResolver;
import org.jetbrains.jet.lang.resolve.ImportsResolver;
import org.jetbrains.jet.lang.resolve.DelegationResolver;
import org.jetbrains.jet.lang.resolve.NamespaceFactoryImpl;
import org.jetbrains.jet.lang.resolve.OverloadResolver;
import org.jetbrains.jet.lang.resolve.OverrideResolver;
import org.jetbrains.jet.lang.resolve.TypeHierarchyResolver;
import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices;
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver;
import org.jetbrains.jet.lang.resolve.java.JavaTypeTransformer;
import com.intellij.openapi.project.Project;
import org.jetbrains.jet.lang.resolve.TopDownAnalysisParameters;
import org.jetbrains.jet.lang.resolve.ObservableBindingTrace;
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
import org.jetbrains.jet.lang.resolve.java.CompilerDependencies;
import org.jetbrains.annotations.NotNull;
import javax.annotation.PreDestroy; import javax.annotation.PreDestroy;
/* This file is generated by org.jetbrains.jet.di.AllInjectorsGenerator. DO NOT EDIT! */ /* This file is generated by org.jetbrains.jet.di.AllInjectorsGenerator. DO NOT EDIT! */
@@ -42,7 +68,6 @@ public class InjectorForTopDownAnalyzerForJvm {
private final TopDownAnalysisParameters topDownAnalysisParameters; private final TopDownAnalysisParameters topDownAnalysisParameters;
private final ObservableBindingTrace observableBindingTrace; private final ObservableBindingTrace observableBindingTrace;
private final ModuleDescriptor moduleDescriptor; private final ModuleDescriptor moduleDescriptor;
private final JetControlFlowDataTraceFactory jetControlFlowDataTraceFactory;
private final CompilerDependencies compilerDependencies; private final CompilerDependencies compilerDependencies;
private CompilerSpecialMode compilerSpecialMode; private CompilerSpecialMode compilerSpecialMode;
private JavaBridgeConfiguration javaBridgeConfiguration; private JavaBridgeConfiguration javaBridgeConfiguration;
@@ -69,7 +94,6 @@ public class InjectorForTopDownAnalyzerForJvm {
@NotNull TopDownAnalysisParameters topDownAnalysisParameters, @NotNull TopDownAnalysisParameters topDownAnalysisParameters,
@NotNull ObservableBindingTrace observableBindingTrace, @NotNull ObservableBindingTrace observableBindingTrace,
@NotNull ModuleDescriptor moduleDescriptor, @NotNull ModuleDescriptor moduleDescriptor,
JetControlFlowDataTraceFactory jetControlFlowDataTraceFactory,
@NotNull CompilerDependencies compilerDependencies @NotNull CompilerDependencies compilerDependencies
) { ) {
this.topDownAnalyzer = new TopDownAnalyzer(); this.topDownAnalyzer = new TopDownAnalyzer();
@@ -82,7 +106,6 @@ public class InjectorForTopDownAnalyzerForJvm {
this.topDownAnalysisParameters = topDownAnalysisParameters; this.topDownAnalysisParameters = topDownAnalysisParameters;
this.observableBindingTrace = observableBindingTrace; this.observableBindingTrace = observableBindingTrace;
this.moduleDescriptor = moduleDescriptor; this.moduleDescriptor = moduleDescriptor;
this.jetControlFlowDataTraceFactory = jetControlFlowDataTraceFactory;
this.compilerDependencies = compilerDependencies; this.compilerDependencies = compilerDependencies;
this.compilerSpecialMode = compilerDependencies.getCompilerSpecialMode(); this.compilerSpecialMode = compilerDependencies.getCompilerSpecialMode();
this.javaBridgeConfiguration = new JavaBridgeConfiguration(); this.javaBridgeConfiguration = new JavaBridgeConfiguration();
@@ -126,7 +149,6 @@ public class InjectorForTopDownAnalyzerForJvm {
this.bodyResolver.setTopDownAnalysisParameters(topDownAnalysisParameters); this.bodyResolver.setTopDownAnalysisParameters(topDownAnalysisParameters);
this.bodyResolver.setTrace(observableBindingTrace); this.bodyResolver.setTrace(observableBindingTrace);
this.controlFlowAnalyzer.setFlowDataTraceFactory(jetControlFlowDataTraceFactory);
this.controlFlowAnalyzer.setTopDownAnalysisParameters(topDownAnalysisParameters); this.controlFlowAnalyzer.setTopDownAnalysisParameters(topDownAnalysisParameters);
this.controlFlowAnalyzer.setTrace(observableBindingTrace); this.controlFlowAnalyzer.setTrace(observableBindingTrace);
@@ -24,7 +24,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.analyzer.AnalyzeExhaust; import org.jetbrains.jet.analyzer.AnalyzeExhaust;
import org.jetbrains.jet.analyzer.AnalyzerFacade; import org.jetbrains.jet.analyzer.AnalyzerFacade;
import org.jetbrains.jet.di.InjectorForTopDownAnalyzerForJvm; import org.jetbrains.jet.di.InjectorForTopDownAnalyzerForJvm;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.*;
@@ -50,9 +49,8 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade {
@NotNull @NotNull
public AnalyzeExhaust analyzeFiles(@NotNull Project project, public AnalyzeExhaust analyzeFiles(@NotNull Project project,
@NotNull Collection<JetFile> files, @NotNull Collection<JetFile> files,
@NotNull Predicate<PsiFile> filesToAnalyzeCompletely, @NotNull Predicate<PsiFile> filesToAnalyzeCompletely) {
@NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) { return analyzeFilesWithJavaIntegration(project, files, filesToAnalyzeCompletely,
return analyzeFilesWithJavaIntegration(project, files, filesToAnalyzeCompletely, flowDataTraceFactory,
compilerDependenciesForProduction(CompilerSpecialMode.REGULAR), true); compilerDependenciesForProduction(CompilerSpecialMode.REGULAR), true);
} }
@@ -60,22 +58,19 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade {
@Override @Override
public AnalyzeExhaust analyzeBodiesInFiles(@NotNull Project project, public AnalyzeExhaust analyzeBodiesInFiles(@NotNull Project project,
@NotNull Predicate<PsiFile> filesForBodiesResolve, @NotNull Predicate<PsiFile> filesForBodiesResolve,
@NotNull JetControlFlowDataTraceFactory flowDataTraceFactory,
@NotNull BindingTrace headersTraceContext, @NotNull BindingTrace headersTraceContext,
@NotNull BodiesResolveContext bodiesResolveContext @NotNull BodiesResolveContext bodiesResolveContext
) { ) {
return analyzeBodiesInFilesWithJavaIntegration( return analyzeBodiesInFilesWithJavaIntegration(
project, filesForBodiesResolve, flowDataTraceFactory, project, filesForBodiesResolve, compilerDependenciesForProduction(CompilerSpecialMode.REGULAR),
compilerDependenciesForProduction(CompilerSpecialMode.REGULAR),
headersTraceContext, bodiesResolveContext); headersTraceContext, bodiesResolveContext);
} }
public static AnalyzeExhaust analyzeOneFileWithJavaIntegrationAndCheckForErrors( public static AnalyzeExhaust analyzeOneFileWithJavaIntegrationAndCheckForErrors(
JetFile file, JetControlFlowDataTraceFactory flowDataTraceFactory, JetFile file, @NotNull CompilerDependencies compilerDependencies) {
@NotNull CompilerDependencies compilerDependencies) {
AnalyzingUtils.checkForSyntacticErrors(file); AnalyzingUtils.checkForSyntacticErrors(file);
AnalyzeExhaust analyzeExhaust = analyzeOneFileWithJavaIntegration(file, flowDataTraceFactory, compilerDependencies); AnalyzeExhaust analyzeExhaust = analyzeOneFileWithJavaIntegration(file, compilerDependencies);
AnalyzingUtils.throwExceptionOnErrors(analyzeExhaust.getBindingContext()); AnalyzingUtils.throwExceptionOnErrors(analyzeExhaust.getBindingContext());
@@ -83,24 +78,20 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade {
} }
public static AnalyzeExhaust analyzeOneFileWithJavaIntegration( public static AnalyzeExhaust analyzeOneFileWithJavaIntegration(
JetFile file, JetControlFlowDataTraceFactory flowDataTraceFactory, JetFile file, @NotNull CompilerDependencies compilerDependencies) {
@NotNull CompilerDependencies compilerDependencies) {
return analyzeFilesWithJavaIntegration(file.getProject(), Collections.singleton(file), return analyzeFilesWithJavaIntegration(file.getProject(), Collections.singleton(file),
Predicates.<PsiFile>alwaysTrue(), flowDataTraceFactory, compilerDependencies); Predicates.<PsiFile>alwaysTrue(), compilerDependencies);
} }
public static AnalyzeExhaust analyzeFilesWithJavaIntegration( public static AnalyzeExhaust analyzeFilesWithJavaIntegration(
Project project, Collection<JetFile> files, Predicate<PsiFile> filesToAnalyzeCompletely, Project project, Collection<JetFile> files, Predicate<PsiFile> filesToAnalyzeCompletely,
JetControlFlowDataTraceFactory flowDataTraceFactory,
@NotNull CompilerDependencies compilerDependencies) { @NotNull CompilerDependencies compilerDependencies) {
return analyzeFilesWithJavaIntegration( return analyzeFilesWithJavaIntegration(
project, files, filesToAnalyzeCompletely, project, files, filesToAnalyzeCompletely, compilerDependencies, false);
flowDataTraceFactory, compilerDependencies, false);
} }
public static AnalyzeExhaust analyzeFilesWithJavaIntegration( public static AnalyzeExhaust analyzeFilesWithJavaIntegration(
Project project, Collection<JetFile> files, Predicate<PsiFile> filesToAnalyzeCompletely, Project project, Collection<JetFile> files, Predicate<PsiFile> filesToAnalyzeCompletely,
JetControlFlowDataTraceFactory flowDataTraceFactory,
@NotNull CompilerDependencies compilerDependencies, @NotNull CompilerDependencies compilerDependencies,
boolean storeContextForBodiesResolve) { boolean storeContextForBodiesResolve) {
BindingTraceContext bindingTraceContext = new BindingTraceContext(); BindingTraceContext bindingTraceContext = new BindingTraceContext();
@@ -112,8 +103,7 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade {
InjectorForTopDownAnalyzerForJvm injector = new InjectorForTopDownAnalyzerForJvm( InjectorForTopDownAnalyzerForJvm injector = new InjectorForTopDownAnalyzerForJvm(
project, topDownAnalysisParameters, project, topDownAnalysisParameters,
new ObservableBindingTrace(bindingTraceContext), owner, flowDataTraceFactory, new ObservableBindingTrace(bindingTraceContext), owner, compilerDependencies);
compilerDependencies);
try { try {
injector.getTopDownAnalyzer().analyzeFiles(files); injector.getTopDownAnalyzer().analyzeFiles(files);
BodiesResolveContext bodiesResolveContext = storeContextForBodiesResolve ? BodiesResolveContext bodiesResolveContext = storeContextForBodiesResolve ?
@@ -127,7 +117,6 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade {
public static AnalyzeExhaust analyzeBodiesInFilesWithJavaIntegration( public static AnalyzeExhaust analyzeBodiesInFilesWithJavaIntegration(
Project project, Predicate<PsiFile> filesToAnalyzeCompletely, Project project, Predicate<PsiFile> filesToAnalyzeCompletely,
JetControlFlowDataTraceFactory flowDataTraceFactory,
@NotNull CompilerDependencies compilerDependencies, @NotNull CompilerDependencies compilerDependencies,
@NotNull BindingTrace traceContext, @NotNull BindingTrace traceContext,
@NotNull BodiesResolveContext bodiesResolveContext) { @NotNull BodiesResolveContext bodiesResolveContext) {
@@ -140,8 +129,7 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade {
InjectorForTopDownAnalyzerForJvm injector = new InjectorForTopDownAnalyzerForJvm( InjectorForTopDownAnalyzerForJvm injector = new InjectorForTopDownAnalyzerForJvm(
project, topDownAnalysisParameters, project, topDownAnalysisParameters,
new ObservableBindingTrace(traceContext), owner, flowDataTraceFactory, new ObservableBindingTrace(traceContext), owner, compilerDependencies);
compilerDependencies);
try { try {
injector.getTopDownAnalyzer().doProcessForBodies(bodiesResolveContext); injector.getTopDownAnalyzer().doProcessForBodies(bodiesResolveContext);
@@ -157,7 +145,6 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade {
Project project = files.iterator().next().getProject(); Project project = files.iterator().next().getProject();
return analyzeFilesWithJavaIntegration(project, files, Predicates.<PsiFile>alwaysFalse(), return analyzeFilesWithJavaIntegration(project, files, Predicates.<PsiFile>alwaysFalse(), compilerDependencies);
JetControlFlowDataTraceFactory.EMPTY, compilerDependencies);
} }
} }
@@ -49,7 +49,7 @@ import java.util.*;
/** /**
* @author abreslav * @author abreslav
*/ */
public class JavaDescriptorResolver { public class JavaDescriptorResolver implements DependencyClassByQualifiedNameResolver {
public static final Name JAVA_ROOT = Name.special("<java_root>"); public static final Name JAVA_ROOT = Name.special("<java_root>");
@@ -107,14 +107,14 @@ public class JavaDescriptorResolver {
@NotNull @NotNull
private final TypeParameterDescriptorOrigin origin; private final TypeParameterDescriptorOrigin origin;
@NotNull @NotNull
final TypeParameterDescriptor descriptor; final TypeParameterDescriptorImpl descriptor;
final PsiTypeParameter psiTypeParameter; final PsiTypeParameter psiTypeParameter;
@Nullable @Nullable
private final List<JetType> upperBoundsForKotlin; private final List<JetType> upperBoundsForKotlin;
@Nullable @Nullable
private final List<JetType> lowerBoundsForKotlin; private final List<JetType> lowerBoundsForKotlin;
private TypeParameterDescriptorInitialization(@NotNull TypeParameterDescriptor descriptor, @NotNull PsiTypeParameter psiTypeParameter) { private TypeParameterDescriptorInitialization(@NotNull TypeParameterDescriptorImpl descriptor, @NotNull PsiTypeParameter psiTypeParameter) {
this.origin = TypeParameterDescriptorOrigin.JAVA; this.origin = TypeParameterDescriptorOrigin.JAVA;
this.descriptor = descriptor; this.descriptor = descriptor;
this.psiTypeParameter = psiTypeParameter; this.psiTypeParameter = psiTypeParameter;
@@ -122,7 +122,7 @@ public class JavaDescriptorResolver {
this.lowerBoundsForKotlin = null; this.lowerBoundsForKotlin = null;
} }
private TypeParameterDescriptorInitialization(@NotNull TypeParameterDescriptor descriptor, @NotNull PsiTypeParameter psiTypeParameter, private TypeParameterDescriptorInitialization(@NotNull TypeParameterDescriptorImpl descriptor, @NotNull PsiTypeParameter psiTypeParameter,
List<JetType> upperBoundsForKotlin, List<JetType> lowerBoundsForKotlin) { List<JetType> upperBoundsForKotlin, List<JetType> lowerBoundsForKotlin) {
this.origin = TypeParameterDescriptorOrigin.KOTLIN; this.origin = TypeParameterDescriptorOrigin.KOTLIN;
this.descriptor = descriptor; this.descriptor = descriptor;
@@ -307,6 +307,11 @@ public class JavaDescriptorResolver {
return clazz; return clazz;
} }
@Override
public ClassDescriptor resolveClass(@NotNull FqName qualifiedName) {
return resolveClass(qualifiedName, DescriptorSearchRule.ERROR_IF_FOUND_IN_KOTLIN);
}
private ClassDescriptor resolveClass(@NotNull FqName qualifiedName, @NotNull DescriptorSearchRule searchRule, @NotNull List<Runnable> tasks) { private ClassDescriptor resolveClass(@NotNull FqName qualifiedName, @NotNull DescriptorSearchRule searchRule, @NotNull List<Runnable> tasks) {
if (qualifiedName.getFqName().endsWith(JvmAbi.TRAIT_IMPL_SUFFIX)) { if (qualifiedName.getFqName().endsWith(JvmAbi.TRAIT_IMPL_SUFFIX)) {
// TODO: only if -$$TImpl class is created by Kotlin // TODO: only if -$$TImpl class is created by Kotlin
@@ -603,10 +608,10 @@ public class JavaDescriptorResolver {
@NotNull @NotNull
private final TypeVariableResolver typeVariableResolver; private final TypeVariableResolver typeVariableResolver;
@NotNull @NotNull
private final TypeParameterDescriptor typeParameterDescriptor; private final TypeParameterDescriptorImpl typeParameterDescriptor;
protected JetSignatureTypeParameterVisitor(PsiTypeParameterListOwner psiOwner, protected JetSignatureTypeParameterVisitor(PsiTypeParameterListOwner psiOwner,
String name, TypeVariableResolver typeVariableResolver, TypeParameterDescriptor typeParameterDescriptor) String name, TypeVariableResolver typeVariableResolver, TypeParameterDescriptorImpl typeParameterDescriptor)
{ {
if (name.isEmpty()) { if (name.isEmpty()) {
throw new IllegalStateException(); throw new IllegalStateException();
@@ -682,7 +687,7 @@ public class JavaDescriptorResolver {
@Override @Override
public JetSignatureVisitor visitFormalTypeParameter(final String name, final TypeInfoVariance variance, boolean reified) { public JetSignatureVisitor visitFormalTypeParameter(final String name, final TypeInfoVariance variance, boolean reified) {
TypeParameterDescriptor typeParameter = TypeParameterDescriptor.createForFurtherModification( TypeParameterDescriptorImpl typeParameter = TypeParameterDescriptorImpl.createForFurtherModification(
containingDeclaration, containingDeclaration,
Collections.<AnnotationDescriptor>emptyList(), // TODO: wrong Collections.<AnnotationDescriptor>emptyList(), // TODO: wrong
reified, reified,
@@ -757,7 +762,7 @@ public class JavaDescriptorResolver {
@NotNull @NotNull
private TypeParameterDescriptorInitialization makeUninitializedTypeParameter(@NotNull DeclarationDescriptor containingDeclaration, @NotNull PsiTypeParameter psiTypeParameter) { private TypeParameterDescriptorInitialization makeUninitializedTypeParameter(@NotNull DeclarationDescriptor containingDeclaration, @NotNull PsiTypeParameter psiTypeParameter) {
TypeParameterDescriptor typeParameterDescriptor = TypeParameterDescriptor.createForFurtherModification( TypeParameterDescriptorImpl typeParameterDescriptor = TypeParameterDescriptorImpl.createForFurtherModification(
containingDeclaration, containingDeclaration,
Collections.<AnnotationDescriptor>emptyList(), // TODO Collections.<AnnotationDescriptor>emptyList(), // TODO
false, false,
@@ -769,7 +774,7 @@ public class JavaDescriptorResolver {
} }
private void initializeTypeParameter(TypeParameterDescriptorInitialization typeParameter, TypeVariableResolver typeVariableByPsiResolver) { private void initializeTypeParameter(TypeParameterDescriptorInitialization typeParameter, TypeVariableResolver typeVariableByPsiResolver) {
TypeParameterDescriptor typeParameterDescriptor = typeParameter.descriptor; TypeParameterDescriptorImpl typeParameterDescriptor = typeParameter.descriptor;
if (typeParameter.origin == TypeParameterDescriptorOrigin.KOTLIN) { if (typeParameter.origin == TypeParameterDescriptorOrigin.KOTLIN) {
List<?> upperBounds = typeParameter.upperBoundsForKotlin; List<?> upperBounds = typeParameter.upperBoundsForKotlin;
if (upperBounds.size() == 0){ if (upperBounds.size() == 0){
@@ -947,6 +952,11 @@ public class JavaDescriptorResolver {
return scopeData.namespaceDescriptor; return scopeData.namespaceDescriptor;
} }
@Override
public NamespaceDescriptor resolveNamespace(@NotNull FqName qualifiedName) {
return resolveNamespace(qualifiedName, DescriptorSearchRule.ERROR_IF_FOUND_IN_KOTLIN);
}
private NamespaceDescriptorParent resolveParentNamespace(FqName fqName) { private NamespaceDescriptorParent resolveParentNamespace(FqName fqName) {
if (fqName.isRoot()) { if (fqName.isRoot()) {
return FAKE_ROOT_MODULE; return FAKE_ROOT_MODULE;
@@ -17,7 +17,6 @@
package org.jetbrains.jet.lang.resolve.java; package org.jetbrains.jet.lang.resolve.java;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassOrNamespaceDescriptor; import org.jetbrains.jet.lang.descriptors.ClassOrNamespaceDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
@@ -17,12 +17,7 @@
package org.jetbrains.jet.lang.resolve.java; package org.jetbrains.jet.lang.resolve.java;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.ClassOrNamespaceDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -20,7 +20,6 @@ import com.google.common.base.Predicate;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.BodiesResolveContext; import org.jetbrains.jet.lang.resolve.BodiesResolveContext;
@@ -35,13 +34,11 @@ public interface AnalyzerFacade {
@NotNull @NotNull
AnalyzeExhaust analyzeFiles(@NotNull Project project, AnalyzeExhaust analyzeFiles(@NotNull Project project,
@NotNull Collection<JetFile> files, @NotNull Collection<JetFile> files,
@NotNull Predicate<PsiFile> filesToAnalyzeCompletely, @NotNull Predicate<PsiFile> filesToAnalyzeCompletely);
@NotNull JetControlFlowDataTraceFactory flowDataTraceFactory);
@NotNull @NotNull
AnalyzeExhaust analyzeBodiesInFiles(@NotNull Project project, AnalyzeExhaust analyzeBodiesInFiles(@NotNull Project project,
@NotNull Predicate<PsiFile> filesForBodiesResolve, @NotNull Predicate<PsiFile> filesForBodiesResolve,
@NotNull JetControlFlowDataTraceFactory flowDataTraceFactory,
@NotNull BindingTrace traceContext, @NotNull BindingTrace traceContext,
@NotNull BodiesResolveContext bodiesResolveContext); @NotNull BodiesResolveContext bodiesResolveContext);
} }
@@ -17,16 +17,36 @@
package org.jetbrains.jet.di; package org.jetbrains.jet.di;
import org.jetbrains.jet.lang.resolve.TopDownAnalyzer;
import org.jetbrains.jet.lang.resolve.TopDownAnalysisContext;
import org.jetbrains.jet.lang.resolve.BodyResolver;
import org.jetbrains.jet.lang.resolve.ControlFlowAnalyzer;
import org.jetbrains.jet.lang.resolve.DeclarationsChecker;
import org.jetbrains.jet.lang.resolve.DescriptorResolver;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.resolve.TopDownAnalysisParameters;
import org.jetbrains.jet.lang.ModuleConfiguration; import org.jetbrains.jet.lang.resolve.ObservableBindingTrace;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.ModuleConfiguration;
import org.jetbrains.jet.lang.resolve.DeclarationResolver;
import org.jetbrains.jet.lang.resolve.AnnotationResolver;
import org.jetbrains.jet.lang.resolve.calls.CallResolver; import org.jetbrains.jet.lang.resolve.calls.CallResolver;
import org.jetbrains.jet.lang.resolve.calls.OverloadingConflictResolver;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
import org.jetbrains.jet.lang.resolve.TypeResolver;
import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver;
import org.jetbrains.jet.lang.resolve.calls.OverloadingConflictResolver;
import org.jetbrains.jet.lang.resolve.ImportsResolver;
import org.jetbrains.jet.lang.resolve.DelegationResolver;
import org.jetbrains.jet.lang.resolve.NamespaceFactoryImpl;
import org.jetbrains.jet.lang.resolve.OverloadResolver;
import org.jetbrains.jet.lang.resolve.OverrideResolver;
import org.jetbrains.jet.lang.resolve.TypeHierarchyResolver;
import com.intellij.openapi.project.Project;
import org.jetbrains.jet.lang.resolve.TopDownAnalysisParameters;
import org.jetbrains.jet.lang.resolve.ObservableBindingTrace;
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
import org.jetbrains.jet.lang.ModuleConfiguration;
import org.jetbrains.annotations.NotNull;
import javax.annotation.PreDestroy; import javax.annotation.PreDestroy;
/* This file is generated by org.jetbrains.jet.di.AllInjectorsGenerator. DO NOT EDIT! */ /* This file is generated by org.jetbrains.jet.di.AllInjectorsGenerator. DO NOT EDIT! */
@@ -42,7 +62,6 @@ public class InjectorForTopDownAnalyzerBasic {
private final TopDownAnalysisParameters topDownAnalysisParameters; private final TopDownAnalysisParameters topDownAnalysisParameters;
private final ObservableBindingTrace observableBindingTrace; private final ObservableBindingTrace observableBindingTrace;
private final ModuleDescriptor moduleDescriptor; private final ModuleDescriptor moduleDescriptor;
private final JetControlFlowDataTraceFactory jetControlFlowDataTraceFactory;
private final ModuleConfiguration moduleConfiguration; private final ModuleConfiguration moduleConfiguration;
private DeclarationResolver declarationResolver; private DeclarationResolver declarationResolver;
private AnnotationResolver annotationResolver; private AnnotationResolver annotationResolver;
@@ -63,7 +82,6 @@ public class InjectorForTopDownAnalyzerBasic {
@NotNull TopDownAnalysisParameters topDownAnalysisParameters, @NotNull TopDownAnalysisParameters topDownAnalysisParameters,
@NotNull ObservableBindingTrace observableBindingTrace, @NotNull ObservableBindingTrace observableBindingTrace,
@NotNull ModuleDescriptor moduleDescriptor, @NotNull ModuleDescriptor moduleDescriptor,
JetControlFlowDataTraceFactory jetControlFlowDataTraceFactory,
@NotNull ModuleConfiguration moduleConfiguration @NotNull ModuleConfiguration moduleConfiguration
) { ) {
this.topDownAnalyzer = new TopDownAnalyzer(); this.topDownAnalyzer = new TopDownAnalyzer();
@@ -76,7 +94,6 @@ public class InjectorForTopDownAnalyzerBasic {
this.topDownAnalysisParameters = topDownAnalysisParameters; this.topDownAnalysisParameters = topDownAnalysisParameters;
this.observableBindingTrace = observableBindingTrace; this.observableBindingTrace = observableBindingTrace;
this.moduleDescriptor = moduleDescriptor; this.moduleDescriptor = moduleDescriptor;
this.jetControlFlowDataTraceFactory = jetControlFlowDataTraceFactory;
this.moduleConfiguration = moduleConfiguration; this.moduleConfiguration = moduleConfiguration;
this.declarationResolver = new DeclarationResolver(); this.declarationResolver = new DeclarationResolver();
this.annotationResolver = new AnnotationResolver(); this.annotationResolver = new AnnotationResolver();
@@ -114,7 +131,6 @@ public class InjectorForTopDownAnalyzerBasic {
this.bodyResolver.setTopDownAnalysisParameters(topDownAnalysisParameters); this.bodyResolver.setTopDownAnalysisParameters(topDownAnalysisParameters);
this.bodyResolver.setTrace(observableBindingTrace); this.bodyResolver.setTrace(observableBindingTrace);
this.controlFlowAnalyzer.setFlowDataTraceFactory(jetControlFlowDataTraceFactory);
this.controlFlowAnalyzer.setTopDownAnalysisParameters(topDownAnalysisParameters); this.controlFlowAnalyzer.setTopDownAnalysisParameters(topDownAnalysisParameters);
this.controlFlowAnalyzer.setTrace(observableBindingTrace); this.controlFlowAnalyzer.setTrace(observableBindingTrace);
@@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.cfg;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import java.util.List; import java.util.List;
@@ -64,7 +65,7 @@ public interface JetControlFlowBuilder {
// Subroutines // Subroutines
void enterSubroutine(@NotNull JetDeclaration subroutine); void enterSubroutine(@NotNull JetDeclaration subroutine);
void exitSubroutine(@NotNull JetDeclaration subroutine); Pseudocode exitSubroutine(@NotNull JetDeclaration subroutine);
@NotNull @NotNull
JetElement getCurrentSubroutine(); JetElement getCurrentSubroutine();
@@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.cfg;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import java.util.List; import java.util.List;
@@ -157,9 +158,9 @@ public class JetControlFlowBuilderAdapter implements JetControlFlowBuilder {
} }
@Override @Override
public void exitSubroutine(@NotNull JetDeclaration subroutine) { public Pseudocode exitSubroutine(@NotNull JetDeclaration subroutine) {
assert builder != null; assert builder != null;
builder.exitSubroutine(subroutine); return builder.exitSubroutine(subroutine);
} }
@NotNull @NotNull
@@ -1,180 +0,0 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.cfg;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.pseudocode.*;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* @author svtk
*/
public class JetControlFlowGraphTraverser<D> {
private final Pseudocode pseudocode;
private final boolean lookInside;
private final boolean straightDirection;
private final Map<Instruction, Pair<D, D>> dataMap = Maps.newLinkedHashMap();
public static <D> JetControlFlowGraphTraverser<D> create(@NotNull Pseudocode pseudocode, boolean lookInside, boolean straightDirection) {
return new JetControlFlowGraphTraverser<D>(pseudocode, lookInside, straightDirection);
}
private JetControlFlowGraphTraverser(@NotNull Pseudocode pseudocode, boolean lookInside, boolean straightDirection) {
this.pseudocode = pseudocode;
this.lookInside = lookInside;
this.straightDirection = straightDirection;
}
@NotNull
private Instruction getStartInstruction(@NotNull Pseudocode pseudocode) {
return straightDirection ? pseudocode.getEnterInstruction() : pseudocode.getSinkInstruction();
}
public void collectInformationFromInstructionGraph(
@NotNull D initialDataValue,
@NotNull D initialDataValueForEnterInstruction,
@NotNull InstructionDataMergeStrategy<D> instructionDataMergeStrategy) {
initializeDataMap(pseudocode, initialDataValue);
dataMap.put(getStartInstruction(pseudocode),
Pair.create(initialDataValueForEnterInstruction, initialDataValueForEnterInstruction));
boolean[] changed = new boolean[1];
changed[0] = true;
while (changed[0]) {
changed[0] = false;
traverseSubGraph(pseudocode, instructionDataMergeStrategy, Collections.<Instruction>emptyList(), changed, false);
}
}
private void initializeDataMap(
@NotNull Pseudocode pseudocode,
@NotNull D initialDataValue) {
List<Instruction> instructions = pseudocode.getInstructions();
Pair<D, D> initialPair = Pair.create(initialDataValue, initialDataValue);
for (Instruction instruction : instructions) {
dataMap.put(instruction, initialPair);
if (lookInside && instruction instanceof LocalDeclarationInstruction) {
initializeDataMap(((LocalDeclarationInstruction) instruction).getBody(), initialDataValue);
}
}
}
private void traverseSubGraph(
@NotNull Pseudocode pseudocode,
@NotNull InstructionDataMergeStrategy<D> instructionDataMergeStrategy,
@NotNull Collection<Instruction> previousSubGraphInstructions,
boolean[] changed,
boolean isLocal) {
List<Instruction> instructions = pseudocode.getInstructions();
Instruction startInstruction = getStartInstruction(pseudocode);
if (!straightDirection) {
instructions = Lists.newArrayList(instructions);
Collections.reverse(instructions);
}
for (Instruction instruction : instructions) {
boolean isStart = straightDirection ? instruction instanceof SubroutineEnterInstruction : instruction instanceof SubroutineSinkInstruction;
if (!isLocal && isStart) continue;
Collection<Instruction> allPreviousInstructions;
Collection<Instruction> previousInstructions = straightDirection
? instruction.getPreviousInstructions()
: instruction.getNextInstructions();
if (instruction == startInstruction && !previousSubGraphInstructions.isEmpty()) {
allPreviousInstructions = Lists.newArrayList(previousInstructions);
allPreviousInstructions.addAll(previousSubGraphInstructions);
}
else {
allPreviousInstructions = previousInstructions;
}
if (lookInside && instruction instanceof LocalDeclarationInstruction) {
Pseudocode subroutinePseudocode = ((LocalDeclarationInstruction) instruction).getBody();
traverseSubGraph(subroutinePseudocode, instructionDataMergeStrategy, previousInstructions, changed, true);
Instruction lastInstruction = straightDirection ? subroutinePseudocode.getSinkInstruction() : subroutinePseudocode.getEnterInstruction();
Pair<D, D> previousValue = dataMap.get(instruction);
Pair<D, D> newValue = dataMap.get(lastInstruction);
if (!previousValue.equals(newValue)) {
changed[0] = true;
dataMap.put(instruction, newValue);
}
continue;
}
Pair<D, D> previousDataValue = dataMap.get(instruction);
Collection<D> incomingEdgesData = Sets.newHashSet();
for (Instruction previousInstruction : allPreviousInstructions) {
Pair<D, D> previousData = dataMap.get(previousInstruction);
if (previousData != null) {
incomingEdgesData.add(previousData.getSecond());
}
}
Pair<D, D> mergedData = instructionDataMergeStrategy.execute(instruction, incomingEdgesData);
if (!mergedData.equals(previousDataValue)) {
changed[0] = true;
dataMap.put(instruction, mergedData);
}
}
}
public void traverseAndAnalyzeInstructionGraph(
@NotNull InstructionDataAnalyzeStrategy<D> instructionDataAnalyzeStrategy) {
traverseAndAnalyzeInstructionGraph(pseudocode, instructionDataAnalyzeStrategy);
}
private void traverseAndAnalyzeInstructionGraph(
@NotNull Pseudocode pseudocode,
@NotNull InstructionDataAnalyzeStrategy<D> instructionDataAnalyzeStrategy) {
List<Instruction> instructions = pseudocode.getInstructions();
if (!straightDirection) {
instructions = Lists.newArrayList(instructions);
Collections.reverse(instructions);
}
for (Instruction instruction : instructions) {
if (lookInside && instruction instanceof LocalDeclarationInstruction) {
traverseAndAnalyzeInstructionGraph(((LocalDeclarationInstruction) instruction).getBody(), instructionDataAnalyzeStrategy);
}
Pair<D, D> pair = dataMap.get(instruction);
instructionDataAnalyzeStrategy.execute(instruction,
pair != null ? pair.getFirst() : null,
pair != null ? pair.getSecond() : null);
}
}
public D getResultInfo() {
return dataMap.get(pseudocode.getExitInstruction()).getFirst();
}
interface InstructionDataMergeStrategy<D> {
Pair<D, D> execute(@NotNull Instruction instruction, @NotNull Collection<D> incomingEdgesData);
}
interface InstructionDataAnalyzeStrategy<D> {
void execute(@NotNull Instruction instruction, @Nullable D enterData, @Nullable D exitData);
}
}
@@ -21,6 +21,10 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.pseudocode.LocalDeclarationInstruction;
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowInstructionsGenerator;
import org.jetbrains.jet.lang.cfg.pseudocode.PseudocodeImpl;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.BindingContextUtils;
@@ -45,12 +49,21 @@ public class JetControlFlowProcessor {
private final JetControlFlowBuilder builder; private final JetControlFlowBuilder builder;
private final BindingTrace trace; private final BindingTrace trace;
public JetControlFlowProcessor(BindingTrace trace, JetControlFlowBuilder builder) { public JetControlFlowProcessor(BindingTrace trace) {
this.builder = builder; this.builder = new JetControlFlowInstructionsGenerator();
this.trace = trace; this.trace = trace;
} }
public void generate(@NotNull JetDeclaration subroutine) { public Pseudocode generatePseudocode(@NotNull JetDeclaration subroutine) {
Pseudocode pseudocode = generate(subroutine);
((PseudocodeImpl)pseudocode).postProcess();
for (LocalDeclarationInstruction localDeclarationInstruction : pseudocode.getLocalDeclarations()) {
((PseudocodeImpl)localDeclarationInstruction.getBody()).postProcess();
}
return pseudocode;
}
private Pseudocode generate(@NotNull JetDeclaration subroutine) {
builder.enterSubroutine(subroutine); builder.enterSubroutine(subroutine);
if (subroutine instanceof JetDeclarationWithBody) { if (subroutine instanceof JetDeclarationWithBody) {
JetDeclarationWithBody declarationWithBody = (JetDeclarationWithBody) subroutine; JetDeclarationWithBody declarationWithBody = (JetDeclarationWithBody) subroutine;
@@ -67,7 +80,7 @@ public class JetControlFlowProcessor {
else { else {
subroutine.accept(new CFPVisitor(false)); subroutine.accept(new CFPVisitor(false));
} }
builder.exitSubroutine(subroutine); return builder.exitSubroutine(subroutine);
} }
private void processLocalDeclaration(@NotNull JetDeclaration subroutine) { private void processLocalDeclaration(@NotNull JetDeclaration subroutine) {
@@ -17,15 +17,16 @@
package org.jetbrains.jet.lang.cfg; package org.jetbrains.jet.lang.cfg;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.pseudocode.*; import org.jetbrains.jet.lang.cfg.pseudocode.*;
import org.jetbrains.jet.lang.cfg.PseudocodeTraverser.*;
import org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableInitState;
import org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableUseState;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.diagnostics.Errors; import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
@@ -33,13 +34,14 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.plugin.JetMainDetector; import org.jetbrains.jet.plugin.JetMainDetector;
import java.util.*; import java.util.*;
import static org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableUseState.*;
import static org.jetbrains.jet.lang.diagnostics.Errors.*; import static org.jetbrains.jet.lang.diagnostics.Errors.*;
import static org.jetbrains.jet.lang.resolve.BindingContext.CAPTURED_IN_CLOSURE; import static org.jetbrains.jet.lang.resolve.BindingContext.CAPTURED_IN_CLOSURE;
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE; import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
@@ -49,52 +51,22 @@ import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
*/ */
public class JetFlowInformationProvider { public class JetFlowInformationProvider {
private final Map<JetElement, Pseudocode> pseudocodeMap; private final JetDeclaration subroutine;
private final Pseudocode pseudocode;
private final PseudocodeVariablesData pseudocodeVariablesData;
private BindingTrace trace; private BindingTrace trace;
public JetFlowInformationProvider(@NotNull JetDeclaration declaration, @NotNull final JetExpression bodyExpression, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory, @NotNull BindingTrace trace) { public JetFlowInformationProvider(
@NotNull JetDeclaration declaration,
@NotNull BindingTrace trace) {
subroutine = declaration;
this.trace = trace; this.trace = trace;
final JetPseudocodeTrace pseudocodeTrace = flowDataTraceFactory.createTrace(declaration); pseudocode = new JetControlFlowProcessor(trace).generatePseudocode(declaration);
pseudocodeMap = new HashMap<JetElement, Pseudocode>(); pseudocodeVariablesData = new PseudocodeVariablesData(pseudocode, trace.getBindingContext());
final Map<JetElement, Instruction> representativeInstructions = new HashMap<JetElement, Instruction>();
final Map<JetExpression, LoopInfo> loopInfo = Maps.newHashMap();
JetPseudocodeTrace wrappedTrace = new JetPseudocodeTrace() {
@Override
public void recordControlFlowData(@NotNull JetElement element, @NotNull Pseudocode pseudocode) {
pseudocodeTrace.recordControlFlowData(element, pseudocode);
pseudocodeMap.put(element, pseudocode);
}
@Override
public void recordRepresentativeInstruction(@NotNull JetElement element, @NotNull Instruction instruction) {
Instruction oldValue = representativeInstructions.put(element, instruction);
// assert oldValue == null : element.getText();
pseudocodeTrace.recordRepresentativeInstruction(element, instruction);
}
@Override
public void recordLoopInfo(JetExpression expression, LoopInfo blockInfo) {
loopInfo.put(expression, blockInfo);
pseudocodeTrace.recordLoopInfo(expression, blockInfo);
}
@Override
public void close() {
pseudocodeTrace.close();
for (Pseudocode pseudocode : pseudocodeMap.values()) {
pseudocode.postProcess();
}
}
};
JetControlFlowInstructionsGenerator instructionsGenerator = new JetControlFlowInstructionsGenerator(wrappedTrace);
new JetControlFlowProcessor(trace, instructionsGenerator).generate(declaration);
wrappedTrace.close();
} }
private void collectReturnExpressions(@NotNull JetElement subroutine, @NotNull final Collection<JetElement> returnedExpressions) { private void collectReturnExpressions(@NotNull final Collection<JetElement> returnedExpressions) {
Pseudocode pseudocode = pseudocodeMap.get(subroutine);
assert pseudocode != null;
final Set<Instruction> instructions = Sets.newHashSet(pseudocode.getInstructions()); final Set<Instruction> instructions = Sets.newHashSet(pseudocode.getInstructions());
SubroutineExitInstruction exitInstruction = pseudocode.getExitInstruction(); SubroutineExitInstruction exitInstruction = pseudocode.getExitInstruction();
for (Instruction previousInstruction : exitInstruction.getPreviousInstructions()) { for (Instruction previousInstruction : exitInstruction.getPreviousInstructions()) {
@@ -149,14 +121,15 @@ public class JetFlowInformationProvider {
} }
} }
public void checkDefiniteReturn(@NotNull final JetDeclarationWithBody function, final @NotNull JetType expectedReturnType) { public void checkDefiniteReturn(final @NotNull JetType expectedReturnType) {
assert function instanceof JetDeclaration; assert subroutine instanceof JetDeclarationWithBody;
JetDeclarationWithBody function = (JetDeclarationWithBody) subroutine;
JetExpression bodyExpression = function.getBodyExpression(); JetExpression bodyExpression = function.getBodyExpression();
if (bodyExpression == null) return; if (bodyExpression == null) return;
List<JetElement> returnedExpressions = Lists.newArrayList(); List<JetElement> returnedExpressions = Lists.newArrayList();
collectReturnExpressions(function.asElement(), returnedExpressions); collectReturnExpressions(returnedExpressions);
boolean nothingReturned = returnedExpressions.isEmpty(); boolean nothingReturned = returnedExpressions.isEmpty();
@@ -167,7 +140,7 @@ public class JetFlowInformationProvider {
} }
final boolean blockBody = function.hasBlockBody(); final boolean blockBody = function.hasBlockBody();
final Set<JetElement> rootUnreachableElements = collectUnreachableCode(function.asElement()); final Set<JetElement> rootUnreachableElements = collectUnreachableCode();
for (JetElement element : rootUnreachableElements) { for (JetElement element : rootUnreachableElements) {
trace.report(UNREACHABLE_CODE.on(element)); trace.report(UNREACHABLE_CODE.on(element));
} }
@@ -195,10 +168,7 @@ public class JetFlowInformationProvider {
} }
} }
private Set<JetElement> collectUnreachableCode(@NotNull JetElement subroutine) { private Set<JetElement> collectUnreachableCode() {
Pseudocode pseudocode = pseudocodeMap.get(subroutine);
assert pseudocode != null;
Collection<JetElement> unreachableElements = Lists.newArrayList(); Collection<JetElement> unreachableElements = Lists.newArrayList();
for (Instruction deadInstruction : pseudocode.getDeadInstructions()) { for (Instruction deadInstruction : pseudocode.getDeadInstructions()) {
if (deadInstruction instanceof JetElementInstruction && if (deadInstruction instanceof JetElementInstruction &&
@@ -213,73 +183,61 @@ public class JetFlowInformationProvider {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Uninitialized variables analysis // Uninitialized variables analysis
public void markUninitializedVariables(@NotNull JetElement subroutine, final boolean processLocalDeclaration) { public void markUninitializedVariables(final boolean processLocalDeclaration) {
final Pseudocode pseudocode = pseudocodeMap.get(subroutine);
assert pseudocode != null;
JetControlFlowGraphTraverser<Map<VariableDescriptor, VariableInitializers>> traverser = JetControlFlowGraphTraverser.create(pseudocode, false, true);
Collection<VariableDescriptor> usedVariables = collectUsedVariables(pseudocode);
final Collection<VariableDescriptor> declaredVariables = collectDeclaredVariables(subroutine);
Map<VariableDescriptor, VariableInitializers> initialMapForStartInstruction = prepareInitialMapForStartInstruction(usedVariables, declaredVariables);
traverser.collectInformationFromInstructionGraph(Collections.<VariableDescriptor, VariableInitializers>emptyMap(), initialMapForStartInstruction,
new JetControlFlowGraphTraverser.InstructionDataMergeStrategy<Map<VariableDescriptor, VariableInitializers>>() {
@Override
public Pair<Map<VariableDescriptor, VariableInitializers>, Map<VariableDescriptor, VariableInitializers>> execute(
@NotNull Instruction instruction,
@NotNull Collection<Map<VariableDescriptor, VariableInitializers>> incomingEdgesData) {
Map<VariableDescriptor, VariableInitializers> enterInstructionData = mergeIncomingEdgesData(incomingEdgesData);
Map<VariableDescriptor, VariableInitializers> exitInstructionData = addVariableInitializerFromCurrentInstructionIfAny(instruction, enterInstructionData);
return Pair.create(enterInstructionData, exitInstructionData);
}
});
final Collection<VariableDescriptor> varWithUninitializedErrorGenerated = Sets.newHashSet(); final Collection<VariableDescriptor> varWithUninitializedErrorGenerated = Sets.newHashSet();
final Collection<VariableDescriptor> varWithValReassignErrorGenerated = Sets.newHashSet(); final Collection<VariableDescriptor> varWithValReassignErrorGenerated = Sets.newHashSet();
final boolean processClassOrObject = subroutine instanceof JetClassOrObject; final boolean processClassOrObject = subroutine instanceof JetClassOrObject;
traverser.traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy<Map<VariableDescriptor, VariableInitializers>>() {
Map<Instruction, Edges<Map<VariableDescriptor,VariableInitState>>> initializers = pseudocodeVariablesData.getVariableInitializers();
final Set<VariableDescriptor> declaredVariables = pseudocodeVariablesData.getDeclaredVariables(pseudocode);
PseudocodeTraverser.traverse(pseudocode, true, true, initializers, new InstructionDataAnalyzeStrategy<Map<VariableDescriptor, PseudocodeVariablesData.VariableInitState>>() {
@Override @Override
public void execute(@NotNull Instruction instruction, @Nullable Map<VariableDescriptor, VariableInitializers> enterData, @Nullable Map<VariableDescriptor, VariableInitializers> exitData) { public void execute(@NotNull Instruction instruction,
assert enterData != null && exitData != null; @Nullable Map<VariableDescriptor, VariableInitState> in,
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, true); @Nullable Map<VariableDescriptor, PseudocodeVariablesData.VariableInitState> out) {
assert in != null && out != null;
VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, true, trace.getBindingContext());
if (variableDescriptor == null) return; if (variableDescriptor == null) return;
if (!(instruction instanceof ReadValueInstruction) && !(instruction instanceof WriteValueInstruction)) return;
VariableInitState outInitState = out.get(variableDescriptor);
if (instruction instanceof ReadValueInstruction) { if (instruction instanceof ReadValueInstruction) {
JetElement element = ((ReadValueInstruction) instruction).getElement(); JetElement element = ((ReadValueInstruction) instruction).getElement();
boolean error = checkBackingField(variableDescriptor, element); boolean error = checkBackingField(variableDescriptor, element);
if (!error && declaredVariables.contains(variableDescriptor)) { if (!error && declaredVariables.contains(variableDescriptor)) {
checkIsInitialized(variableDescriptor, element, exitData.get(variableDescriptor), varWithUninitializedErrorGenerated); checkIsInitialized(variableDescriptor, element, outInitState, varWithUninitializedErrorGenerated);
} }
return;
} }
else if (instruction instanceof WriteValueInstruction) { JetElement element = ((WriteValueInstruction) instruction).getlValue();
JetElement element = ((WriteValueInstruction) instruction).getlValue(); boolean error = checkBackingField(variableDescriptor, element);
boolean error = checkBackingField(variableDescriptor, element); if (!(element instanceof JetExpression)) return;
if (!(element instanceof JetExpression)) return; PseudocodeVariablesData.VariableInitState inInitState = in.get(variableDescriptor);
if (!error && !processLocalDeclaration) { // error has been generated before, while processing outer function of this local declaration if (!error && !processLocalDeclaration) { // error has been generated before, while processing outer function of this local declaration
error = checkValReassignment(variableDescriptor, (JetExpression) element, enterData.get(variableDescriptor), varWithValReassignErrorGenerated); error = checkValReassignment(variableDescriptor, (JetExpression) element, inInitState, varWithValReassignErrorGenerated);
} }
if (!error && processClassOrObject) { if (!error && processClassOrObject) {
error = checkAssignmentBeforeDeclaration(variableDescriptor, (JetExpression) element, enterData.get(variableDescriptor), exitData.get(variableDescriptor)); error = checkAssignmentBeforeDeclaration(variableDescriptor, (JetExpression) element, inInitState, outInitState);
} }
if (!error && processClassOrObject) { if (!error && processClassOrObject) {
checkInitializationUsingBackingField(variableDescriptor, (JetExpression) element, enterData.get(variableDescriptor), exitData.get(variableDescriptor)); checkInitializationUsingBackingField(variableDescriptor, (JetExpression) element, inInitState, outInitState);
}
} }
} }
}); });
recordInitializedVariables(declaredVariables, traverser.getResultInfo()); Pseudocode pseudocode = pseudocodeVariablesData.getPseudocode();
analyzeLocalDeclarations(pseudocode, processLocalDeclaration); recordInitializedVariables(pseudocode, initializers);
for (LocalDeclarationInstruction instruction : pseudocode.getLocalDeclarations()) {
recordInitializedVariables(instruction.getBody(), initializers);
}
} }
private void checkIsInitialized(@NotNull VariableDescriptor variableDescriptor, private void checkIsInitialized(@NotNull VariableDescriptor variableDescriptor,
@NotNull JetElement element, @NotNull JetElement element,
@NotNull VariableInitializers variableInitializers, @NotNull PseudocodeVariablesData.VariableInitState variableInitState,
@NotNull Collection<VariableDescriptor> varWithUninitializedErrorGenerated) { @NotNull Collection<VariableDescriptor> varWithUninitializedErrorGenerated) {
if (!(element instanceof JetSimpleNameExpression)) return; if (!(element instanceof JetSimpleNameExpression)) return;
boolean isInitialized = variableInitializers.isInitialized(); boolean isInitialized = variableInitState.isInitialized;
if (variableDescriptor instanceof PropertyDescriptor) { if (variableDescriptor instanceof PropertyDescriptor) {
if (!trace.get(BindingContext.BACKING_FIELD_REQUIRED, (PropertyDescriptor) variableDescriptor)) { if (!trace.get(BindingContext.BACKING_FIELD_REQUIRED, (PropertyDescriptor) variableDescriptor)) {
isInitialized = true; isInitialized = true;
@@ -288,7 +246,8 @@ public class JetFlowInformationProvider {
if (!isInitialized && !varWithUninitializedErrorGenerated.contains(variableDescriptor)) { if (!isInitialized && !varWithUninitializedErrorGenerated.contains(variableDescriptor)) {
varWithUninitializedErrorGenerated.add(variableDescriptor); varWithUninitializedErrorGenerated.add(variableDescriptor);
if (variableDescriptor instanceof ValueParameterDescriptor) { if (variableDescriptor instanceof ValueParameterDescriptor) {
trace.report(Errors.UNINITIALIZED_PARAMETER.on((JetSimpleNameExpression) element, (ValueParameterDescriptor) variableDescriptor)); trace.report(Errors.UNINITIALIZED_PARAMETER.on((JetSimpleNameExpression) element,
(ValueParameterDescriptor) variableDescriptor));
} }
else { else {
trace.report(Errors.UNINITIALIZED_VARIABLE.on((JetSimpleNameExpression) element, variableDescriptor)); trace.report(Errors.UNINITIALIZED_VARIABLE.on((JetSimpleNameExpression) element, variableDescriptor));
@@ -298,15 +257,11 @@ public class JetFlowInformationProvider {
private boolean checkValReassignment(@NotNull VariableDescriptor variableDescriptor, private boolean checkValReassignment(@NotNull VariableDescriptor variableDescriptor,
@NotNull JetExpression expression, @NotNull JetExpression expression,
@NotNull VariableInitializers enterInitializers, @NotNull VariableInitState enterInitState,
@NotNull Collection<VariableDescriptor> varWithValReassignErrorGenerated) { @NotNull Collection<VariableDescriptor> varWithValReassignErrorGenerated) {
boolean isInitializedNotHere = enterInitializers.isInitialized(); boolean isInitializedNotHere = enterInitState.isInitialized;
Set<JetElement> possibleLocalInitializers = enterInitializers.getPossibleLocalInitializers(); if (expression.getParent() instanceof JetProperty && ((JetProperty)expression).getInitializer() != null) {
if (possibleLocalInitializers.size() == 1) { isInitializedNotHere = false;
JetElement initializer = possibleLocalInitializers.iterator().next();
if (initializer instanceof JetProperty && initializer == expression.getParent()) {
isInitializedNotHere = false;
}
} }
boolean hasBackingField = true; boolean hasBackingField = true;
if (variableDescriptor instanceof PropertyDescriptor) { if (variableDescriptor instanceof PropertyDescriptor) {
@@ -349,16 +304,16 @@ public class JetFlowInformationProvider {
return false; return false;
} }
private boolean checkAssignmentBeforeDeclaration(@NotNull VariableDescriptor variableDescriptor, @NotNull JetExpression expression, @NotNull VariableInitializers enterInitializers, @NotNull VariableInitializers exitInitializers) { private boolean checkAssignmentBeforeDeclaration(@NotNull VariableDescriptor variableDescriptor, @NotNull JetExpression expression, @NotNull VariableInitState enterInitState, @NotNull VariableInitState exitInitState) {
if (!enterInitializers.isDeclared() && !exitInitializers.isDeclared() && !enterInitializers.isInitialized() && exitInitializers.isInitialized()) { if (!enterInitState.isDeclared && !exitInitState.isDeclared && !enterInitState.isInitialized && exitInitState.isInitialized) {
trace.report(Errors.INITIALIZATION_BEFORE_DECLARATION.on(expression, variableDescriptor)); trace.report(Errors.INITIALIZATION_BEFORE_DECLARATION.on(expression, variableDescriptor));
return true; return true;
} }
return false; return false;
} }
private boolean checkInitializationUsingBackingField(@NotNull VariableDescriptor variableDescriptor, @NotNull JetExpression expression, @NotNull VariableInitializers enterInitializers, @NotNull VariableInitializers exitInitializers) { private boolean checkInitializationUsingBackingField(@NotNull VariableDescriptor variableDescriptor, @NotNull JetExpression expression, @NotNull VariableInitState enterInitState, @NotNull VariableInitState exitInitState) {
if (variableDescriptor instanceof PropertyDescriptor && !enterInitializers.isInitialized() && exitInitializers.isInitialized()) { if (variableDescriptor instanceof PropertyDescriptor && !enterInitState.isInitialized && exitInitState.isInitialized) {
if (!variableDescriptor.isVar()) return false; if (!variableDescriptor.isVar()) return false;
if (!trace.get(BindingContext.BACKING_FIELD_REQUIRED, (PropertyDescriptor) variableDescriptor)) return false; if (!trace.get(BindingContext.BACKING_FIELD_REQUIRED, (PropertyDescriptor) variableDescriptor)) return false;
PsiElement property = BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), variableDescriptor); PsiElement property = BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), variableDescriptor);
@@ -397,7 +352,9 @@ public class JetFlowInformationProvider {
} }
PsiElement property = BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), variableDescriptor); PsiElement property = BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), variableDescriptor);
boolean insideSelfAccessors = PsiTreeUtil.isAncestor(property, element, false); boolean insideSelfAccessors = PsiTreeUtil.isAncestor(property, element, false);
if (!trace.get(BindingContext.BACKING_FIELD_REQUIRED, (PropertyDescriptor) variableDescriptor) && !insideSelfAccessors) { // not to generate error in accessors of abstract properties, there is one: declared accessor of abstract property if (!trace.get(BindingContext.BACKING_FIELD_REQUIRED, (PropertyDescriptor) variableDescriptor) &&
!insideSelfAccessors) { // not to generate error in accessors of abstract properties, there is one: declared accessor of abstract property
if (((PropertyDescriptor) variableDescriptor).getModality() == Modality.ABSTRACT) { if (((PropertyDescriptor) variableDescriptor).getModality() == Modality.ABSTRACT) {
trace.report(NO_BACKING_FIELD_ABSTRACT_PROPERTY.on(element)); trace.report(NO_BACKING_FIELD_ABSTRACT_PROPERTY.on(element));
} }
@@ -436,173 +393,44 @@ public class JetFlowInformationProvider {
return false; return false;
} }
private void recordInitializedVariables(Collection<VariableDescriptor> declaredVariables, Map<VariableDescriptor, VariableInitializers> resultInfo) { private void recordInitializedVariables(@NotNull Pseudocode pseudocode, @NotNull Map<Instruction, Edges<Map<VariableDescriptor,PseudocodeVariablesData.VariableInitState>>> initializersMap) {
for (Map.Entry<VariableDescriptor, VariableInitializers> entry : resultInfo.entrySet()) { Edges<Map<VariableDescriptor, VariableInitState>> initializers = initializersMap.get(pseudocode.getExitInstruction());
VariableDescriptor variable = entry.getKey(); Set<VariableDescriptor> usedVariables = pseudocodeVariablesData.getUsedVariables(pseudocode);
if (variable instanceof PropertyDescriptor && declaredVariables.contains(variable)) { Set<VariableDescriptor> declaredVariables = pseudocodeVariablesData.getDeclaredVariables(pseudocode);
VariableInitializers initializers = entry.getValue();
trace.record(BindingContext.IS_INITIALIZED, (PropertyDescriptor) variable, initializers.isInitialized());
}
}
}
private void analyzeLocalDeclarations(Pseudocode pseudocode, boolean processLocalDeclaration) {
for (Instruction instruction : pseudocode.getInstructions()) {
if (instruction instanceof LocalDeclarationInstruction) {
JetElement element = ((LocalDeclarationInstruction) instruction).getElement();
markUninitializedVariables(element, processLocalDeclaration);
}
}
}
private Map<VariableDescriptor, VariableInitializers> addVariableInitializerFromCurrentInstructionIfAny(Instruction instruction, Map<VariableDescriptor, VariableInitializers> enterInstructionData) {
Map<VariableDescriptor, VariableInitializers> exitInstructionData = Maps.newHashMap(enterInstructionData);
if (instruction instanceof WriteValueInstruction) {
VariableDescriptor variable = extractVariableDescriptorIfAny(instruction, false);
VariableInitializers enterInitializers = enterInstructionData.get(variable);
VariableInitializers initializationAtThisElement = new VariableInitializers(((WriteValueInstruction) instruction).getElement(), enterInitializers);
exitInstructionData.put(variable, initializationAtThisElement);
}
else if (instruction instanceof VariableDeclarationInstruction) {
VariableDescriptor variable = extractVariableDescriptorIfAny(instruction, false);
VariableInitializers enterInitializers = enterInstructionData.get(variable);
if (enterInitializers == null || !enterInitializers.isInitialized() || !enterInitializers.isDeclared()) {
JetElement element = ((VariableDeclarationInstruction) instruction).getElement();
if (element instanceof JetProperty) {
JetProperty property = (JetProperty) element;
if (property.getInitializer() == null) {
boolean isInitialized = enterInitializers != null && enterInitializers.isInitialized();
VariableInitializers variableDeclarationInfo = new VariableInitializers(isInitialized, true);
exitInstructionData.put(variable, variableDeclarationInfo);
}
}
}
}
return exitInstructionData;
}
private Map<VariableDescriptor, VariableInitializers> mergeIncomingEdgesData(Collection<Map<VariableDescriptor, VariableInitializers>> incomingEdgesData) {
Set<VariableDescriptor> variablesInScope = Sets.newHashSet();
for (Map<VariableDescriptor, VariableInitializers> edgeData : incomingEdgesData) {
variablesInScope.addAll(edgeData.keySet());
}
Map<VariableDescriptor, VariableInitializers> enterInstructionData = Maps.newHashMap();
for (VariableDescriptor variable : variablesInScope) {
Set<VariableInitializers> edgesDataForVariable = Sets.newHashSet();
for (Map<VariableDescriptor, VariableInitializers> edgeData : incomingEdgesData) {
VariableInitializers initializers = edgeData.get(variable);
if (initializers != null) {
edgesDataForVariable.add(initializers);
}
}
enterInstructionData.put(variable, new VariableInitializers(edgesDataForVariable));
}
return enterInstructionData;
}
private Map<VariableDescriptor, VariableInitializers> prepareInitialMapForStartInstruction(Collection<VariableDescriptor> usedVariables, Collection<VariableDescriptor> declaredVariables) {
Map<VariableDescriptor, VariableInitializers> initialMapForStartInstruction = Maps.newHashMap();
VariableInitializers isInitializedForExternalVariable = new VariableInitializers(true);
VariableInitializers isNotInitializedForDeclaredVariable = new VariableInitializers(false);
for (VariableDescriptor variable : usedVariables) { for (VariableDescriptor variable : usedVariables) {
if (declaredVariables.contains(variable)) { if (variable instanceof PropertyDescriptor && declaredVariables.contains(variable)) {
initialMapForStartInstruction.put(variable, isNotInitializedForDeclaredVariable); PseudocodeVariablesData.VariableInitState variableInitState = initializers.in.get(variable);
} if (variableInitState == null) return;
else { trace.record(BindingContext.IS_INITIALIZED, (PropertyDescriptor) variable, variableInitState.isInitialized);
initialMapForStartInstruction.put(variable, isInitializedForExternalVariable);
} }
} }
return initialMapForStartInstruction;
}
////////////////////////////////////////////////////////////////////////////////
public void markNotOnlyInvokedFunctionVariables(@NotNull JetElement subroutine, List<? extends VariableDescriptor> variables) {
final List<VariableDescriptor> functionVariables = Lists.newArrayList();
for (VariableDescriptor variable : variables) {
if (JetStandardClasses.isFunctionType(variable.getReturnType())) {
functionVariables.add(variable);
}
}
Pseudocode pseudocode = pseudocodeMap.get(subroutine);
assert pseudocode != null;
JetControlFlowGraphTraverser.<Void>create(pseudocode, true, true).traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy<Void>() {
@Override
public void execute(@NotNull Instruction instruction, Void enterData, Void exitData) {
if (instruction instanceof ReadValueInstruction) {
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, false);
if (variableDescriptor != null && functionVariables.contains(variableDescriptor)) {
//check that we only invoke this variable
JetElement element = ((ReadValueInstruction) instruction).getElement();
if (element instanceof JetSimpleNameExpression && !(element.getParent() instanceof JetCallExpression)) {
trace.report(Errors.FUNCTION_PARAMETERS_OF_INLINE_FUNCTION.on((JetSimpleNameExpression) element, variableDescriptor));
}
}
}
}
});
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// "Unused variable" & "unused value" analyses // "Unused variable" & "unused value" analyses
public void markUnusedVariables(@NotNull JetElement subroutine) { public void markUnusedVariables() {
Pseudocode pseudocode = pseudocodeMap.get(subroutine); Map<Instruction, Edges<Map<VariableDescriptor, VariableUseState>>> variableStatusData = pseudocodeVariablesData.getVariableUseStatusData();
assert pseudocode != null; InstructionDataAnalyzeStrategy<Map<VariableDescriptor, VariableUseState>> variableStatusAnalyzeStrategy =
JetControlFlowGraphTraverser<Map<VariableDescriptor, VariableStatus>> traverser = JetControlFlowGraphTraverser.create(pseudocode, true, false); new InstructionDataAnalyzeStrategy<Map<VariableDescriptor, PseudocodeVariablesData.VariableUseState>>() {
final Collection<VariableDescriptor> declaredVariables = collectDeclaredVariables(subroutine);
Map<VariableDescriptor, VariableStatus> sinkInstructionData = Maps.newHashMap();
traverser.collectInformationFromInstructionGraph(Collections.<VariableDescriptor, VariableStatus>emptyMap(), sinkInstructionData, new JetControlFlowGraphTraverser.InstructionDataMergeStrategy<Map<VariableDescriptor, VariableStatus>>() {
@Override @Override
public Pair<Map<VariableDescriptor, VariableStatus>, Map<VariableDescriptor, VariableStatus>> execute(@NotNull Instruction instruction, @NotNull Collection<Map<VariableDescriptor, VariableStatus>> incomingEdgesData) { public void execute(@NotNull Instruction instruction,
Map<VariableDescriptor, VariableStatus> enterResult = Maps.newHashMap(); @Nullable Map<VariableDescriptor, PseudocodeVariablesData.VariableUseState> in,
for (Map<VariableDescriptor, VariableStatus> edgeData : incomingEdgesData) { @Nullable Map<VariableDescriptor, VariableUseState> out) {
for (Map.Entry<VariableDescriptor, VariableStatus> entry : edgeData.entrySet()) {
VariableDescriptor variableDescriptor = entry.getKey(); assert in != null && out != null;
VariableStatus variableStatus = entry.getValue(); Set<VariableDescriptor> declaredVariables = pseudocodeVariablesData.getDeclaredVariables(instruction.getOwner());
enterResult.put(variableDescriptor, variableStatus.merge(enterResult.get(variableDescriptor))); VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, false,
} trace.getBindingContext());
}
Map<VariableDescriptor, VariableStatus> exitResult = Maps.newHashMap(enterResult);
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, true);
if (variableDescriptor != null) {
if (instruction instanceof ReadValueInstruction) {
exitResult.put(variableDescriptor, VariableStatus.READ);
}
else if (instruction instanceof WriteValueInstruction) {
VariableStatus variableStatus = enterResult.get(variableDescriptor);
if (variableStatus == null) variableStatus = VariableStatus.UNUSED;
switch(variableStatus) {
case UNUSED:
case ONLY_WRITTEN:
exitResult.put(variableDescriptor, VariableStatus.ONLY_WRITTEN);
break;
case WRITTEN:
case READ:
exitResult.put(variableDescriptor, VariableStatus.WRITTEN);
}
}
}
return new Pair<Map<VariableDescriptor, VariableStatus>, Map<VariableDescriptor, VariableStatus>>(enterResult, exitResult);
}
});
traverser.traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy<Map<VariableDescriptor, VariableStatus>>() {
@Override
public void execute(@NotNull Instruction instruction, @Nullable Map<VariableDescriptor, VariableStatus> enterData, @Nullable Map<VariableDescriptor, VariableStatus> exitData) {
assert enterData != null && exitData != null;
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, false);
if (variableDescriptor == null || !declaredVariables.contains(variableDescriptor) || if (variableDescriptor == null || !declaredVariables.contains(variableDescriptor) ||
!DescriptorUtils.isLocal(variableDescriptor.getContainingDeclaration(), variableDescriptor)) return; !DescriptorUtils.isLocal(variableDescriptor.getContainingDeclaration(), variableDescriptor)) return;
VariableStatus variableStatus = enterData.get(variableDescriptor); PseudocodeVariablesData.VariableUseState variableUseState = in.get(variableDescriptor);
if (instruction instanceof WriteValueInstruction) { if (instruction instanceof WriteValueInstruction) {
if (trace.get(CAPTURED_IN_CLOSURE, variableDescriptor)) return; if (trace.get(CAPTURED_IN_CLOSURE, variableDescriptor)) return;
JetElement element = ((WriteValueInstruction) instruction).getElement(); JetElement element = ((WriteValueInstruction) instruction).getElement();
if (variableStatus != VariableStatus.READ) { if (variableUseState != LAST_READ) {
if (element instanceof JetBinaryExpression && ((JetBinaryExpression) element).getOperationToken() == JetTokens.EQ) { if (element instanceof JetBinaryExpression &&
((JetBinaryExpression) element).getOperationToken() == JetTokens.EQ) {
JetExpression right = ((JetBinaryExpression) element).getRight(); JetExpression right = ((JetBinaryExpression) element).getRight();
if (right != null) { if (right != null) {
trace.report(Errors.UNUSED_VALUE.on(right, right, variableDescriptor)); trace.report(Errors.UNUSED_VALUE.on(right, right, variableDescriptor));
@@ -621,7 +449,7 @@ public class JetFlowInformationProvider {
if (element instanceof JetNamedDeclaration) { if (element instanceof JetNamedDeclaration) {
PsiElement nameIdentifier = ((JetNamedDeclaration) element).getNameIdentifier(); PsiElement nameIdentifier = ((JetNamedDeclaration) element).getNameIdentifier();
if (nameIdentifier == null) return; if (nameIdentifier == null) return;
if (variableStatus == null || variableStatus == VariableStatus.UNUSED) { if (!VariableUseState.isUsed(variableUseState)) {
if (element instanceof JetProperty) { if (element instanceof JetProperty) {
trace.report(Errors.UNUSED_VARIABLE.on((JetProperty) element, variableDescriptor)); trace.report(Errors.UNUSED_VARIABLE.on((JetProperty) element, variableDescriptor));
} }
@@ -629,8 +457,9 @@ public class JetFlowInformationProvider {
PsiElement psiElement = element.getParent().getParent(); PsiElement psiElement = element.getParent().getParent();
if (psiElement instanceof JetFunction) { if (psiElement instanceof JetFunction) {
boolean isMain = (psiElement instanceof JetNamedFunction) && JetMainDetector.isMain((JetNamedFunction) psiElement); boolean isMain = (psiElement instanceof JetNamedFunction) && JetMainDetector.isMain((JetNamedFunction) psiElement);
if (psiElement instanceof JetFunctionLiteral) return;
DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, psiElement); DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, psiElement);
assert descriptor instanceof FunctionDescriptor; assert descriptor instanceof FunctionDescriptor : psiElement.getText();
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor; FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
if (!isMain && !functionDescriptor.getModality().isOverridable() && functionDescriptor.getOverriddenDescriptors().isEmpty()) { if (!isMain && !functionDescriptor.getModality().isOverridable() && functionDescriptor.getOverriddenDescriptors().isEmpty()) {
trace.report(Errors.UNUSED_PARAMETER.on((JetParameter) element, variableDescriptor)); trace.report(Errors.UNUSED_PARAMETER.on((JetParameter) element, variableDescriptor));
@@ -638,52 +467,34 @@ public class JetFlowInformationProvider {
} }
} }
} }
else if (variableStatus == VariableStatus.ONLY_WRITTEN && element instanceof JetProperty) { else if (variableUseState == ONLY_WRITTEN_NEVER_READ && element instanceof JetProperty) {
trace.report(Errors.ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE.on((JetNamedDeclaration) element, variableDescriptor)); trace.report(Errors.ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE.on((JetNamedDeclaration) element, variableDescriptor));
} }
else if (variableStatus == VariableStatus.WRITTEN && element instanceof JetProperty) { else if (variableUseState == LAST_WRITTEN && element instanceof JetProperty) {
JetExpression initializer = ((JetProperty) element).getInitializer(); JetExpression initializer = ((JetProperty) element).getInitializer();
if (initializer != null) { if (initializer != null) {
trace.report(Errors.VARIABLE_WITH_REDUNDANT_INITIALIZER.on(initializer, variableDescriptor)); trace.report(Errors.VARIABLE_WITH_REDUNDANT_INITIALIZER.on(initializer, variableDescriptor));
} }
} }
} }
} }
} }
}); };
} PseudocodeTraverser.traverse(pseudocode, false, true, variableStatusData, variableStatusAnalyzeStrategy);
private static enum VariableStatus {
READ(3),
WRITTEN(2),
ONLY_WRITTEN(1),
UNUSED(0);
private int importance;
private VariableStatus(int importance) {
this.importance = importance;
}
public VariableStatus merge(@Nullable VariableStatus variableStatus) {
if (variableStatus == null || importance > variableStatus.importance) return this;
return variableStatus;
}
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// "Unused literals" in block // "Unused literals" in block
public void markUnusedLiteralsInBlock(@NotNull JetElement subroutine) { public void markUnusedLiteralsInBlock() {
Pseudocode pseudocode = pseudocodeMap.get(subroutine);
assert pseudocode != null; assert pseudocode != null;
JetControlFlowGraphTraverser<Void> traverser = JetControlFlowGraphTraverser.create(pseudocode, true, true); PseudocodeTraverser.traverse(
traverser.traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy<Void>() { pseudocode, true, new InstructionAnalyzeStrategy() {
@Override @Override
public void execute(@NotNull Instruction instruction, @Nullable Void enterData, @Nullable Void exitData) { public void execute(@NotNull Instruction instruction) {
if (!(instruction instanceof ReadValueInstruction)) return; if (!(instruction instanceof ReadValueInstruction)) return;
JetElement element = ((ReadValueInstruction) instruction).getElement(); JetElement element =
((ReadValueInstruction) instruction).getElement();
if (!(element instanceof JetFunctionLiteralExpression if (!(element instanceof JetFunctionLiteralExpression
|| element instanceof JetConstantExpression || element instanceof JetConstantExpression
|| element instanceof JetStringTemplateExpression || element instanceof JetStringTemplateExpression
@@ -694,7 +505,8 @@ public class JetFlowInformationProvider {
if (parent instanceof JetBlockExpression) { if (parent instanceof JetBlockExpression) {
if (!JetPsiUtil.isImplicitlyUsed(element)) { if (!JetPsiUtil.isImplicitlyUsed(element)) {
if (element instanceof JetFunctionLiteralExpression) { if (element instanceof JetFunctionLiteralExpression) {
trace.report(Errors.UNUSED_FUNCTION_LITERAL.on((JetFunctionLiteralExpression) element)); trace.report(Errors.UNUSED_FUNCTION_LITERAL
.on((JetFunctionLiteralExpression) element));
} }
else { else {
trace.report(Errors.UNUSED_EXPRESSION.on(element)); trace.report(Errors.UNUSED_EXPRESSION.on(element));
@@ -704,133 +516,4 @@ public class JetFlowInformationProvider {
} }
}); });
} }
////////////////////////////////////////////////////////////////////////////////
// Util methods 7
@Nullable
private VariableDescriptor extractVariableDescriptorIfAny(Instruction instruction, boolean onlyReference) {
JetElement element = null;
if (instruction instanceof ReadValueInstruction) {
element = ((ReadValueInstruction) instruction).getElement();
}
else if (instruction instanceof WriteValueInstruction) {
element = ((WriteValueInstruction) instruction).getlValue();
}
else if (instruction instanceof VariableDeclarationInstruction) {
element = ((VariableDeclarationInstruction) instruction).getVariableDeclarationElement();
}
return BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), element, onlyReference);
}
private Collection<VariableDescriptor> collectUsedVariables(Pseudocode pseudocode) {
final Set<VariableDescriptor> usedVariables = Sets.newHashSet();
JetControlFlowGraphTraverser.<Void>create(pseudocode, true, true).traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy<Void>() {
@Override
public void execute(@NotNull Instruction instruction, Void enterData, Void exitData) {
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, false);
if (variableDescriptor != null) {
usedVariables.add(variableDescriptor);
}
}
});
return usedVariables;
}
private Collection<VariableDescriptor> collectDeclaredVariables(JetElement element) {
final Pseudocode pseudocode = pseudocodeMap.get(element);
assert pseudocode != null;
final Set<VariableDescriptor> declaredVariables = Sets.newHashSet();
JetControlFlowGraphTraverser.<Void>create(pseudocode, false, true).traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy<Void>() {
@Override
public void execute(@NotNull Instruction instruction, @Nullable Void enterData, @Nullable Void exitData) {
if (instruction instanceof VariableDeclarationInstruction) {
JetDeclaration variableDeclarationElement = ((VariableDeclarationInstruction) instruction).getVariableDeclarationElement();
DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, variableDeclarationElement);
if (descriptor != null) {
assert descriptor instanceof VariableDescriptor;
declaredVariables.add((VariableDescriptor) descriptor);
}
}
}
});
return declaredVariables;
}
////////////////////////////////////////////////////////////////////////////////
// Local class for uninitialized variables analysis
private static class VariableInitializers {
private Set<JetElement> possibleLocalInitializers = Sets.newHashSet();
private boolean isInitialized;
private boolean isDeclared;
public VariableInitializers(boolean isInitialized) {
this(isInitialized, false);
}
public VariableInitializers(boolean isInitialized, boolean isDeclared) {
this.isInitialized = isInitialized;
this.isDeclared = isDeclared;
}
public VariableInitializers(JetElement element, @Nullable VariableInitializers previous) {
isInitialized = true;
isDeclared = element instanceof JetProperty || (previous != null && previous.isDeclared());
possibleLocalInitializers.add(element);
}
public VariableInitializers(Set<VariableInitializers> edgesData) {
isInitialized = true;
isDeclared = true;
for (VariableInitializers edgeData : edgesData) {
if (!edgeData.isInitialized) {
isInitialized = false;
}
if (!edgeData.isDeclared) {
isDeclared = false;
}
possibleLocalInitializers.addAll(edgeData.possibleLocalInitializers);
}
}
public Set<JetElement> getPossibleLocalInitializers() {
return possibleLocalInitializers;
}
public boolean isInitialized() {
return isInitialized;
}
public boolean isDeclared() {
return isDeclared;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof VariableInitializers)) return false;
VariableInitializers that = (VariableInitializers) o;
if (isDeclared != that.isDeclared) return false;
if (isInitialized != that.isInitialized) return false;
if (possibleLocalInitializers != null
? !possibleLocalInitializers.equals(that.possibleLocalInitializers)
: that.possibleLocalInitializers != null) {
return false;
}
return true;
}
@Override
public int hashCode() {
int result = possibleLocalInitializers != null ? possibleLocalInitializers.hashCode() : 0;
result = 31 * result + (isInitialized ? 1 : 0);
result = 31 * result + (isDeclared ? 1 : 0);
return result;
}
}
} }
@@ -0,0 +1,204 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.cfg;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.pseudocode.*;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* @author svtk
*/
public class PseudocodeTraverser {
@NotNull
private static Instruction getStartInstruction(@NotNull Pseudocode pseudocode, boolean directOrder) {
return directOrder ? pseudocode.getEnterInstruction() : pseudocode.getSinkInstruction();
}
public static <D> Map<Instruction, Edges<D>> collectData(
@NotNull Pseudocode pseudocode, boolean directOrder, boolean lookInside,
@NotNull D initialDataValue, @NotNull D initialDataValueForEnterInstruction,
@NotNull InstructionDataMergeStrategy<D> instructionDataMergeStrategy) {
Map<Instruction, Edges<D>> edgesMap = Maps.newLinkedHashMap();
initializeEdgesMap(pseudocode, lookInside, edgesMap, initialDataValue);
edgesMap.put(getStartInstruction(pseudocode, directOrder), Edges.create(initialDataValueForEnterInstruction, initialDataValueForEnterInstruction));
boolean[] changed = new boolean[1];
changed[0] = true;
while (changed[0]) {
changed[0] = false;
collectDataFromSubgraph(pseudocode, directOrder, lookInside, edgesMap, instructionDataMergeStrategy,
Collections.<Instruction>emptyList(), changed, false);
}
return edgesMap;
}
private static <D> void initializeEdgesMap(
@NotNull Pseudocode pseudocode, boolean lookInside,
@NotNull Map<Instruction, Edges<D>> edgesMap,
@NotNull D initialDataValue) {
List<Instruction> instructions = pseudocode.getInstructions();
Edges<D> initialEdge = Edges.create(initialDataValue, initialDataValue);
for (Instruction instruction : instructions) {
edgesMap.put(instruction, initialEdge);
if (lookInside && instruction instanceof LocalDeclarationInstruction) {
initializeEdgesMap(((LocalDeclarationInstruction) instruction).getBody(), lookInside, edgesMap, initialDataValue);
}
}
}
private static <D> void collectDataFromSubgraph(
@NotNull Pseudocode pseudocode, boolean directOrder, boolean lookInside,
@NotNull Map<Instruction, Edges<D>> edgesMap,
@NotNull InstructionDataMergeStrategy<D> instructionDataMergeStrategy,
@NotNull Collection<Instruction> previousSubGraphInstructions,
boolean[] changed, boolean isLocal) {
List<Instruction> instructions = directOrder ? pseudocode.getInstructions() : pseudocode.getReversedInstructions();
Instruction startInstruction = getStartInstruction(pseudocode, directOrder);
for (Instruction instruction : instructions) {
boolean isStart = directOrder ? instruction instanceof SubroutineEnterInstruction : instruction instanceof SubroutineSinkInstruction;
if (!isLocal && isStart) continue;
Collection<Instruction> allPreviousInstructions;
Collection<Instruction> previousInstructions = directOrder ? instruction.getPreviousInstructions() : instruction.getNextInstructions();
if (instruction == startInstruction && !previousSubGraphInstructions.isEmpty()) {
allPreviousInstructions = Lists.newArrayList(previousInstructions);
allPreviousInstructions.addAll(previousSubGraphInstructions);
}
else {
allPreviousInstructions = previousInstructions;
}
if (lookInside && instruction instanceof LocalDeclarationInstruction) {
Pseudocode subroutinePseudocode = ((LocalDeclarationInstruction) instruction).getBody();
collectDataFromSubgraph(subroutinePseudocode, directOrder, lookInside, edgesMap, instructionDataMergeStrategy,
previousInstructions,
changed, true);
Instruction lastInstruction = directOrder ? subroutinePseudocode.getSinkInstruction() : subroutinePseudocode.getEnterInstruction();
Edges<D> previousValue = edgesMap.get(instruction);
Edges<D> newValue = edgesMap.get(lastInstruction);
if (!previousValue.equals(newValue)) {
changed[0] = true;
edgesMap.put(instruction, newValue);
}
continue;
}
Edges<D> previousDataValue = edgesMap.get(instruction);
Collection<D> incomingEdgesData = Sets.newHashSet();
for (Instruction previousInstruction : allPreviousInstructions) {
Edges<D> previousData = edgesMap.get(previousInstruction);
if (previousData != null) {
incomingEdgesData.add(previousData.out);
}
}
Edges<D> mergedData = instructionDataMergeStrategy.execute(instruction, incomingEdgesData);
if (!mergedData.equals(previousDataValue)) {
changed[0] = true;
edgesMap.put(instruction, mergedData);
}
}
}
public static void traverse(
@NotNull Pseudocode pseudocode, boolean directOrder,
InstructionAnalyzeStrategy instructionAnalyzeStrategy) {
List<Instruction> instructions = directOrder ? pseudocode.getInstructions() : pseudocode.getReversedInstructions();
for (Instruction instruction : instructions) {
if (instruction instanceof LocalDeclarationInstruction) {
traverse(((LocalDeclarationInstruction) instruction).getBody(), directOrder, instructionAnalyzeStrategy);
}
instructionAnalyzeStrategy.execute(instruction);
}
}
public static <D> void traverse(
@NotNull Pseudocode pseudocode, boolean directOrder, boolean lookInside,
@NotNull Map<Instruction, Edges<D>> edgesMap,
@NotNull InstructionDataAnalyzeStrategy<D> instructionDataAnalyzeStrategy) {
List<Instruction> instructions = directOrder ? pseudocode.getInstructions() : pseudocode.getReversedInstructions();
for (Instruction instruction : instructions) {
if (lookInside && instruction instanceof LocalDeclarationInstruction) {
traverse(((LocalDeclarationInstruction) instruction).getBody(), directOrder, lookInside, edgesMap,
instructionDataAnalyzeStrategy);
}
Edges<D> edges = edgesMap.get(instruction);
instructionDataAnalyzeStrategy.execute(instruction, edges != null ? edges.in : null, edges != null ? edges.out : null);
}
}
public interface InstructionDataMergeStrategy<D> {
Edges<D> execute(@NotNull Instruction instruction, @NotNull Collection<D> incomingEdgesData);
}
public interface InstructionDataAnalyzeStrategy<D> {
void execute(@NotNull Instruction instruction, @Nullable D enterData, @Nullable D exitData);
}
public interface InstructionAnalyzeStrategy {
void execute(@NotNull Instruction instruction);
}
public static class Edges<T> {
public final T in;
public final T out;
Edges(@NotNull T in, @NotNull T out) {
this.in = in;
this.out = out;
}
public static <T> Edges<T> create(@NotNull T in, @NotNull T out) {
return new Edges<T>(in, out);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Edges)) return false;
Edges edges = (Edges) o;
if (in != null ? !in.equals(edges.in) : edges.in != null) return false;
if (out != null ? !out.equals(edges.out) : edges.out != null) return false;
return true;
}
@Override
public int hashCode() {
int result = in != null ? in.hashCode() : 0;
result = 31 * result + (out != null ? out.hashCode() : 0);
return result;
}
}
}
@@ -0,0 +1,348 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.cfg;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.PseudocodeTraverser.*;
import org.jetbrains.jet.lang.cfg.pseudocode.*;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.psi.JetDeclaration;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetProperty;
import org.jetbrains.jet.lang.resolve.BindingContext;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
/**
* @author svtk
*/
public class PseudocodeVariablesData {
private final Pseudocode pseudocode;
private final BindingContext bindingContext;
private final Map<Pseudocode, Set<VariableDescriptor>> declaredVariablesInEachDeclaration = Maps.newHashMap();
private final Map<Pseudocode, Set<VariableDescriptor>> usedVariablesInEachDeclaration = Maps.newHashMap();
private Map<Instruction, Edges<Map<VariableDescriptor, VariableInitState>>> variableInitializersMap;
private Map<Instruction, Edges<Map<VariableDescriptor, VariableUseState>>> variableStatusMap;
public PseudocodeVariablesData(@NotNull Pseudocode pseudocode, @NotNull BindingContext bindingContext) {
this.pseudocode = pseudocode;
this.bindingContext = bindingContext;
}
@NotNull
public Pseudocode getPseudocode() {
return pseudocode;
}
@NotNull
public Set<VariableDescriptor> getUsedVariables(@NotNull Pseudocode pseudocode) {
Set<VariableDescriptor> usedVariables = usedVariablesInEachDeclaration.get(pseudocode);
if (usedVariables == null) {
final Set<VariableDescriptor> result = Sets.newHashSet();
PseudocodeTraverser.traverse(pseudocode, true, new InstructionAnalyzeStrategy() {
@Override
public void execute(@NotNull Instruction instruction) {
VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, false,
bindingContext);
if (variableDescriptor != null) {
result.add(variableDescriptor);
}
}
});
usedVariables = Collections.unmodifiableSet(result);
usedVariablesInEachDeclaration.put(pseudocode, usedVariables);
}
return usedVariables;
}
@NotNull
public Set<VariableDescriptor> getDeclaredVariables(@NotNull Pseudocode pseudocode) {
Set<VariableDescriptor> declaredVariables = declaredVariablesInEachDeclaration.get(pseudocode);
if (declaredVariables == null) {
declaredVariables = Sets.newHashSet();
for (Instruction instruction : pseudocode.getInstructions()) {
if (instruction instanceof VariableDeclarationInstruction) {
JetDeclaration variableDeclarationElement = ((VariableDeclarationInstruction) instruction).getVariableDeclarationElement();
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, variableDeclarationElement);
if (descriptor != null) {
assert descriptor instanceof VariableDescriptor;
declaredVariables.add((VariableDescriptor) descriptor);
}
}
}
declaredVariables = Collections.unmodifiableSet(declaredVariables);
declaredVariablesInEachDeclaration.put(pseudocode, declaredVariables);
}
return declaredVariables;
}
// variable initializers
@NotNull
public Map<Instruction, Edges<Map<VariableDescriptor, VariableInitState>>> getVariableInitializers() {
if (variableInitializersMap == null) {
variableInitializersMap = getVariableInitializers(pseudocode);
}
return variableInitializersMap;
}
@NotNull
private Map<Instruction, Edges<Map<VariableDescriptor, VariableInitState>>> getVariableInitializers(@NotNull Pseudocode pseudocode) {
Set<VariableDescriptor> usedVariables = getUsedVariables(pseudocode);
Set<VariableDescriptor> declaredVariables = getDeclaredVariables(pseudocode);
Map<VariableDescriptor, VariableInitState> initialMap = Collections.emptyMap();
final Map<VariableDescriptor, VariableInitState> initialMapForStartInstruction = prepareInitializersMapForStartInstruction(
usedVariables, declaredVariables);
Map<Instruction, Edges<Map<VariableDescriptor, VariableInitState>>> variableInitializersMap = PseudocodeTraverser.collectData(
pseudocode, /* directOrder = */ true, /* lookInside = */ false,
initialMap, initialMapForStartInstruction, new PseudocodeTraverser.InstructionDataMergeStrategy<Map<VariableDescriptor, VariableInitState>>() {
@Override
public Edges<Map<VariableDescriptor, VariableInitState>> execute(
@NotNull Instruction instruction, @NotNull Collection<Map<VariableDescriptor, VariableInitState>> incomingEdgesData) {
Map<VariableDescriptor, VariableInitState> enterInstructionData = mergeIncomingEdgesDataForInitializers(incomingEdgesData);
Map<VariableDescriptor, VariableInitState> exitInstructionData =
addVariableInitStateFromCurrentInstructionIfAny(instruction, enterInstructionData);
return Edges.create(enterInstructionData, exitInstructionData);
}
});
for (LocalDeclarationInstruction localDeclarationInstruction : pseudocode.getLocalDeclarations()) {
Pseudocode localPseudocode = localDeclarationInstruction.getBody();
Map<Instruction, Edges<Map<VariableDescriptor, VariableInitState>>> initializersForLocalDeclaration = getVariableInitializers(localPseudocode);
for (Instruction instruction : initializersForLocalDeclaration.keySet()) {
//todo
if (!variableInitializersMap.containsKey(instruction)) {
variableInitializersMap.put(instruction, initializersForLocalDeclaration.get(instruction));
}
}
variableInitializersMap.putAll(initializersForLocalDeclaration);
}
return variableInitializersMap;
}
@NotNull
private Map<VariableDescriptor, VariableInitState> prepareInitializersMapForStartInstruction(
@NotNull Collection<VariableDescriptor> usedVariables,
@NotNull Collection<VariableDescriptor> declaredVariables) {
Map<VariableDescriptor, VariableInitState> initialMapForStartInstruction = Maps.newHashMap();
VariableInitState initializedForExternalVariable = VariableInitState.create(true);
VariableInitState notInitializedForDeclaredVariable = VariableInitState.create(false);
for (VariableDescriptor variable : usedVariables) {
if (declaredVariables.contains(variable)) {
initialMapForStartInstruction.put(variable, notInitializedForDeclaredVariable);
}
else {
initialMapForStartInstruction.put(variable, initializedForExternalVariable);
}
}
return initialMapForStartInstruction;
}
@NotNull
private Map<VariableDescriptor, VariableInitState> mergeIncomingEdgesDataForInitializers(
@NotNull Collection<Map<VariableDescriptor, VariableInitState>> incomingEdgesData) {
Set<VariableDescriptor> variablesInScope = Sets.newHashSet();
for (Map<VariableDescriptor, VariableInitState> edgeData : incomingEdgesData) {
variablesInScope.addAll(edgeData.keySet());
}
Map<VariableDescriptor, VariableInitState> enterInstructionData = Maps.newHashMap();
for (VariableDescriptor variable : variablesInScope) {
Set<VariableInitState> edgesDataForVariable = Sets.newHashSet();
for (Map<VariableDescriptor, VariableInitState> edgeData : incomingEdgesData) {
VariableInitState initState = edgeData.get(variable);
if (initState != null) {
edgesDataForVariable.add(initState);
}
}
enterInstructionData.put(variable, VariableInitState.create(edgesDataForVariable));
}
return enterInstructionData;
}
@NotNull
private Map<VariableDescriptor, VariableInitState> addVariableInitStateFromCurrentInstructionIfAny(
@NotNull Instruction instruction, @NotNull Map<VariableDescriptor, VariableInitState> enterInstructionData) {
if (!(instruction instanceof WriteValueInstruction) && !(instruction instanceof VariableDeclarationInstruction)) {
return enterInstructionData;
}
VariableDescriptor variable = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, false, bindingContext);
if (variable == null) {
return enterInstructionData;
}
Map<VariableDescriptor, VariableInitState> exitInstructionData = Maps.newHashMap(enterInstructionData);
if (instruction instanceof WriteValueInstruction) {
VariableInitState enterInitState = enterInstructionData.get(variable);
VariableInitState initializationAtThisElement =
VariableInitState.create(((WriteValueInstruction) instruction).getElement() instanceof JetProperty, enterInitState);
exitInstructionData.put(variable, initializationAtThisElement);
}
else { // instruction instanceof VariableDeclarationInstruction
VariableInitState enterInitState = enterInstructionData.get(variable);
if (enterInitState == null || !enterInitState.isInitialized || !enterInitState.isDeclared) {
boolean isInitialized = enterInitState != null && enterInitState.isInitialized;
VariableInitState variableDeclarationInfo = VariableInitState.create(isInitialized, true);
exitInstructionData.put(variable, variableDeclarationInfo);
}
}
return exitInstructionData;
}
// variable use
@NotNull
public Map<Instruction, Edges<Map<VariableDescriptor, VariableUseState>>> getVariableUseStatusData() {
if (variableStatusMap == null) {
Map<VariableDescriptor, VariableUseState> sinkInstructionData = Maps.newHashMap();
for (VariableDescriptor usedVariable : usedVariablesInEachDeclaration.get(pseudocode)) {
sinkInstructionData.put(usedVariable, VariableUseState.UNUSED);
}
InstructionDataMergeStrategy<Map<VariableDescriptor, VariableUseState>> collectVariableUseStatusStrategy = new InstructionDataMergeStrategy<Map<VariableDescriptor, VariableUseState>>() {
@Override
public Edges<Map<VariableDescriptor, VariableUseState>> execute(@NotNull Instruction instruction,
@NotNull Collection<Map<VariableDescriptor, VariableUseState>> incomingEdgesData) {
Map<VariableDescriptor, VariableUseState> enterResult = Maps.newHashMap();
for (Map<VariableDescriptor, VariableUseState> edgeData : incomingEdgesData) {
for (Map.Entry<VariableDescriptor, VariableUseState> entry : edgeData.entrySet()) {
VariableDescriptor variableDescriptor = entry.getKey();
VariableUseState variableUseState = entry.getValue();
enterResult.put(variableDescriptor, variableUseState.merge(enterResult.get(variableDescriptor)));
}
}
VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, true,
bindingContext);
if (variableDescriptor == null ||
(!(instruction instanceof ReadValueInstruction) && !(instruction instanceof WriteValueInstruction))) {
return Edges.create(enterResult, enterResult);
}
Map<VariableDescriptor, VariableUseState> exitResult = Maps.newHashMap(enterResult);
if (instruction instanceof ReadValueInstruction) {
exitResult.put(variableDescriptor, VariableUseState.LAST_READ);
}
else { //instruction instanceof WriteValueInstruction
VariableUseState variableUseState = enterResult.get(variableDescriptor);
if (variableUseState == null) {
variableUseState = VariableUseState.UNUSED;
}
switch (variableUseState) {
case UNUSED:
case ONLY_WRITTEN_NEVER_READ:
exitResult.put(variableDescriptor, VariableUseState.ONLY_WRITTEN_NEVER_READ);
break;
case LAST_WRITTEN:
case LAST_READ:
exitResult.put(variableDescriptor, VariableUseState.LAST_WRITTEN);
}
}
return Edges.create(enterResult, exitResult);
}
};
variableStatusMap = PseudocodeTraverser.collectData(pseudocode, false, true,
Collections.<VariableDescriptor, VariableUseState>emptyMap(),
sinkInstructionData, collectVariableUseStatusStrategy);
}
return variableStatusMap;
}
public static class VariableInitState {
public final boolean isInitialized;
public final boolean isDeclared;
private VariableInitState(boolean isInitialized, boolean isDeclared) {
this.isInitialized = isInitialized;
this.isDeclared = isDeclared;
}
private static final VariableInitState VS_TT = new VariableInitState(true, true);
private static final VariableInitState VS_TF = new VariableInitState(true, false);
private static final VariableInitState VS_FT = new VariableInitState(false, true);
private static final VariableInitState VS_FF = new VariableInitState(false, false);
private static VariableInitState create(boolean isInitialized, boolean isDeclared) {
if (isInitialized) {
if (isDeclared) return VS_TT;
return VS_TF;
}
if (isDeclared) return VS_FT;
return VS_FF;
}
private static VariableInitState create(boolean isInitialized) {
return create(isInitialized, false);
}
private static VariableInitState create(boolean isDeclaredHere, @Nullable VariableInitState mergedEdgesData) {
return create(true, isDeclaredHere || (mergedEdgesData != null && mergedEdgesData.isDeclared));
}
private static VariableInitState create(@NotNull Set<VariableInitState> edgesData) {
boolean isInitialized = true;
boolean isDeclared = true;
for (VariableInitState edgeData : edgesData) {
if (!edgeData.isInitialized) {
isInitialized = false;
}
if (!edgeData.isDeclared) {
isDeclared = false;
}
}
return create(isInitialized, isDeclared);
}
}
public static enum VariableUseState {
LAST_READ(3),
LAST_WRITTEN(2),
ONLY_WRITTEN_NEVER_READ(1),
UNUSED(0);
private final int importance;
VariableUseState(int importance) {
this.importance = importance;
}
private VariableUseState merge(@Nullable VariableUseState variableUseState) {
if (variableUseState == null || importance > variableUseState.importance) return this;
return variableUseState;
}
public static boolean isUsed(@Nullable VariableUseState variableUseState) {
return variableUseState != null && variableUseState != UNUSED;
}
}
}
@@ -35,12 +35,6 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
private final Stack<BlockInfo> allBlocks = new Stack<BlockInfo>(); private final Stack<BlockInfo> allBlocks = new Stack<BlockInfo>();
private final JetPseudocodeTrace trace;
public JetControlFlowInstructionsGenerator(JetPseudocodeTrace trace) {
this.trace = trace;
}
private void pushBuilder(JetElement scopingElement, JetElement subroutine) { private void pushBuilder(JetElement scopingElement, JetElement subroutine) {
JetControlFlowInstructionsGeneratorWorker worker = new JetControlFlowInstructionsGeneratorWorker(scopingElement, subroutine); JetControlFlowInstructionsGeneratorWorker worker = new JetControlFlowInstructionsGeneratorWorker(scopingElement, subroutine);
builders.push(worker); builders.push(worker);
@@ -49,7 +43,6 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
private JetControlFlowInstructionsGeneratorWorker popBuilder(@NotNull JetElement element) { private JetControlFlowInstructionsGeneratorWorker popBuilder(@NotNull JetElement element) {
JetControlFlowInstructionsGeneratorWorker worker = builders.pop(); JetControlFlowInstructionsGeneratorWorker worker = builders.pop();
trace.recordControlFlowData(element, worker.getPseudocode());
if (!builders.isEmpty()) { if (!builders.isEmpty()) {
builder = builders.peek(); builder = builders.peek();
} }
@@ -72,7 +65,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
} }
@Override @Override
public void exitSubroutine(@NotNull JetDeclaration subroutine) { public Pseudocode exitSubroutine(@NotNull JetDeclaration subroutine) {
super.exitSubroutine(subroutine); super.exitSubroutine(subroutine);
JetControlFlowInstructionsGeneratorWorker worker = popBuilder(subroutine); JetControlFlowInstructionsGeneratorWorker worker = popBuilder(subroutine);
if (!builders.empty()) { if (!builders.empty()) {
@@ -80,32 +73,29 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
LocalDeclarationInstruction instruction = new LocalDeclarationInstruction(subroutine, worker.getPseudocode()); LocalDeclarationInstruction instruction = new LocalDeclarationInstruction(subroutine, worker.getPseudocode());
builder.add(instruction); builder.add(instruction);
} }
return worker.getPseudocode();
} }
private class JetControlFlowInstructionsGeneratorWorker implements JetControlFlowBuilder { private class JetControlFlowInstructionsGeneratorWorker implements JetControlFlowBuilder {
private final Pseudocode pseudocode; private final PseudocodeImpl pseudocode;
private final Label error; private final Label error;
private final Label sink; private final Label sink;
private final JetElement returnSubroutine; private final JetElement returnSubroutine;
private JetControlFlowInstructionsGeneratorWorker(@NotNull JetElement scopingElement, @NotNull JetElement returnSubroutine) { private JetControlFlowInstructionsGeneratorWorker(@NotNull JetElement scopingElement, @NotNull JetElement returnSubroutine) {
this.pseudocode = new Pseudocode(scopingElement); this.pseudocode = new PseudocodeImpl(scopingElement);
this.error = pseudocode.createLabel("error"); this.error = pseudocode.createLabel("error");
this.sink = pseudocode.createLabel("sink"); this.sink = pseudocode.createLabel("sink");
this.returnSubroutine = returnSubroutine; this.returnSubroutine = returnSubroutine;
} }
public Pseudocode getPseudocode() { public PseudocodeImpl getPseudocode() {
return pseudocode; return pseudocode;
} }
private void add(@NotNull Instruction instruction) { private void add(@NotNull Instruction instruction) {
pseudocode.addInstruction(instruction); pseudocode.addInstruction(instruction);
if (instruction instanceof JetElementInstruction) {
JetElementInstruction elementInstruction = (JetElementInstruction) instruction;
trace.recordRepresentativeInstruction(elementInstruction.getElement(), instruction);
}
} }
@NotNull @NotNull
@@ -127,7 +117,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
loopInfo.push(blockInfo); loopInfo.push(blockInfo);
elementToBlockInfo.put(expression, blockInfo); elementToBlockInfo.put(expression, blockInfo);
allBlocks.push(blockInfo); allBlocks.push(blockInfo);
trace.recordLoopInfo(expression, blockInfo); pseudocode.recordLoopInfo(expression, blockInfo);
return blockInfo; return blockInfo;
} }
@@ -202,7 +192,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
} }
@Override @Override
public void exitSubroutine(@NotNull JetDeclaration subroutine) { public Pseudocode exitSubroutine(@NotNull JetDeclaration subroutine) {
bindLabel(getExitPoint(subroutine)); bindLabel(getExitPoint(subroutine));
pseudocode.addExitInstruction(new SubroutineExitInstruction(subroutine, "<END>")); pseudocode.addExitInstruction(new SubroutineExitInstruction(subroutine, "<END>"));
bindLabel(error); bindLabel(error);
@@ -211,6 +201,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
pseudocode.addSinkInstruction(new SubroutineSinkInstruction(subroutine, "<SINK>")); pseudocode.addSinkInstruction(new SubroutineSinkInstruction(subroutine, "<SINK>"));
elementToBlockInfo.remove(subroutine); elementToBlockInfo.remove(subroutine);
allBlocks.pop(); allBlocks.pop();
return null;
} }
@Override @Override
@@ -1,54 +0,0 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.cfg.LoopInfo;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetExpression;
/**
* @author abreslav
*/
public interface JetPseudocodeTrace {
JetPseudocodeTrace EMPTY = new JetPseudocodeTrace() {
@Override
public void recordControlFlowData(@NotNull JetElement element, @NotNull Pseudocode pseudocode) {
}
@Override
public void recordRepresentativeInstruction(@NotNull JetElement element, @NotNull Instruction instruction) {
}
@Override
public void close() {
}
@Override
public void recordLoopInfo(JetExpression expression, LoopInfo blockInfo) {
}
};
void recordControlFlowData(@NotNull JetElement element, @NotNull Pseudocode pseudocode);
void recordRepresentativeInstruction(@NotNull JetElement element, @NotNull Instruction instruction);
void close();
void recordLoopInfo(JetExpression expression, LoopInfo blockInfo);
}
@@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.cfg.pseudocode;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetDeclaration; import org.jetbrains.jet.lang.psi.JetDeclaration;
import org.jetbrains.jet.lang.psi.JetElement;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@@ -40,6 +41,12 @@ public class LocalDeclarationInstruction extends InstructionWithNext {
return body; return body;
} }
@NotNull
@Override
public JetDeclaration getElement() {
return (JetDeclaration) super.getElement();
}
@NotNull @NotNull
@Override @Override
public Collection<Instruction> getNextInstructions() { public Collection<Instruction> getNextInstructions() {
@@ -16,343 +16,37 @@
package org.jetbrains.jet.lang.cfg.pseudocode; package org.jetbrains.jet.lang.cfg.pseudocode;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.Label;
import org.jetbrains.jet.lang.psi.JetElement; import org.jetbrains.jet.lang.psi.JetElement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
/** /**
* @author abreslav * @author svtk
*/ */
public class Pseudocode { public interface Pseudocode {
@NotNull
public class PseudocodeLabel implements Label { JetElement getCorrespondingElement();
private final String name;
private Integer targetInstructionIndex;
private PseudocodeLabel(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
@Override
public String toString() {
return name;
}
public Integer getTargetInstructionIndex() {
return targetInstructionIndex;
}
public void setTargetInstructionIndex(int targetInstructionIndex) {
this.targetInstructionIndex = targetInstructionIndex;
}
@Nullable
private List<Instruction> resolve() {
assert targetInstructionIndex != null;
return mutableInstructionList.subList(getTargetInstructionIndex(), mutableInstructionList.size());
}
public Instruction resolveToInstruction() {
assert targetInstructionIndex != null;
return mutableInstructionList.get(targetInstructionIndex);
}
}
private final List<Instruction> mutableInstructionList = new ArrayList<Instruction>();
private final List<Instruction> instructions = new ArrayList<Instruction>();
private List<Instruction> deadInstructions;
private final List<PseudocodeLabel> labels = new ArrayList<PseudocodeLabel>();
private final List<PseudocodeLabel> allowedDeadLabels = new ArrayList<PseudocodeLabel>();
private final List<PseudocodeLabel> stopAllowDeadLabels = new ArrayList<PseudocodeLabel>();
private final JetElement correspondingElement;
private SubroutineExitInstruction exitInstruction;
private SubroutineSinkInstruction sinkInstruction;
private SubroutineExitInstruction errorInstruction;
private boolean postPrecessed = false;
public Pseudocode(JetElement correspondingElement) {
this.correspondingElement = correspondingElement;
}
public JetElement getCorrespondingElement() {
return correspondingElement;
}
public PseudocodeLabel createLabel(String name) {
PseudocodeLabel label = new PseudocodeLabel(name);
labels.add(label);
return label;
}
public void allowDead(Label label) {
allowedDeadLabels.add((PseudocodeLabel) label);
}
public void stopAllowDead(Label label) {
stopAllowDeadLabels.add((PseudocodeLabel) label);
}
@NotNull @NotNull
public List<Instruction> getInstructions() { Set<LocalDeclarationInstruction> getLocalDeclarations();
return instructions;
}
@Deprecated //for tests only
@NotNull
public List<Instruction> getMutableInstructionList() {
return mutableInstructionList;
}
@NotNull @NotNull
public List<Instruction> getDeadInstructions() { List<Instruction> getInstructions();
if (deadInstructions != null) {
return deadInstructions;
}
deadInstructions = Lists.newArrayList();
Collection<Instruction> allowedDeadInstructions = collectAllowedDeadInstructions();
for (Instruction instruction : mutableInstructionList) {
if (((InstructionImpl)instruction).isDead()) {
if (!allowedDeadInstructions.contains(instruction)) {
deadInstructions.add(instruction);
}
}
}
return deadInstructions;
}
@Deprecated //for tests only
@NotNull
public List<PseudocodeLabel> getLabels() {
return labels;
}
public void addExitInstruction(SubroutineExitInstruction exitInstruction) {
addInstruction(exitInstruction);
assert this.exitInstruction == null;
this.exitInstruction = exitInstruction;
}
public void addSinkInstruction(SubroutineSinkInstruction sinkInstruction) {
addInstruction(sinkInstruction);
assert this.sinkInstruction == null;
this.sinkInstruction = sinkInstruction;
}
public void addErrorInstruction(SubroutineExitInstruction errorInstruction) {
addInstruction(errorInstruction);
assert this.errorInstruction == null;
this.errorInstruction = errorInstruction;
}
public void addInstruction(Instruction instruction) {
mutableInstructionList.add(instruction);
instruction.setOwner(this);
}
@NotNull @NotNull
public SubroutineExitInstruction getExitInstruction() { List<Instruction> getReversedInstructions();
return exitInstruction;
}
@NotNull @NotNull
public SubroutineSinkInstruction getSinkInstruction() { List<Instruction> getDeadInstructions();
return sinkInstruction;
}
@NotNull @NotNull
public SubroutineEnterInstruction getEnterInstruction() { SubroutineExitInstruction getExitInstruction();
return (SubroutineEnterInstruction) mutableInstructionList.get(0);
}
public void bindLabel(Label label) {
((PseudocodeLabel) label).setTargetInstructionIndex(mutableInstructionList.size());
}
public void postProcess() {
if (postPrecessed) return;
postPrecessed = true;
for (int i = 0, instructionsSize = mutableInstructionList.size(); i < instructionsSize; i++) {
processInstruction(mutableInstructionList.get(i), i);
}
getExitInstruction().setSink(getSinkInstruction());
Set<Instruction> reachableInstructions = collectReachableInstructions();
for (Instruction instruction : mutableInstructionList) {
if (reachableInstructions.contains(instruction)) {
instructions.add(instruction);
}
}
markDeadInstructions();
}
private void processInstruction(Instruction instruction, final int currentPosition) {
instruction.accept(new InstructionVisitor() {
@Override
public void visitInstructionWithNext(InstructionWithNext instruction) {
instruction.setNext(getNextPosition(currentPosition));
}
@Override
public void visitJump(AbstractJumpInstruction instruction) {
instruction.setResolvedTarget(getJumpTarget(instruction.getTargetLabel()));
}
@Override
public void visitNondeterministicJump(NondeterministicJumpInstruction instruction) {
instruction.setNext(getNextPosition(currentPosition));
List<Label> targetLabels = instruction.getTargetLabels();
for (Label targetLabel : targetLabels) {
instruction.setResolvedTarget(targetLabel, getJumpTarget(targetLabel));
}
}
@Override
public void visitConditionalJump(ConditionalJumpInstruction instruction) {
Instruction nextInstruction = getNextPosition(currentPosition);
Instruction jumpTarget = getJumpTarget(instruction.getTargetLabel());
if (instruction.onTrue()) {
instruction.setNextOnFalse(nextInstruction);
instruction.setNextOnTrue(jumpTarget);
}
else {
instruction.setNextOnFalse(jumpTarget);
instruction.setNextOnTrue(nextInstruction);
}
visitJump(instruction);
}
@Override
public void visitLocalDeclarationInstruction(LocalDeclarationInstruction instruction) {
instruction.getBody().postProcess();
instruction.setNext(getSinkInstruction());
}
@Override
public void visitSubroutineExit(SubroutineExitInstruction instruction) {
// Nothing
}
@Override
public void visitSubroutineSink(SubroutineSinkInstruction instruction) {
// Nothing
}
@Override
public void visitInstruction(Instruction instruction) {
throw new UnsupportedOperationException(instruction.toString());
}
});
}
private Set<Instruction> collectReachableInstructions() {
Set<Instruction> visited = Sets.newHashSet();
traverseNextInstructions(getEnterInstruction(), visited);
if (!visited.contains(getExitInstruction())) {
visited.add(getExitInstruction());
}
if (!visited.contains(errorInstruction)) {
visited.add(errorInstruction);
}
if (!visited.contains(getSinkInstruction())) {
visited.add(getSinkInstruction());
}
return visited;
}
private void traverseNextInstructions(@NotNull Instruction instruction, @NotNull Set<Instruction> visited) {
if (visited.contains(instruction)) return;
visited.add(instruction);
for (Instruction nextInstruction : instruction.getNextInstructions()) {
if (nextInstruction == null) continue; //todo it might be null on incomplete code
traverseNextInstructions(nextInstruction, visited);
}
}
private void markDeadInstructions() {
Set<Instruction> instructionSet = Sets.newHashSet(instructions);
for (Instruction instruction : mutableInstructionList) {
if (!instructionSet.contains(instruction)) {
((InstructionImpl)instruction).die();
for (Instruction nextInstruction : instruction.getNextInstructions()) {
nextInstruction.getPreviousInstructions().remove(instruction);
}
}
}
}
@NotNull @NotNull
private Set<Instruction> prepareAllowedDeadInstructions() { SubroutineSinkInstruction getSinkInstruction();
Set<Instruction> allowedDeadStartInstructions = Sets.newHashSet();
for (PseudocodeLabel allowedDeadLabel : allowedDeadLabels) {
Instruction allowedDeadInstruction = getJumpTarget(allowedDeadLabel);
if (((InstructionImpl)allowedDeadInstruction).isDead()) {
allowedDeadStartInstructions.add(allowedDeadInstruction);
}
}
return allowedDeadStartInstructions;
}
@NotNull @NotNull
private Set<Instruction> prepareStopAllowedDeadInstructions() { SubroutineEnterInstruction getEnterInstruction();
Set<Instruction> stopAllowedDeadInstructions = Sets.newHashSet();
for (PseudocodeLabel stopAllowedDeadLabel : stopAllowDeadLabels) {
Instruction stopAllowDeadInsruction = getJumpTarget(stopAllowedDeadLabel);
if (((InstructionImpl)stopAllowDeadInsruction).isDead()) {
stopAllowedDeadInstructions.add(stopAllowDeadInsruction);
}
}
return stopAllowedDeadInstructions;
}
@NotNull
private Collection<Instruction> collectAllowedDeadInstructions() {
Set<Instruction> allowedDeadStartInstructions = prepareAllowedDeadInstructions();
Set<Instruction> stopAllowDeadInstructions = prepareStopAllowedDeadInstructions();
Set<Instruction> allowedDeadInstructions = Sets.newHashSet();
for (Instruction allowedDeadStartInstruction : allowedDeadStartInstructions) {
collectAllowedDeadInstructions(allowedDeadStartInstruction, allowedDeadInstructions, stopAllowDeadInstructions);
}
return allowedDeadInstructions;
}
private void collectAllowedDeadInstructions(Instruction allowedDeadInstruction, Set<Instruction> instructionSet, Set<Instruction> stopAllowDeadInstructions) {
if (instructionSet.contains(allowedDeadInstruction) || stopAllowDeadInstructions.contains(allowedDeadInstruction)) return;
if (((InstructionImpl)allowedDeadInstruction).isDead()) {
instructionSet.add(allowedDeadInstruction);
for (Instruction instruction : allowedDeadInstruction.getNextInstructions()) {
collectAllowedDeadInstructions(instruction, instructionSet, stopAllowDeadInstructions);
}
}
}
@NotNull
private Instruction getJumpTarget(@NotNull Label targetLabel) {
return ((PseudocodeLabel)targetLabel).resolveToInstruction();
}
@NotNull
private Instruction getNextPosition(int currentPosition) {
int targetPosition = currentPosition + 1;
assert targetPosition < mutableInstructionList.size() : currentPosition;
return mutableInstructionList.get(targetPosition);
}
} }
@@ -0,0 +1,423 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.cfg.pseudocode;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.Label;
import org.jetbrains.jet.lang.cfg.LoopInfo;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetExpression;
import java.util.*;
/**
* @author abreslav
* @author svtk
*/
public class PseudocodeImpl implements Pseudocode {
public class PseudocodeLabel implements Label {
private final String name;
private Integer targetInstructionIndex;
private PseudocodeLabel(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
@Override
public String toString() {
return name;
}
public Integer getTargetInstructionIndex() {
return targetInstructionIndex;
}
public void setTargetInstructionIndex(int targetInstructionIndex) {
this.targetInstructionIndex = targetInstructionIndex;
}
@Nullable
private List<Instruction> resolve() {
assert targetInstructionIndex != null;
return mutableInstructionList.subList(getTargetInstructionIndex(), mutableInstructionList.size());
}
public Instruction resolveToInstruction() {
assert targetInstructionIndex != null;
return mutableInstructionList.get(targetInstructionIndex);
}
}
private final List<Instruction> mutableInstructionList = new ArrayList<Instruction>();
private final List<Instruction> instructions = new ArrayList<Instruction>();
private List<Instruction> reversedInstructions = null;
private List<Instruction> deadInstructions;
private Set<LocalDeclarationInstruction> localDeclarations = null;
//todo getters
private final Map<JetElement, Instruction> representativeInstructions = new HashMap<JetElement, Instruction>();
private final Map<JetExpression, LoopInfo> loopInfo = Maps.newHashMap();
private final List<PseudocodeLabel> labels = new ArrayList<PseudocodeLabel>();
private final List<PseudocodeLabel> allowedDeadLabels = new ArrayList<PseudocodeLabel>();
private final List<PseudocodeLabel> stopAllowDeadLabels = new ArrayList<PseudocodeLabel>();
private final JetElement correspondingElement;
private SubroutineExitInstruction exitInstruction;
private SubroutineSinkInstruction sinkInstruction;
private SubroutineExitInstruction errorInstruction;
private boolean postPrecessed = false;
public PseudocodeImpl(JetElement correspondingElement) {
this.correspondingElement = correspondingElement;
}
@NotNull
@Override
public JetElement getCorrespondingElement() {
return correspondingElement;
}
@NotNull
@Override
public Set<LocalDeclarationInstruction> getLocalDeclarations() {
if (localDeclarations == null) {
localDeclarations = getLocalDeclarations(this);
}
return localDeclarations;
}
@NotNull
private static Set<LocalDeclarationInstruction> getLocalDeclarations(@NotNull Pseudocode pseudocode) {
Set<LocalDeclarationInstruction> localDeclarations = Sets.newLinkedHashSet();
for (Instruction instruction : pseudocode.getInstructions()) {
if (instruction instanceof LocalDeclarationInstruction) {
localDeclarations.add((LocalDeclarationInstruction) instruction);
localDeclarations.addAll(getLocalDeclarations(((LocalDeclarationInstruction)instruction).getBody()));
}
}
return localDeclarations;
}
/*package*/ PseudocodeLabel createLabel(String name) {
PseudocodeLabel label = new PseudocodeLabel(name);
labels.add(label);
return label;
}
/*package*/ void allowDead(Label label) {
allowedDeadLabels.add((PseudocodeLabel) label);
}
/*package*/ void stopAllowDead(Label label) {
stopAllowDeadLabels.add((PseudocodeLabel) label);
}
@Override
@NotNull
public List<Instruction> getInstructions() {
return instructions;
}
@NotNull
@Override
public List<Instruction> getReversedInstructions() {
if (reversedInstructions == null) {
LinkedHashSet<Instruction> traversedInstructions = Sets.newLinkedHashSet();
traverseInstructionsInReverseOrder(sinkInstruction, traversedInstructions);
reversedInstructions = Lists.newArrayList(traversedInstructions);
}
return reversedInstructions;
}
private static void traverseInstructionsInReverseOrder(@NotNull Instruction instruction,
@NotNull LinkedHashSet<Instruction> instructions) {
if (instructions.contains(instruction)) return;
instructions.add(instruction);
for (Instruction previousInstruction : instruction.getPreviousInstructions()) {
traverseInstructionsInReverseOrder(previousInstruction, instructions);
}
}
//for tests only
@NotNull
public List<Instruction> getAllInstructions() {
return mutableInstructionList;
}
@Override
@NotNull
public List<Instruction> getDeadInstructions() {
if (deadInstructions != null) {
return deadInstructions;
}
deadInstructions = Lists.newArrayList();
Collection<Instruction> allowedDeadInstructions = collectAllowedDeadInstructions();
for (Instruction instruction : mutableInstructionList) {
if (((InstructionImpl)instruction).isDead()) {
if (!allowedDeadInstructions.contains(instruction)) {
deadInstructions.add(instruction);
}
}
}
return deadInstructions;
}
//for tests only
@NotNull
public List<PseudocodeLabel> getLabels() {
return labels;
}
/*package*/ void addExitInstruction(SubroutineExitInstruction exitInstruction) {
addInstruction(exitInstruction);
assert this.exitInstruction == null;
this.exitInstruction = exitInstruction;
}
/*package*/ void addSinkInstruction(SubroutineSinkInstruction sinkInstruction) {
addInstruction(sinkInstruction);
assert this.sinkInstruction == null;
this.sinkInstruction = sinkInstruction;
}
/*package*/ void addErrorInstruction(SubroutineExitInstruction errorInstruction) {
addInstruction(errorInstruction);
assert this.errorInstruction == null;
this.errorInstruction = errorInstruction;
}
/*package*/ void addInstruction(Instruction instruction) {
mutableInstructionList.add(instruction);
instruction.setOwner(this);
if (instruction instanceof JetElementInstruction) {
JetElementInstruction elementInstruction = (JetElementInstruction) instruction;
representativeInstructions.put(elementInstruction.getElement(), instruction);
}
}
/*package*/ void recordLoopInfo(JetExpression expression, LoopInfo blockInfo) {
loopInfo.put(expression, blockInfo);
}
@Override
@NotNull
public SubroutineExitInstruction getExitInstruction() {
return exitInstruction;
}
@Override
@NotNull
public SubroutineSinkInstruction getSinkInstruction() {
return sinkInstruction;
}
@Override
@NotNull
public SubroutineEnterInstruction getEnterInstruction() {
return (SubroutineEnterInstruction) mutableInstructionList.get(0);
}
/*package*/ void bindLabel(Label label) {
((PseudocodeLabel) label).setTargetInstructionIndex(mutableInstructionList.size());
}
public void postProcess() {
if (postPrecessed) return;
postPrecessed = true;
errorInstruction.setSink(getSinkInstruction());
exitInstruction.setSink(getSinkInstruction());
for (int i = 0, instructionsSize = mutableInstructionList.size(); i < instructionsSize; i++) {
processInstruction(mutableInstructionList.get(i), i);
}
Set<Instruction> reachableInstructions = collectReachableInstructions();
for (Instruction instruction : mutableInstructionList) {
if (reachableInstructions.contains(instruction)) {
instructions.add(instruction);
}
}
markDeadInstructions();
}
private void processInstruction(Instruction instruction, final int currentPosition) {
instruction.accept(new InstructionVisitor() {
@Override
public void visitInstructionWithNext(InstructionWithNext instruction) {
instruction.setNext(getNextPosition(currentPosition));
}
@Override
public void visitJump(AbstractJumpInstruction instruction) {
instruction.setResolvedTarget(getJumpTarget(instruction.getTargetLabel()));
}
@Override
public void visitNondeterministicJump(NondeterministicJumpInstruction instruction) {
instruction.setNext(getNextPosition(currentPosition));
List<Label> targetLabels = instruction.getTargetLabels();
for (Label targetLabel : targetLabels) {
instruction.setResolvedTarget(targetLabel, getJumpTarget(targetLabel));
}
}
@Override
public void visitConditionalJump(ConditionalJumpInstruction instruction) {
Instruction nextInstruction = getNextPosition(currentPosition);
Instruction jumpTarget = getJumpTarget(instruction.getTargetLabel());
if (instruction.onTrue()) {
instruction.setNextOnFalse(nextInstruction);
instruction.setNextOnTrue(jumpTarget);
}
else {
instruction.setNextOnFalse(jumpTarget);
instruction.setNextOnTrue(nextInstruction);
}
visitJump(instruction);
}
@Override
public void visitLocalDeclarationInstruction(LocalDeclarationInstruction instruction) {
((PseudocodeImpl)instruction.getBody()).postProcess();
instruction.setNext(getSinkInstruction());
}
@Override
public void visitSubroutineExit(SubroutineExitInstruction instruction) {
// Nothing
}
@Override
public void visitSubroutineSink(SubroutineSinkInstruction instruction) {
// Nothing
}
@Override
public void visitInstruction(Instruction instruction) {
throw new UnsupportedOperationException(instruction.toString());
}
});
}
private Set<Instruction> collectReachableInstructions() {
Set<Instruction> visited = Sets.newHashSet();
traverseNextInstructions(getEnterInstruction(), visited);
if (!visited.contains(getExitInstruction())) {
visited.add(getExitInstruction());
}
if (!visited.contains(errorInstruction)) {
visited.add(errorInstruction);
}
if (!visited.contains(getSinkInstruction())) {
visited.add(getSinkInstruction());
}
return visited;
}
private void traverseNextInstructions(@NotNull Instruction instruction, @NotNull Set<Instruction> visited) {
if (visited.contains(instruction)) return;
visited.add(instruction);
for (Instruction nextInstruction : instruction.getNextInstructions()) {
if (nextInstruction == null) continue; //todo it might be null on incomplete code
traverseNextInstructions(nextInstruction, visited);
}
}
private void markDeadInstructions() {
Set<Instruction> instructionSet = Sets.newHashSet(instructions);
for (Instruction instruction : mutableInstructionList) {
if (!instructionSet.contains(instruction)) {
((InstructionImpl)instruction).die();
for (Instruction nextInstruction : instruction.getNextInstructions()) {
nextInstruction.getPreviousInstructions().remove(instruction);
}
}
}
}
@NotNull
private Set<Instruction> prepareAllowedDeadInstructions() {
Set<Instruction> allowedDeadStartInstructions = Sets.newHashSet();
for (PseudocodeLabel allowedDeadLabel : allowedDeadLabels) {
Instruction allowedDeadInstruction = getJumpTarget(allowedDeadLabel);
if (((InstructionImpl)allowedDeadInstruction).isDead()) {
allowedDeadStartInstructions.add(allowedDeadInstruction);
}
}
return allowedDeadStartInstructions;
}
@NotNull
private Set<Instruction> prepareStopAllowedDeadInstructions() {
Set<Instruction> stopAllowedDeadInstructions = Sets.newHashSet();
for (PseudocodeLabel stopAllowedDeadLabel : stopAllowDeadLabels) {
Instruction stopAllowDeadInsruction = getJumpTarget(stopAllowedDeadLabel);
if (((InstructionImpl)stopAllowDeadInsruction).isDead()) {
stopAllowedDeadInstructions.add(stopAllowDeadInsruction);
}
}
return stopAllowedDeadInstructions;
}
@NotNull
private Collection<Instruction> collectAllowedDeadInstructions() {
Set<Instruction> allowedDeadStartInstructions = prepareAllowedDeadInstructions();
Set<Instruction> stopAllowDeadInstructions = prepareStopAllowedDeadInstructions();
Set<Instruction> allowedDeadInstructions = Sets.newHashSet();
for (Instruction allowedDeadStartInstruction : allowedDeadStartInstructions) {
collectAllowedDeadInstructions(allowedDeadStartInstruction, allowedDeadInstructions, stopAllowDeadInstructions);
}
return allowedDeadInstructions;
}
private void collectAllowedDeadInstructions(Instruction allowedDeadInstruction, Set<Instruction> instructionSet, Set<Instruction> stopAllowDeadInstructions) {
if (instructionSet.contains(allowedDeadInstruction) || stopAllowDeadInstructions.contains(allowedDeadInstruction)) return;
if (((InstructionImpl)allowedDeadInstruction).isDead()) {
instructionSet.add(allowedDeadInstruction);
for (Instruction instruction : allowedDeadInstruction.getNextInstructions()) {
collectAllowedDeadInstructions(instruction, instructionSet, stopAllowDeadInstructions);
}
}
}
@NotNull
private Instruction getJumpTarget(@NotNull Label targetLabel) {
return ((PseudocodeLabel)targetLabel).resolveToInstruction();
}
@NotNull
private Instruction getNextPosition(int currentPosition) {
int targetPosition = currentPosition + 1;
assert targetPosition < mutableInstructionList.size() : currentPosition;
return mutableInstructionList.get(targetPosition);
}
}
@@ -0,0 +1,86 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.cfg.pseudocode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.JetControlFlowProcessor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.psi.JetDeclaration;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.util.slicedmap.ReadOnlySlice;
import org.jetbrains.jet.util.slicedmap.WritableSlice;
import java.util.Collection;
/**
* @author svtk
*/
public class PseudocodeUtil {
public static Pseudocode generatePseudocode(@NotNull JetDeclaration declaration, @NotNull final BindingContext bindingContext) {
BindingTrace mockTrace = new BindingTrace() {
@Override
public BindingContext getBindingContext() {
return bindingContext;
}
@Override
public <K, V> void record(WritableSlice<K, V> slice, K key, V value) {
}
@Override
public <K> void record(WritableSlice<K, Boolean> slice, K key) {
}
@Override
public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
return bindingContext.get(slice, key);
}
@NotNull
@Override
public <K, V> Collection<K> getKeys(WritableSlice<K, V> slice) {
return bindingContext.getKeys(slice);
}
@Override
public void report(@NotNull Diagnostic diagnostic) {
}
};
return new JetControlFlowProcessor(mockTrace).generatePseudocode(declaration);
}
@Nullable
public static VariableDescriptor extractVariableDescriptorIfAny(@NotNull Instruction instruction, boolean onlyReference, @NotNull BindingContext bindingContext) {
JetElement element = null;
if (instruction instanceof ReadValueInstruction) {
element = ((ReadValueInstruction) instruction).getElement();
}
else if (instruction instanceof WriteValueInstruction) {
element = ((WriteValueInstruction) instruction).getlValue();
}
else if (instruction instanceof VariableDeclarationInstruction) {
element = ((VariableDeclarationInstruction) instruction).getVariableDeclarationElement();
}
return BindingContextUtils.extractVariableDescriptorIfAny(bindingContext, element, onlyReference);
}
}
@@ -46,10 +46,8 @@ public class SubroutineExitInstruction extends InstructionImpl {
@NotNull @NotNull
@Override @Override
public Collection<Instruction> getNextInstructions() { public Collection<Instruction> getNextInstructions() {
if (sinkInstruction != null) { assert sinkInstruction != null;
return Collections.<Instruction>singleton(sinkInstruction); return Collections.<Instruction>singleton(sinkInstruction);
}
return Collections.emptyList();
} }
@Override @Override
@@ -48,7 +48,7 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl
} }
public final ClassDescriptorImpl initialize(boolean sealed, public final ClassDescriptorImpl initialize(boolean sealed,
@NotNull List<TypeParameterDescriptor> typeParameters, @NotNull List<? extends TypeParameterDescriptor> typeParameters,
@NotNull Collection<JetType> supertypes, @NotNull Collection<JetType> supertypes,
@NotNull JetScope memberDeclarations, @NotNull JetScope memberDeclarations,
@NotNull Set<ConstructorDescriptor> constructors, @NotNull Set<ConstructorDescriptor> constructors,
@@ -57,7 +57,7 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl
} }
public final ClassDescriptorImpl initialize(boolean sealed, public final ClassDescriptorImpl initialize(boolean sealed,
@NotNull List<TypeParameterDescriptor> typeParameters, @NotNull List<? extends TypeParameterDescriptor> typeParameters,
@NotNull Collection<JetType> supertypes, @NotNull Collection<JetType> supertypes,
@NotNull JetScope memberDeclarations, @NotNull JetScope memberDeclarations,
@NotNull Set<ConstructorDescriptor> constructors, @NotNull Set<ConstructorDescriptor> constructors,
@@ -77,12 +77,12 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorImpl i
protected FunctionDescriptorImpl initialize( protected FunctionDescriptorImpl initialize(
@Nullable JetType receiverType, @Nullable JetType receiverType,
@NotNull ReceiverDescriptor expectedThisObject, @NotNull ReceiverDescriptor expectedThisObject,
@NotNull List<TypeParameterDescriptor> typeParameters, @NotNull List<? extends TypeParameterDescriptor> typeParameters,
@NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters, @NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters,
@Nullable JetType unsubstitutedReturnType, @Nullable JetType unsubstitutedReturnType,
@Nullable Modality modality, @Nullable Modality modality,
@NotNull Visibility visibility) { @NotNull Visibility visibility) {
this.typeParameters = typeParameters; this.typeParameters = Lists.newArrayList(typeParameters);
this.unsubstitutedValueParameters = unsubstitutedValueParameters; this.unsubstitutedValueParameters = unsubstitutedValueParameters;
this.unsubstitutedReturnType = unsubstitutedReturnType; this.unsubstitutedReturnType = unsubstitutedReturnType;
this.modality = modality; this.modality = modality;
@@ -126,7 +126,7 @@ public class FunctionDescriptorUtil {
assert JetStandardClasses.isFunctionType(functionType); assert JetStandardClasses.isFunctionType(functionType);
functionDescriptor.initialize(JetStandardClasses.getReceiverType(functionType), functionDescriptor.initialize(JetStandardClasses.getReceiverType(functionType),
expectedThisObject, expectedThisObject,
Collections.<TypeParameterDescriptor>emptyList(), Collections.<TypeParameterDescriptorImpl>emptyList(),
JetStandardClasses.getValueParameters(functionDescriptor, functionType), JetStandardClasses.getValueParameters(functionDescriptor, functionType),
JetStandardClasses.getReturnTypeFromFunctionType(functionType), JetStandardClasses.getReturnTypeFromFunctionType(functionType),
modality, modality,
@@ -112,17 +112,17 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
setType(outType, Collections.<TypeParameterDescriptor>emptyList(), expectedThisObject, receiverType); setType(outType, Collections.<TypeParameterDescriptor>emptyList(), expectedThisObject, receiverType);
} }
public void setType(@NotNull JetType outType, @NotNull List<TypeParameterDescriptor> typeParameters, @NotNull ReceiverDescriptor expectedThisObject, @Nullable JetType receiverType) { public void setType(@NotNull JetType outType, @NotNull List<? extends TypeParameterDescriptor> typeParameters, @NotNull ReceiverDescriptor expectedThisObject, @Nullable JetType receiverType) {
ReceiverDescriptor receiver = receiverType == null ReceiverDescriptor receiver = receiverType == null
? NO_RECEIVER ? NO_RECEIVER
: new ExtensionReceiver(this, receiverType); : new ExtensionReceiver(this, receiverType);
setType(outType, typeParameters, expectedThisObject, receiver); setType(outType, typeParameters, expectedThisObject, receiver);
} }
public void setType(@NotNull JetType outType, @NotNull List<TypeParameterDescriptor> typeParameters, @NotNull ReceiverDescriptor expectedThisObject, @NotNull ReceiverDescriptor receiver) { public void setType(@NotNull JetType outType, @NotNull List<? extends TypeParameterDescriptor> typeParameters, @NotNull ReceiverDescriptor expectedThisObject, @NotNull ReceiverDescriptor receiver) {
setOutType(outType); setOutType(outType);
this.typeParameters = typeParameters; this.typeParameters = Lists.newArrayList(typeParameters);
this.receiver = receiver; this.receiver = receiver;
this.expectedThisObject = expectedThisObject; this.expectedThisObject = expectedThisObject;
@@ -54,7 +54,7 @@ public class SimpleFunctionDescriptorImpl extends FunctionDescriptorImpl impleme
public SimpleFunctionDescriptorImpl initialize( public SimpleFunctionDescriptorImpl initialize(
@Nullable JetType receiverType, @Nullable JetType receiverType,
@NotNull ReceiverDescriptor expectedThisObject, @NotNull ReceiverDescriptor expectedThisObject,
@NotNull List<TypeParameterDescriptor> typeParameters, @NotNull List<? extends TypeParameterDescriptor> typeParameters,
@NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters, @NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters,
@Nullable JetType unsubstitutedReturnType, @Nullable JetType unsubstitutedReturnType,
@Nullable Modality modality, @Nullable Modality modality,
@@ -16,251 +16,45 @@
package org.jetbrains.jet.lang.descriptors; package org.jetbrains.jet.lang.descriptors;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.types.TypeConstructor;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.types.TypeSubstitutor;
import org.jetbrains.jet.lang.resolve.scopes.LazyScopeAdapter; import org.jetbrains.jet.lang.types.Variance;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
import org.jetbrains.jet.resolve.DescriptorRenderer;
import org.jetbrains.jet.util.lazy.LazyValue;
import java.util.Collections;
import java.util.List;
import java.util.Set; import java.util.Set;
/** /**
* @author abreslav * @author abreslav
*/ */
public class TypeParameterDescriptor extends DeclarationDescriptorImpl implements ClassifierDescriptor { public interface TypeParameterDescriptor extends ClassifierDescriptor {
public static TypeParameterDescriptor createWithDefaultBound( boolean isReified();
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull List<AnnotationDescriptor> annotations,
boolean reified,
@NotNull Variance variance,
@NotNull Name name,
int index) {
TypeParameterDescriptor typeParameterDescriptor = createForFurtherModification(containingDeclaration, annotations, reified, variance, name, index);
typeParameterDescriptor.addUpperBound(JetStandardClasses.getDefaultBound());
typeParameterDescriptor.setInitialized();
return typeParameterDescriptor;
}
public static TypeParameterDescriptor createForFurtherModification( Variance getVariance();
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull List<AnnotationDescriptor> annotations,
boolean reified,
@NotNull Variance variance,
@NotNull Name name,
int index) {
return new TypeParameterDescriptor(containingDeclaration, annotations, reified, variance, name, index);
}
// 0-based
private final int index;
private final Variance variance;
private final Set<JetType> upperBounds;
private JetType upperBoundsAsType;
private final TypeConstructor typeConstructor;
private JetType defaultType;
private final Set<JetType> classObjectUpperBounds = Sets.newLinkedHashSet();
private JetType classObjectBoundsAsType;
private final boolean reified;
private boolean initialized = false;
private TypeParameterDescriptor(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull List<AnnotationDescriptor> annotations,
boolean reified,
@NotNull Variance variance,
@NotNull Name name,
int index) {
super(containingDeclaration, annotations, name);
this.index = index;
this.variance = variance;
this.upperBounds = Sets.newLinkedHashSet();
this.reified = reified;
// TODO: Should we actually pass the annotations on to the type constructor?
this.typeConstructor = new TypeConstructorImpl(
this,
annotations,
false,
name.getName(),
Collections.<TypeParameterDescriptor>emptyList(),
upperBounds);
}
private void checkInitialized() {
if (!initialized) {
throw new IllegalStateException("Type parameter descriptor in not initialized: " + nameForAssertions());
}
}
private void checkUninitialized() {
if (initialized) {
throw new IllegalStateException("Type parameter descriptor is already initialized: " + nameForAssertions());
}
}
private String nameForAssertions() {
DeclarationDescriptor owner = getContainingDeclaration();
return getName() + " declared in " + (owner == null ? "<no owner>" : owner.getName());
}
public void setInitialized() {
checkUninitialized();
initialized = true;
}
public boolean isReified() {
checkInitialized();
return reified;
}
public Variance getVariance() {
checkInitialized();
return variance;
}
public void addUpperBound(@NotNull JetType bound) {
checkUninitialized();
doAddUpperBound(bound);
}
private void doAddUpperBound(JetType bound) {
upperBounds.add(bound); // TODO : Duplicates?
}
public void addDefaultUpperBound() {
checkUninitialized();
if (upperBounds.isEmpty()) {
doAddUpperBound(JetStandardClasses.getDefaultBound());
}
}
@NotNull @NotNull
public Set<JetType> getUpperBounds() { Set<JetType> getUpperBounds();
checkInitialized();
return upperBounds;
}
@NotNull @NotNull
public JetType getUpperBoundsAsType() { JetType getUpperBoundsAsType();
checkInitialized();
if (upperBoundsAsType == null) {
assert upperBounds != null : "Upper bound list is null in " + getName();
assert upperBounds.size() > 0 : "Upper bound list is empty in " + getName();
upperBoundsAsType = TypeUtils.intersect(JetTypeChecker.INSTANCE, upperBounds);
if (upperBoundsAsType == null) {
upperBoundsAsType = JetStandardClasses.getNothingType();
}
}
return upperBoundsAsType;
}
@NotNull @NotNull
public Set<JetType> getLowerBounds() { Set<JetType> getLowerBounds();
//checkInitialized();
return Collections.singleton(JetStandardClasses.getNothingType());
}
@NotNull @NotNull
public JetType getLowerBoundsAsType() { JetType getLowerBoundsAsType();
checkInitialized();
return JetStandardClasses.getNothingType();
}
@NotNull @NotNull
@Override @Override
public TypeConstructor getTypeConstructor() { TypeConstructor getTypeConstructor();
//checkInitialized();
return typeConstructor;
}
@Override
public String toString() {
try {
return DescriptorRenderer.TEXT.render(this);
} catch (Exception e) {
return this.getClass().getName() + "@" + System.identityHashCode(this);
}
}
@NotNull @NotNull
@Override @Override
@Deprecated // Use the static method TypeParameterDescriptor.substitute() @Deprecated // Use the static method TypeParameterDescriptor.substitute()
public TypeParameterDescriptor substitute(TypeSubstitutor substitutor) { TypeParameterDescriptor substitute(TypeSubstitutor substitutor);
throw new UnsupportedOperationException();
}
@Override int getIndex();
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
checkInitialized();
return visitor.visitTypeParameterDescriptor(this, data);
}
@NotNull @NotNull
@Override TypeParameterDescriptor copy(@NotNull DeclarationDescriptor newOwner);
public JetType getDefaultType() {
//checkInitialized();
if (defaultType == null) {
defaultType = new JetTypeImpl(
Collections.<AnnotationDescriptor>emptyList(),
getTypeConstructor(),
TypeUtils.hasNullableLowerBound(this),
Collections.<TypeProjection>emptyList(),
new LazyScopeAdapter(new LazyValue<JetScope>() {
@Override
protected JetScope compute() {
return getUpperBoundsAsType().getMemberScope();
}
}));
}
return defaultType;
}
@Override
public JetType getClassObjectType() {
checkInitialized();
if (classObjectUpperBounds.isEmpty()) return null;
if (classObjectBoundsAsType == null) {
classObjectBoundsAsType = TypeUtils.intersect(JetTypeChecker.INSTANCE, classObjectUpperBounds);
if (classObjectBoundsAsType == null) {
classObjectBoundsAsType = JetStandardClasses.getNothingType();
}
}
return classObjectBoundsAsType;
}
@Override
public boolean isClassObjectAValue() {
return true;
}
public void addClassObjectBound(@NotNull JetType bound) {
checkUninitialized();
classObjectUpperBounds.add(bound); // TODO : Duplicates?
}
public int getIndex() {
checkInitialized();
return index;
}
@NotNull
public TypeParameterDescriptor copy(@NotNull DeclarationDescriptor newOwner) {
TypeParameterDescriptor copy = new TypeParameterDescriptor(newOwner, Lists.newArrayList(getAnnotations()), reified, variance, getName(), index);
copy.upperBounds.addAll(this.upperBounds);
copy.initialized = this.initialized;
return copy;
}
} }
@@ -0,0 +1,275 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.descriptors;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.LazyScopeAdapter;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
import org.jetbrains.jet.resolve.DescriptorRenderer;
import org.jetbrains.jet.util.lazy.LazyValue;
import java.util.Collections;
import java.util.List;
import java.util.Set;
/**
* @author abreslav
*/
public class TypeParameterDescriptorImpl extends DeclarationDescriptorImpl implements TypeParameterDescriptor {
public static TypeParameterDescriptor createWithDefaultBound(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull List<AnnotationDescriptor> annotations,
boolean reified,
@NotNull Variance variance,
@NotNull Name name,
int index) {
TypeParameterDescriptorImpl typeParameterDescriptor = createForFurtherModification(containingDeclaration, annotations, reified, variance, name, index);
typeParameterDescriptor.addUpperBound(JetStandardClasses.getDefaultBound());
typeParameterDescriptor.setInitialized();
return typeParameterDescriptor;
}
public static TypeParameterDescriptorImpl createForFurtherModification(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull List<AnnotationDescriptor> annotations,
boolean reified,
@NotNull Variance variance,
@NotNull Name name,
int index) {
return new TypeParameterDescriptorImpl(containingDeclaration, annotations, reified, variance, name, index);
}
// 0-based
private final int index;
private final Variance variance;
private final Set<JetType> upperBounds;
private JetType upperBoundsAsType;
private final TypeConstructor typeConstructor;
private JetType defaultType;
private final Set<JetType> classObjectUpperBounds = Sets.newLinkedHashSet();
private JetType classObjectBoundsAsType;
private final boolean reified;
private boolean initialized = false;
private TypeParameterDescriptorImpl(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull List<AnnotationDescriptor> annotations,
boolean reified,
@NotNull Variance variance,
@NotNull Name name,
int index) {
super(containingDeclaration, annotations, name);
this.index = index;
this.variance = variance;
this.upperBounds = Sets.newLinkedHashSet();
this.reified = reified;
// TODO: Should we actually pass the annotations on to the type constructor?
this.typeConstructor = new TypeConstructorImpl(
this,
annotations,
false,
name.getName(),
Collections.<TypeParameterDescriptor>emptyList(),
upperBounds);
}
private void checkInitialized() {
if (!initialized) {
throw new IllegalStateException("Type parameter descriptor in not initialized: " + nameForAssertions());
}
}
private void checkUninitialized() {
if (initialized) {
throw new IllegalStateException("Type parameter descriptor is already initialized: " + nameForAssertions());
}
}
private String nameForAssertions() {
DeclarationDescriptor owner = getContainingDeclaration();
return getName() + " declared in " + (owner == null ? "<no owner>" : owner.getName());
}
public void setInitialized() {
checkUninitialized();
initialized = true;
}
@Override
public boolean isReified() {
checkInitialized();
return reified;
}
@Override
public Variance getVariance() {
checkInitialized();
return variance;
}
public void addUpperBound(@NotNull JetType bound) {
checkUninitialized();
doAddUpperBound(bound);
}
private void doAddUpperBound(JetType bound) {
upperBounds.add(bound); // TODO : Duplicates?
}
public void addDefaultUpperBound() {
checkUninitialized();
if (upperBounds.isEmpty()) {
doAddUpperBound(JetStandardClasses.getDefaultBound());
}
}
@Override
@NotNull
public Set<JetType> getUpperBounds() {
checkInitialized();
return upperBounds;
}
@Override
@NotNull
public JetType getUpperBoundsAsType() {
checkInitialized();
if (upperBoundsAsType == null) {
assert upperBounds != null : "Upper bound list is null in " + getName();
assert upperBounds.size() > 0 : "Upper bound list is empty in " + getName();
upperBoundsAsType = TypeUtils.intersect(JetTypeChecker.INSTANCE, upperBounds);
if (upperBoundsAsType == null) {
upperBoundsAsType = JetStandardClasses.getNothingType();
}
}
return upperBoundsAsType;
}
@Override
@NotNull
public Set<JetType> getLowerBounds() {
//checkInitialized();
return Collections.singleton(JetStandardClasses.getNothingType());
}
@Override
@NotNull
public JetType getLowerBoundsAsType() {
checkInitialized();
return JetStandardClasses.getNothingType();
}
@NotNull
@Override
public TypeConstructor getTypeConstructor() {
//checkInitialized();
return typeConstructor;
}
@Override
public String toString() {
try {
return DescriptorRenderer.TEXT.render(this);
} catch (Exception e) {
return this.getClass().getName() + "@" + System.identityHashCode(this);
}
}
@NotNull
@Override
@Deprecated // Use the static method TypeParameterDescriptor.substitute()
public TypeParameterDescriptor substitute(TypeSubstitutor substitutor) {
throw new UnsupportedOperationException();
}
@Override
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
checkInitialized();
return visitor.visitTypeParameterDescriptor(this, data);
}
@NotNull
@Override
public JetType getDefaultType() {
//checkInitialized();
if (defaultType == null) {
defaultType = new JetTypeImpl(
Collections.<AnnotationDescriptor>emptyList(),
getTypeConstructor(),
TypeUtils.hasNullableLowerBound(this),
Collections.<TypeProjection>emptyList(),
new LazyScopeAdapter(new LazyValue<JetScope>() {
@Override
protected JetScope compute() {
return getUpperBoundsAsType().getMemberScope();
}
}));
}
return defaultType;
}
@Override
public JetType getClassObjectType() {
checkInitialized();
if (classObjectUpperBounds.isEmpty()) return null;
if (classObjectBoundsAsType == null) {
classObjectBoundsAsType = TypeUtils.intersect(JetTypeChecker.INSTANCE, classObjectUpperBounds);
if (classObjectBoundsAsType == null) {
classObjectBoundsAsType = JetStandardClasses.getNothingType();
}
}
return classObjectBoundsAsType;
}
@Override
public boolean isClassObjectAValue() {
return true;
}
public void addClassObjectBound(@NotNull JetType bound) {
checkUninitialized();
classObjectUpperBounds.add(bound); // TODO : Duplicates?
}
@Override
public int getIndex() {
checkInitialized();
return index;
}
@Override
@NotNull
public TypeParameterDescriptor copy(@NotNull DeclarationDescriptor newOwner) {
TypeParameterDescriptorImpl
copy = new TypeParameterDescriptorImpl(newOwner, Lists.newArrayList(getAnnotations()), reified, variance, getName(), index);
copy.upperBounds.addAll(this.upperBounds);
copy.initialized = this.initialized;
return copy;
}
}
@@ -16,22 +16,15 @@
package org.jetbrains.jet.lang.resolve; package org.jetbrains.jet.lang.resolve;
import com.google.common.base.Predicate;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiErrorElement; import com.intellij.psi.PsiErrorElement;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.ModuleConfiguration;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.diagnostics.DiagnosticHolder; import org.jetbrains.jet.lang.diagnostics.DiagnosticHolder;
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
import org.jetbrains.jet.lang.psi.JetFile;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.List; import java.util.List;
/** /**
@@ -18,7 +18,6 @@ package org.jetbrains.jet.lang.resolve;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider; import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.descriptors.PropertyAccessorDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyAccessorDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor; import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
@@ -37,7 +36,6 @@ import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
public class ControlFlowAnalyzer { public class ControlFlowAnalyzer {
private TopDownAnalysisParameters topDownAnalysisParameters; private TopDownAnalysisParameters topDownAnalysisParameters;
private BindingTrace trace; private BindingTrace trace;
private JetControlFlowDataTraceFactory flowDataTraceFactory;
@Inject @Inject
public void setTopDownAnalysisParameters(TopDownAnalysisParameters topDownAnalysisParameters) { public void setTopDownAnalysisParameters(TopDownAnalysisParameters topDownAnalysisParameters) {
@@ -49,11 +47,6 @@ public class ControlFlowAnalyzer {
this.trace = trace; this.trace = trace;
} }
@Inject
public void setFlowDataTraceFactory(JetControlFlowDataTraceFactory flowDataTraceFactory) {
this.flowDataTraceFactory = flowDataTraceFactory;
}
public void process(@NotNull BodiesResolveContext bodiesResolveContext) { public void process(@NotNull BodiesResolveContext bodiesResolveContext) {
for (JetClass aClass : bodiesResolveContext.getClasses().keySet()) { for (JetClass aClass : bodiesResolveContext.getClasses().keySet()) {
if (!bodiesResolveContext.completeAnalysisNeeded(aClass)) continue; if (!bodiesResolveContext.completeAnalysisNeeded(aClass)) continue;
@@ -86,8 +79,8 @@ public class ControlFlowAnalyzer {
private void checkClassOrObject(JetClassOrObject klass) { private void checkClassOrObject(JetClassOrObject klass) {
// A pseudocode of class initialization corresponds to a class // A pseudocode of class initialization corresponds to a class
JetFlowInformationProvider flowInformationProvider = new JetFlowInformationProvider((JetDeclaration) klass, (JetExpression) klass, flowDataTraceFactory, trace); JetFlowInformationProvider flowInformationProvider = new JetFlowInformationProvider((JetDeclaration) klass, trace);
flowInformationProvider.markUninitializedVariables((JetElement) klass, topDownAnalysisParameters.isDeclaredLocally()); flowInformationProvider.markUninitializedVariables(topDownAnalysisParameters.isDeclaredLocally());
} }
private void checkProperty(JetProperty property, PropertyDescriptor propertyDescriptor) { private void checkProperty(JetProperty property, PropertyDescriptor propertyDescriptor) {
@@ -105,16 +98,16 @@ public class ControlFlowAnalyzer {
JetExpression bodyExpression = function.getBodyExpression(); JetExpression bodyExpression = function.getBodyExpression();
if (bodyExpression == null) return; if (bodyExpression == null) return;
JetFlowInformationProvider flowInformationProvider = new JetFlowInformationProvider((JetDeclaration) function, bodyExpression, flowDataTraceFactory, trace); JetFlowInformationProvider flowInformationProvider = new JetFlowInformationProvider((JetDeclaration) function, trace);
flowInformationProvider.checkDefiniteReturn(function, expectedReturnType); flowInformationProvider.checkDefiniteReturn(expectedReturnType);
// Property accessor is checked through initialization of a class check (at 'checkClassOrObject') // Property accessor is checked through initialization of a class check (at 'checkClassOrObject')
boolean isPropertyAccessor = function instanceof JetPropertyAccessor; boolean isPropertyAccessor = function instanceof JetPropertyAccessor;
flowInformationProvider.markUninitializedVariables(function.asElement(), topDownAnalysisParameters.isDeclaredLocally() || isPropertyAccessor); flowInformationProvider.markUninitializedVariables(topDownAnalysisParameters.isDeclaredLocally() || isPropertyAccessor);
flowInformationProvider.markUnusedVariables(function.asElement()); flowInformationProvider.markUnusedVariables();
flowInformationProvider.markUnusedLiteralsInBlock(function.asElement()); flowInformationProvider.markUnusedLiteralsInBlock();
} }
} }
@@ -79,7 +79,7 @@ public class DescriptorResolver {
List<TypeParameterDescriptor> typeParameters = Lists.newArrayList(); List<TypeParameterDescriptor> typeParameters = Lists.newArrayList();
int index = 0; int index = 0;
for (JetTypeParameter typeParameter : classElement.getTypeParameters()) { for (JetTypeParameter typeParameter : classElement.getTypeParameters()) {
TypeParameterDescriptor typeParameterDescriptor = TypeParameterDescriptor.createForFurtherModification( TypeParameterDescriptor typeParameterDescriptor = TypeParameterDescriptorImpl.createForFurtherModification(
descriptor, descriptor,
annotationResolver.createAnnotationStubs(typeParameter.getModifierList(), trace), annotationResolver.createAnnotationStubs(typeParameter.getModifierList(), trace),
!typeParameter.hasModifier(JetTokens.ERASED_KEYWORD), !typeParameter.hasModifier(JetTokens.ERASED_KEYWORD),
@@ -175,7 +175,7 @@ public class DescriptorResolver {
WritableScope innerScope = new WritableScopeImpl(scope, functionDescriptor, new TraceBasedRedeclarationHandler(trace)).setDebugName("Function descriptor header scope"); WritableScope innerScope = new WritableScopeImpl(scope, functionDescriptor, new TraceBasedRedeclarationHandler(trace)).setDebugName("Function descriptor header scope");
innerScope.addLabeledDeclaration(functionDescriptor); innerScope.addLabeledDeclaration(functionDescriptor);
List<TypeParameterDescriptor> typeParameterDescriptors = resolveTypeParameters(functionDescriptor, innerScope, function.getTypeParameters(), trace); List<TypeParameterDescriptorImpl> typeParameterDescriptors = resolveTypeParameters(functionDescriptor, innerScope, function.getTypeParameters(), trace);
innerScope.changeLockLevel(WritableScope.LockLevel.BOTH); innerScope.changeLockLevel(WritableScope.LockLevel.BOTH);
resolveGenericBounds(function, innerScope, typeParameterDescriptors, trace); resolveGenericBounds(function, innerScope, typeParameterDescriptors, trace);
@@ -307,8 +307,8 @@ public class DescriptorResolver {
} }
} }
public List<TypeParameterDescriptor> resolveTypeParameters(DeclarationDescriptor containingDescriptor, WritableScope extensibleScope, List<JetTypeParameter> typeParameters, BindingTrace trace) { public List<TypeParameterDescriptorImpl> resolveTypeParameters(DeclarationDescriptor containingDescriptor, WritableScope extensibleScope, List<JetTypeParameter> typeParameters, BindingTrace trace) {
List<TypeParameterDescriptor> result = new ArrayList<TypeParameterDescriptor>(); List<TypeParameterDescriptorImpl> result = new ArrayList<TypeParameterDescriptorImpl>();
for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) { for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) {
JetTypeParameter typeParameter = typeParameters.get(i); JetTypeParameter typeParameter = typeParameters.get(i);
result.add(resolveTypeParameter(containingDescriptor, extensibleScope, typeParameter, i, trace)); result.add(resolveTypeParameter(containingDescriptor, extensibleScope, typeParameter, i, trace));
@@ -316,12 +316,12 @@ public class DescriptorResolver {
return result; return result;
} }
private TypeParameterDescriptor resolveTypeParameter(DeclarationDescriptor containingDescriptor, WritableScope extensibleScope, JetTypeParameter typeParameter, int index, BindingTrace trace) { private TypeParameterDescriptorImpl resolveTypeParameter(DeclarationDescriptor containingDescriptor, WritableScope extensibleScope, JetTypeParameter typeParameter, int index, BindingTrace trace) {
// JetTypeReference extendsBound = typeParameter.getExtendsBound(); // JetTypeReference extendsBound = typeParameter.getExtendsBound();
// JetType bound = extendsBound == null // JetType bound = extendsBound == null
// ? JetStandardClasses.getDefaultBound() // ? JetStandardClasses.getDefaultBound()
// : typeResolver.resolveType(extensibleScope, extendsBound); // : typeResolver.resolveType(extensibleScope, extendsBound);
TypeParameterDescriptor typeParameterDescriptor = TypeParameterDescriptor.createForFurtherModification( TypeParameterDescriptorImpl typeParameterDescriptor = TypeParameterDescriptorImpl.createForFurtherModification(
containingDescriptor, containingDescriptor,
annotationResolver.createAnnotationStubs(typeParameter.getModifierList(), trace), annotationResolver.createAnnotationStubs(typeParameter.getModifierList(), trace),
!typeParameter.hasModifier(JetTokens.ERASED_KEYWORD), !typeParameter.hasModifier(JetTokens.ERASED_KEYWORD),
@@ -346,14 +346,15 @@ public class DescriptorResolver {
isClassObjectConstraint = classObjectConstraint; isClassObjectConstraint = classObjectConstraint;
} }
} }
public void resolveGenericBounds(@NotNull JetTypeParameterListOwner declaration, JetScope scope, List<TypeParameterDescriptor> parameters, BindingTrace trace) {
public void resolveGenericBounds(@NotNull JetTypeParameterListOwner declaration, JetScope scope, List<TypeParameterDescriptorImpl> parameters, BindingTrace trace) {
List<UpperBoundCheckerTask> deferredUpperBoundCheckerTasks = Lists.newArrayList(); List<UpperBoundCheckerTask> deferredUpperBoundCheckerTasks = Lists.newArrayList();
List<JetTypeParameter> typeParameters = declaration.getTypeParameters(); List<JetTypeParameter> typeParameters = declaration.getTypeParameters();
Map<Name, TypeParameterDescriptor> parameterByName = Maps.newHashMap(); Map<Name, TypeParameterDescriptorImpl> parameterByName = Maps.newHashMap();
for (int i = 0; i < typeParameters.size(); i++) { for (int i = 0; i < typeParameters.size(); i++) {
JetTypeParameter jetTypeParameter = typeParameters.get(i); JetTypeParameter jetTypeParameter = typeParameters.get(i);
TypeParameterDescriptor typeParameterDescriptor = parameters.get(i); TypeParameterDescriptorImpl typeParameterDescriptor = parameters.get(i);
parameterByName.put(typeParameterDescriptor.getName(), typeParameterDescriptor); parameterByName.put(typeParameterDescriptor.getName(), typeParameterDescriptor);
@@ -373,7 +374,7 @@ public class DescriptorResolver {
if (referencedName == null) { if (referencedName == null) {
continue; continue;
} }
TypeParameterDescriptor typeParameterDescriptor = parameterByName.get(referencedName); TypeParameterDescriptorImpl typeParameterDescriptor = parameterByName.get(referencedName);
JetTypeReference boundTypeReference = constraint.getBoundTypeReference(); JetTypeReference boundTypeReference = constraint.getBoundTypeReference();
JetType bound = null; JetType bound = null;
if (boundTypeReference != null) { if (boundTypeReference != null) {
@@ -405,7 +406,7 @@ public class DescriptorResolver {
} }
} }
for (TypeParameterDescriptor parameter : parameters) { for (TypeParameterDescriptorImpl parameter : parameters) {
parameter.addDefaultUpperBound(); parameter.addDefaultUpperBound();
parameter.setInitialized(); parameter.setInitialized();
@@ -551,7 +552,7 @@ public class DescriptorResolver {
return variableDescriptor; return variableDescriptor;
} }
public JetScope getPropertyDeclarationInnerScope(@NotNull JetScope outerScope, @NotNull List<TypeParameterDescriptor> typeParameters, public JetScope getPropertyDeclarationInnerScope(@NotNull JetScope outerScope, @NotNull List<? extends TypeParameterDescriptor> typeParameters,
@NotNull ReceiverDescriptor receiver, BindingTrace trace) { @NotNull ReceiverDescriptor receiver, BindingTrace trace) {
WritableScopeImpl result = new WritableScopeImpl(outerScope, outerScope.getContainingDeclaration(), new TraceBasedRedeclarationHandler(trace)).setDebugName("Property declaration inner scope"); WritableScopeImpl result = new WritableScopeImpl(outerScope, outerScope.getContainingDeclaration(), new TraceBasedRedeclarationHandler(trace)).setDebugName("Property declaration inner scope");
for (TypeParameterDescriptor typeParameterDescriptor : typeParameters) { for (TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
@@ -583,7 +584,7 @@ public class DescriptorResolver {
CallableMemberDescriptor.Kind.DECLARATION CallableMemberDescriptor.Kind.DECLARATION
); );
List<TypeParameterDescriptor> typeParameterDescriptors; List<TypeParameterDescriptorImpl> typeParameterDescriptors;
JetScope scopeWithTypeParameters; JetScope scopeWithTypeParameters;
JetType receiverType = null; JetType receiverType = null;
@@ -275,7 +275,7 @@ public class DescriptorUtils {
ClassDescriptor clazz = (ClassDescriptor) classifier; ClassDescriptor clazz = (ClassDescriptor) classifier;
return clazz.getKind() == ClassKind.OBJECT || clazz.getKind() == ClassKind.ENUM_ENTRY; return clazz.getKind() == ClassKind.OBJECT || clazz.getKind() == ClassKind.ENUM_ENTRY;
} }
else if (classifier instanceof TypeParameterDescriptor) { else if (classifier instanceof TypeParameterDescriptorImpl) {
return false; return false;
} }
else { else {
@@ -212,7 +212,7 @@ public class OverridingUtil {
if (type.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) { if (type.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) {
return type; return type;
} }
else if (type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) { else if (type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptorImpl) {
return ((TypeParameterDescriptor) type.getConstructor().getDeclarationDescriptor()).getUpperBoundsAsType(); return ((TypeParameterDescriptor) type.getConstructor().getDeclarationDescriptor()).getUpperBoundsAsType();
} }
else { else {
@@ -23,7 +23,6 @@ import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.di.InjectorForTopDownAnalyzerBasic; import org.jetbrains.jet.di.InjectorForTopDownAnalyzerBasic;
import org.jetbrains.jet.lang.ModuleConfiguration; import org.jetbrains.jet.lang.ModuleConfiguration;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.JetDeclaration; import org.jetbrains.jet.lang.psi.JetDeclaration;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
@@ -188,7 +187,7 @@ public class TopDownAnalyzer {
TopDownAnalysisParameters topDownAnalysisParameters = new TopDownAnalysisParameters(Predicates.<PsiFile>alwaysFalse(), true, false); TopDownAnalysisParameters topDownAnalysisParameters = new TopDownAnalysisParameters(Predicates.<PsiFile>alwaysFalse(), true, false);
InjectorForTopDownAnalyzerBasic injector = new InjectorForTopDownAnalyzerBasic( InjectorForTopDownAnalyzerBasic injector = new InjectorForTopDownAnalyzerBasic(
project, topDownAnalysisParameters, new ObservableBindingTrace(trace), project, topDownAnalysisParameters, new ObservableBindingTrace(trace),
JetStandardClasses.FAKE_STANDARD_CLASSES_MODULE, null, ModuleConfiguration.EMPTY); JetStandardClasses.FAKE_STANDARD_CLASSES_MODULE, ModuleConfiguration.EMPTY);
injector.getTopDownAnalyzer().doProcessStandardLibraryNamespace(outerScope, standardLibraryNamespace, files); injector.getTopDownAnalyzer().doProcessStandardLibraryNamespace(outerScope, standardLibraryNamespace, files);
} }
@@ -220,7 +219,7 @@ public class TopDownAnalyzer {
InjectorForTopDownAnalyzerBasic injector = new InjectorForTopDownAnalyzerBasic( InjectorForTopDownAnalyzerBasic injector = new InjectorForTopDownAnalyzerBasic(
project, topDownAnalysisParameters, new ObservableBindingTrace(trace), moduleDescriptor, project, topDownAnalysisParameters, new ObservableBindingTrace(trace), moduleDescriptor,
JetControlFlowDataTraceFactory.EMPTY, ModuleConfiguration.EMPTY); ModuleConfiguration.EMPTY);
injector.getTopDownAnalyzer().doProcess(outerScope, new NamespaceLikeBuilder() { injector.getTopDownAnalyzer().doProcess(outerScope, new NamespaceLikeBuilder() {
@@ -395,7 +395,7 @@ public class TypeHierarchyResolver {
JetClass jetClass = entry.getKey(); JetClass jetClass = entry.getKey();
MutableClassDescriptor descriptor = entry.getValue(); MutableClassDescriptor descriptor = entry.getValue();
descriptorResolver.resolveGenericBounds(jetClass, descriptor.getScopeForSupertypeResolution(), descriptorResolver.resolveGenericBounds(jetClass, descriptor.getScopeForSupertypeResolution(),
descriptor.getTypeConstructor().getParameters(), trace); (List) descriptor.getTypeConstructor().getParameters(), trace);
descriptorResolver.resolveSupertypes(jetClass, descriptor, trace); descriptorResolver.resolveSupertypes(jetClass, descriptor, trace);
} }
for (Map.Entry<JetObjectDeclaration, MutableClassDescriptor> entry : context.getObjects().entrySet()) { for (Map.Entry<JetObjectDeclaration, MutableClassDescriptor> entry : context.getObjects().entrySet()) {
@@ -528,7 +528,7 @@ public class TypeHierarchyResolver {
if (projections.size() > 1) { if (projections.size() > 1) {
TypeConstructor typeConstructor = entry.getKey(); TypeConstructor typeConstructor = entry.getKey();
DeclarationDescriptor declarationDescriptor = typeConstructor.getDeclarationDescriptor(); DeclarationDescriptor declarationDescriptor = typeConstructor.getDeclarationDescriptor();
assert declarationDescriptor instanceof TypeParameterDescriptor : declarationDescriptor; assert declarationDescriptor instanceof TypeParameterDescriptorImpl : declarationDescriptor;
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) declarationDescriptor; TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) declarationDescriptor;
// Immediate arguments of supertypes cannot be projected // Immediate arguments of supertypes cannot be projected
@@ -95,7 +95,7 @@ public class TypeResolver {
return; return;
} }
if (classifierDescriptor instanceof TypeParameterDescriptor) { if (classifierDescriptor instanceof TypeParameterDescriptorImpl) {
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) classifierDescriptor; TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) classifierDescriptor;
trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, typeParameterDescriptor); trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, typeParameterDescriptor);
@@ -21,6 +21,7 @@ import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptorImpl;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.types.checker.TypeCheckingProcedure; import org.jetbrains.jet.lang.types.checker.TypeCheckingProcedure;
@@ -88,7 +89,7 @@ public class ConstraintSystemWithPriorities implements ConstraintSystem {
@NotNull @NotNull
private TypeValue getTypeValueFor(@NotNull JetType type) { private TypeValue getTypeValueFor(@NotNull JetType type) {
DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor(); DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor();
if (declarationDescriptor instanceof TypeParameterDescriptor) { if (declarationDescriptor instanceof TypeParameterDescriptorImpl) {
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) declarationDescriptor; TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) declarationDescriptor;
// Checking that this is not a T?, but exactly T // Checking that this is not a T?, but exactly T
if (typeParameterDescriptor.getDefaultType().isNullable() == type.isNullable()) { if (typeParameterDescriptor.getDefaultType().isNullable() == type.isNullable()) {
@@ -488,7 +489,7 @@ public class ConstraintSystemWithPriorities implements ConstraintSystem {
@Override @Override
public TypeProjection get(TypeConstructor key) { public TypeProjection get(TypeConstructor key) {
DeclarationDescriptor declarationDescriptor = key.getDeclarationDescriptor(); DeclarationDescriptor declarationDescriptor = key.getDeclarationDescriptor();
if (declarationDescriptor instanceof TypeParameterDescriptor) { if (declarationDescriptor instanceof TypeParameterDescriptorImpl) {
TypeParameterDescriptor descriptor = (TypeParameterDescriptor) declarationDescriptor; TypeParameterDescriptor descriptor = (TypeParameterDescriptor) declarationDescriptor;
if (!unknownTypes.containsKey(descriptor)) return null; if (!unknownTypes.containsKey(descriptor)) return null;
@@ -14,23 +14,22 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.jet.lang.cfg.pseudocode; package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetElement; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.resolve.name.FqName;
/** /**
* @author abreslav * @author Stepan Koltsov
*/ */
public interface JetControlFlowDataTraceFactory { public interface DependencyClassByQualifiedNameResolver {
JetControlFlowDataTraceFactory EMPTY = new JetControlFlowDataTraceFactory() {
@NotNull @Nullable
@Override ClassDescriptor resolveClass(@NotNull FqName qualifiedName);
public JetPseudocodeTrace createTrace(JetElement element) { @Nullable
return JetPseudocodeTrace.EMPTY; NamespaceDescriptor resolveNamespace(@NotNull FqName qualifiedName);
}
};
@NotNull
JetPseudocodeTrace createTrace(JetElement element);
} }
@@ -0,0 +1,37 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.resolve.name.FqName;
/**
* @author Stepan Koltsov
*/
public class DependencyClassByQualifiedNameResolverDummyImpl implements DependencyClassByQualifiedNameResolver {
@Override
public ClassDescriptor resolveClass(@NotNull FqName qualifiedName) {
return null;
}
@Override
public NamespaceDescriptor resolveNamespace(@NotNull FqName qualifiedName) {
return null;
}
}
@@ -20,6 +20,7 @@ import com.google.common.collect.Maps;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptorImpl;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -58,7 +59,7 @@ public class DescriptorSubstitutor {
}); });
for (TypeParameterDescriptor descriptor : typeParameters) { for (TypeParameterDescriptor descriptor : typeParameters) {
TypeParameterDescriptor substituted = TypeParameterDescriptor.createForFurtherModification( TypeParameterDescriptorImpl substituted = TypeParameterDescriptorImpl.createForFurtherModification(
newContainingDeclaration, newContainingDeclaration,
descriptor.getAnnotations(), descriptor.getAnnotations(),
descriptor.isReified(), descriptor.isReified(),
@@ -170,7 +170,7 @@ public class ErrorUtils {
function.initialize( function.initialize(
null, null,
ReceiverDescriptor.NO_RECEIVER, ReceiverDescriptor.NO_RECEIVER,
Collections.<TypeParameterDescriptor>emptyList(), // TODO Collections.<TypeParameterDescriptorImpl>emptyList(), // TODO
Collections.<ValueParameterDescriptor>emptyList(), // TODO Collections.<ValueParameterDescriptor>emptyList(), // TODO
createErrorType("<ERROR FUNCTION RETURN TYPE>"), createErrorType("<ERROR FUNCTION RETURN TYPE>"),
Modality.OPEN, Modality.OPEN,
@@ -223,7 +223,7 @@ public class ErrorUtils {
} }
private static JetType createErrorTypeWithCustomDebugName(JetScope memberScope, String debugName) { private static JetType createErrorTypeWithCustomDebugName(JetScope memberScope, String debugName) {
return new ErrorTypeImpl(new TypeConstructorImpl(ERROR_CLASS, Collections.<AnnotationDescriptor>emptyList(), false, debugName, Collections.<TypeParameterDescriptor>emptyList(), Collections.singleton(JetStandardClasses.getAnyType())), memberScope); return new ErrorTypeImpl(new TypeConstructorImpl(ERROR_CLASS, Collections.<AnnotationDescriptor>emptyList(), false, debugName, Collections.<TypeParameterDescriptorImpl>emptyList(), Collections.singleton(JetStandardClasses.getAnyType())), memberScope);
} }
public static JetType createWrongVarianceErrorType(TypeProjection value) { public static JetType createWrongVarianceErrorType(TypeProjection value) {
@@ -21,6 +21,7 @@ import com.google.common.collect.Multimap;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptorImpl;
import org.jetbrains.jet.lang.types.lang.JetStandardClasses; import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
import org.jetbrains.jet.util.CommonSuppliers; import org.jetbrains.jet.util.CommonSuppliers;
@@ -95,6 +96,9 @@ public class SubstitutionUtils {
} }
private static void fillInSubstitutionContext(List<TypeParameterDescriptor> parameters, List<TypeProjection> contextArguments, Map<TypeConstructor, TypeProjection> parameterValues) { private static void fillInSubstitutionContext(List<TypeParameterDescriptor> parameters, List<TypeProjection> contextArguments, Map<TypeConstructor, TypeProjection> parameterValues) {
if (parameters.size() != contextArguments.size()) {
throw new IllegalArgumentException("type parameter count != context arguments");
}
for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) { for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
TypeParameterDescriptor parameter = parameters.get(i); TypeParameterDescriptor parameter = parameters.get(i);
TypeProjection value = contextArguments.get(i); TypeProjection value = contextArguments.get(i);
@@ -108,7 +112,7 @@ public class SubstitutionUtils {
} }
public static boolean hasUnsubstitutedTypeParameters(JetType type) { public static boolean hasUnsubstitutedTypeParameters(JetType type) {
if (type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) { if (type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptorImpl) {
return true; return true;
} }
@@ -45,7 +45,7 @@ public class TypeConstructorImpl extends AnnotatedImpl implements TypeConstructo
@NotNull List<AnnotationDescriptor> annotations, @NotNull List<AnnotationDescriptor> annotations,
boolean sealed, boolean sealed,
@NotNull String debugName, @NotNull String debugName,
@NotNull List<TypeParameterDescriptor> parameters, @NotNull List<? extends TypeParameterDescriptor> parameters,
@NotNull Collection<JetType> supertypes) { @NotNull Collection<JetType> supertypes) {
super(annotations); super(annotations);
this.classifierDescriptor = classifierDescriptor; this.classifierDescriptor = classifierDescriptor;
@@ -22,10 +22,7 @@ import com.google.common.collect.Sets;
import com.intellij.util.Processor; import com.intellij.util.Processor;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintResolutionListener; import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintResolutionListener;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemSolution; import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemSolution;
@@ -222,7 +219,7 @@ public class TypeUtils {
private static void processAllTypeParameters(JetType type, Variance howThiTypeIsUsed, Processor<TypeParameterUsage> result) { private static void processAllTypeParameters(JetType type, Variance howThiTypeIsUsed, Processor<TypeParameterUsage> result) {
ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor(); ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
if (descriptor instanceof TypeParameterDescriptor) { if (descriptor instanceof TypeParameterDescriptorImpl) {
result.process(new TypeParameterUsage((TypeParameterDescriptor)descriptor, howThiTypeIsUsed)); result.process(new TypeParameterUsage((TypeParameterDescriptor)descriptor, howThiTypeIsUsed));
} }
for (TypeProjection projection : type.getArguments()) { for (TypeProjection projection : type.getArguments()) {
@@ -149,7 +149,7 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor {
} }
functionDescriptor.initialize(effectiveReceiverType, functionDescriptor.initialize(effectiveReceiverType,
NO_RECEIVER, NO_RECEIVER,
Collections.<TypeParameterDescriptor>emptyList(), Collections.<TypeParameterDescriptorImpl>emptyList(),
valueParameterDescriptors, valueParameterDescriptors,
/*unsubstitutedReturnType = */ null, /*unsubstitutedReturnType = */ null,
Modality.FINAL, Modality.FINAL,
@@ -157,13 +157,13 @@ public class JetStandardClasses {
Name.identifier("Tuple" + i)); Name.identifier("Tuple" + i));
WritableScopeImpl writableScope = new WritableScopeImpl(JetScope.EMPTY, classDescriptor, RedeclarationHandler.THROW_EXCEPTION); WritableScopeImpl writableScope = new WritableScopeImpl(JetScope.EMPTY, classDescriptor, RedeclarationHandler.THROW_EXCEPTION);
for (int j = 0; j < i; j++) { for (int j = 0; j < i; j++) {
TypeParameterDescriptor typeParameterDescriptor = TypeParameterDescriptor.createWithDefaultBound( TypeParameterDescriptor typeParameterDescriptor = TypeParameterDescriptorImpl.createWithDefaultBound(
classDescriptor, classDescriptor,
Collections.<AnnotationDescriptor>emptyList(), Collections.<AnnotationDescriptor>emptyList(),
true, Variance.OUT_VARIANCE, Name.identifier("T" + (j + 1)), j); true, Variance.OUT_VARIANCE, Name.identifier("T" + (j + 1)), j);
parameters.add(typeParameterDescriptor); parameters.add(typeParameterDescriptor);
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(classDescriptor, Collections.<AnnotationDescriptor>emptyList(), Modality.FINAL, Visibilities.PUBLIC, false, false, Name.identifier("_" + (j + 1)), CallableMemberDescriptor.Kind.DECLARATION); PropertyDescriptor propertyDescriptor = new PropertyDescriptor(classDescriptor, Collections.<AnnotationDescriptor>emptyList(), Modality.FINAL, Visibilities.PUBLIC, false, false, Name.identifier("_" + (j + 1)), CallableMemberDescriptor.Kind.DECLARATION);
propertyDescriptor.setType(typeParameterDescriptor.getDefaultType(), Collections.<TypeParameterDescriptor>emptyList(), classDescriptor.getImplicitReceiver(), ReceiverDescriptor.NO_RECEIVER); propertyDescriptor.setType(typeParameterDescriptor.getDefaultType(), Collections.<TypeParameterDescriptorImpl>emptyList(), classDescriptor.getImplicitReceiver(), ReceiverDescriptor.NO_RECEIVER);
PropertyGetterDescriptor getterDescriptor = new PropertyGetterDescriptor(propertyDescriptor, Collections.<AnnotationDescriptor>emptyList(), Modality.FINAL, Visibilities.PUBLIC, false, true, CallableMemberDescriptor.Kind.DECLARATION); PropertyGetterDescriptor getterDescriptor = new PropertyGetterDescriptor(propertyDescriptor, Collections.<AnnotationDescriptor>emptyList(), Modality.FINAL, Visibilities.PUBLIC, false, true, CallableMemberDescriptor.Kind.DECLARATION);
getterDescriptor.initialize(typeParameterDescriptor.getDefaultType()); getterDescriptor.initialize(typeParameterDescriptor.getDefaultType());
propertyDescriptor.initialize(getterDescriptor, null); propertyDescriptor.initialize(getterDescriptor, null);
@@ -215,7 +215,7 @@ public class JetStandardClasses {
SimpleFunctionDescriptorImpl invokeWithReceiver = new SimpleFunctionDescriptorImpl(receiverFunction, Collections.<AnnotationDescriptor>emptyList(), Name.identifier("invoke"), CallableMemberDescriptor.Kind.DECLARATION); SimpleFunctionDescriptorImpl invokeWithReceiver = new SimpleFunctionDescriptorImpl(receiverFunction, Collections.<AnnotationDescriptor>emptyList(), Name.identifier("invoke"), CallableMemberDescriptor.Kind.DECLARATION);
WritableScope scopeForInvokeWithReceiver = createScopeForInvokeFunction(receiverFunction, invokeWithReceiver); WritableScope scopeForInvokeWithReceiver = createScopeForInvokeFunction(receiverFunction, invokeWithReceiver);
List<TypeParameterDescriptor> parameters = createTypeParameters(i, receiverFunction); List<TypeParameterDescriptor> parameters = createTypeParameters(i, receiverFunction);
parameters.add(0, TypeParameterDescriptor.createWithDefaultBound( parameters.add(0, TypeParameterDescriptorImpl.createWithDefaultBound(
receiverFunction, receiverFunction,
Collections.<AnnotationDescriptor>emptyList(), Collections.<AnnotationDescriptor>emptyList(),
true, Variance.IN_VARIANCE, Name.identifier("T"), 0)); true, Variance.IN_VARIANCE, Name.identifier("T"), 0));
@@ -238,12 +238,12 @@ public class JetStandardClasses {
private static List<TypeParameterDescriptor> createTypeParameters(int parameterCount, ClassDescriptorImpl function) { private static List<TypeParameterDescriptor> createTypeParameters(int parameterCount, ClassDescriptorImpl function) {
List<TypeParameterDescriptor> parameters = new ArrayList<TypeParameterDescriptor>(); List<TypeParameterDescriptor> parameters = new ArrayList<TypeParameterDescriptor>();
for (int j = 1; j <= parameterCount; j++) { for (int j = 1; j <= parameterCount; j++) {
parameters.add(TypeParameterDescriptor.createWithDefaultBound( parameters.add(TypeParameterDescriptorImpl.createWithDefaultBound(
function, function,
Collections.<AnnotationDescriptor>emptyList(), Collections.<AnnotationDescriptor>emptyList(),
true, Variance.IN_VARIANCE, Name.identifier("P" + j), j)); true, Variance.IN_VARIANCE, Name.identifier("P" + j), j));
} }
parameters.add(TypeParameterDescriptor.createWithDefaultBound( parameters.add(TypeParameterDescriptorImpl.createWithDefaultBound(
function, function,
Collections.<AnnotationDescriptor>emptyList(), Collections.<AnnotationDescriptor>emptyList(),
true, Variance.OUT_VARIANCE, Name.identifier("R"), parameterCount + 1)); true, Variance.OUT_VARIANCE, Name.identifier("R"), parameterCount + 1));
@@ -146,7 +146,7 @@ public class DescriptorRenderer implements Renderer<DeclarationDescriptor> {
Object typeNameObject; Object typeNameObject;
if (cd == null || cd instanceof TypeParameterDescriptor) { if (cd == null || cd instanceof TypeParameterDescriptorImpl) {
typeNameObject = type.getConstructor(); typeNameObject = type.getConstructor();
} }
else { else {
@@ -1,16 +1,3 @@
== get_j ==
get() = 20
---------------------
l0:
<START> NEXT:[r(20)] PREV:[]
r(20) NEXT:[<END>] PREV:[<START>]
l1:
<END> NEXT:[<SINK>] PREV:[r(20)]
error:
<ERROR> NEXT:[] PREV:[]
sink:
<SINK> NEXT:[] PREV:[<END>]
=====================
== AnonymousInitializers == == AnonymousInitializers ==
class AnonymousInitializers() { class AnonymousInitializers() {
val k = 34 val k = 34
@@ -46,16 +33,29 @@ l2:
l1: l1:
<END> NEXT:[<SINK>] PREV:[w($i)] <END> NEXT:[<SINK>] PREV:[w($i)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[d(get() = 20), <END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>, d(get() = 20)]
l3: l3:
<START> NEXT:[r(20)] PREV:[] <START> NEXT:[r(20)] PREV:[]
r(20) NEXT:[<END>] PREV:[<START>] r(20) NEXT:[<END>] PREV:[<START>]
l4: l4:
<END> NEXT:[<SINK>] PREV:[r(20)] <END> NEXT:[<SINK>] PREV:[r(20)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
=====================
== get_j ==
get() = 20
---------------------
l3:
<START> NEXT:[r(20)] PREV:[]
r(20) NEXT:[<END>] PREV:[<START>]
l4:
<END> NEXT:[<SINK>] PREV:[r(20)]
error:
<ERROR> NEXT:[<SINK>] PREV:[]
sink:
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
@@ -35,7 +35,7 @@ l0:
l1: l1:
<END> NEXT:[<SINK>] PREV:[w(a[10])] <END> NEXT:[<SINK>] PREV:[w(a[10])]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
@@ -9,9 +9,9 @@ l0:
l1: l1:
<END> NEXT:[<SINK>] PREV:[v(var x : Int;)] <END> NEXT:[<SINK>] PREV:[v(var x : Int;)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== assignments == == assignments ==
fun assignments() : Unit { fun assignments() : Unit {
@@ -72,7 +72,7 @@ l5:
l1: l1:
<END> NEXT:[<SINK>] PREV:[w(t.x)] <END> NEXT:[<SINK>] PREV:[w(t.x)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
+23 -23
View File
@@ -1,16 +1,3 @@
== anonymous_0 ==
{1}
---------------------
l3:
<START> NEXT:[r(1)] PREV:[]
r(1) NEXT:[<END>] PREV:[<START>]
l4:
<END> NEXT:[<SINK>] PREV:[r(1)]
error:
<ERROR> NEXT:[] PREV:[]
sink:
<SINK> NEXT:[] PREV:[<END>]
=====================
== f == == f ==
fun f(a : Boolean) : Unit { fun f(a : Boolean) : Unit {
1 1
@@ -78,18 +65,31 @@ l6:
l1: l1:
<END> NEXT:[<SINK>] PREV:[r(a || false)] <END> NEXT:[<SINK>] PREV:[r(a || false)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[d({1}), <END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>, d({1})]
l3: l3:
<START> NEXT:[r(1)] PREV:[] <START> NEXT:[r(1)] PREV:[]
r(1) NEXT:[<END>] PREV:[<START>] r(1) NEXT:[<END>] PREV:[<START>]
l4: l4:
<END> NEXT:[<SINK>] PREV:[r(1)] <END> NEXT:[<SINK>] PREV:[r(1)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
=====================
== anonymous_0 ==
{1}
---------------------
l3:
<START> NEXT:[r(1)] PREV:[]
r(1) NEXT:[<END>] PREV:[<START>]
l4:
<END> NEXT:[<SINK>] PREV:[r(1)]
error:
<ERROR> NEXT:[<SINK>] PREV:[]
sink:
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== foo == == foo ==
fun foo(a : Boolean, b : Int) : Unit {} fun foo(a : Boolean, b : Int) : Unit {}
@@ -104,9 +104,9 @@ l0:
l1: l1:
<END> NEXT:[<SINK>] PREV:[read (Unit)] <END> NEXT:[<SINK>] PREV:[read (Unit)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== genfun == == genfun ==
fun genfun<T>() : Unit {} fun genfun<T>() : Unit {}
@@ -117,9 +117,9 @@ l0:
l1: l1:
<END> NEXT:[<SINK>] PREV:[read (Unit)] <END> NEXT:[<SINK>] PREV:[read (Unit)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== flfun == == flfun ==
fun flfun(f : () -> Any) : Unit {} fun flfun(f : () -> Any) : Unit {}
@@ -132,7 +132,7 @@ l0:
l1: l1:
<END> NEXT:[<SINK>] PREV:[read (Unit)] <END> NEXT:[<SINK>] PREV:[read (Unit)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
@@ -0,0 +1,20 @@
== test ==
fun test() {
throw Exception()
test()
}
---------------------
l0:
<START> NEXT:[r(Exception)] PREV:[]
r(Exception) NEXT:[r(Exception())] PREV:[<START>]
r(Exception()) NEXT:[jmp(error)] PREV:[r(Exception)]
jmp(error) NEXT:[<ERROR>] PREV:[r(Exception())]
- r(test) NEXT:[r(test())] PREV:[]
- r(test()) NEXT:[<END>] PREV:[]
l1:
<END> NEXT:[<SINK>] PREV:[]
error:
<ERROR> NEXT:[<SINK>] PREV:[jmp(error)]
sink:
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
=====================
+4
View File
@@ -0,0 +1,4 @@
fun test() {
throw Exception()
test()
}
@@ -7,7 +7,7 @@ l0:
l1: l1:
<END> NEXT:[<SINK>] PREV:[read (Unit)] <END> NEXT:[<SINK>] PREV:[read (Unit)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
@@ -15,7 +15,7 @@ l0:
l1: l1:
<END> NEXT:[<SINK>] PREV:[] <END> NEXT:[<SINK>] PREV:[]
error: error:
<ERROR> NEXT:[] PREV:[jmp(error)] <ERROR> NEXT:[<SINK>] PREV:[jmp(error)]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
+101 -101
View File
@@ -21,9 +21,9 @@ l1:
l3: l3:
<END> NEXT:[<SINK>] PREV:[r(2)] <END> NEXT:[<SINK>] PREV:[r(2)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== t2 == == t2 ==
fun t2() { fun t2() {
@@ -65,36 +65,9 @@ l1:
l5: l5:
<END> NEXT:[<SINK>] PREV:[ret l1, r(2)] <END> NEXT:[<SINK>] PREV:[ret l1, r(2)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
=====================
== anonymous_0 ==
{ () =>
if (2 > 3) {
return@
}
}
---------------------
l3:
<START> NEXT:[r(())] PREV:[]
r(()) NEXT:[r(2)] PREV:[<START>]
r(2) NEXT:[r(3)] PREV:[r(())]
r(3) NEXT:[r(>)] PREV:[r(2)]
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
r(2 > 3) NEXT:[jf(l5)] PREV:[r(>)]
jf(l5) NEXT:[read (Unit), ret l4] PREV:[r(2 > 3)]
ret l4 NEXT:[<END>] PREV:[jf(l5)]
- jmp(l6) NEXT:[<END>] PREV:[]
l5:
read (Unit) NEXT:[<END>] PREV:[jf(l5)]
l4:
l6:
<END> NEXT:[<SINK>] PREV:[ret l4, read (Unit)]
error:
<ERROR> NEXT:[] PREV:[]
sink:
<SINK> NEXT:[] PREV:[<END>]
===================== =====================
== t3 == == t3 ==
fun t3() { fun t3() {
@@ -141,9 +114,9 @@ l1:
l8: l8:
<END> NEXT:[<SINK>] PREV:[r(2)] <END> NEXT:[<SINK>] PREV:[r(2)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[d({ () => if (2 > 3) { retur..), <END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>, d({ () => if (2 > 3) { retur..)]
l3: l3:
<START> NEXT:[r(())] PREV:[] <START> NEXT:[r(())] PREV:[]
r(()) NEXT:[r(2)] PREV:[<START>] r(()) NEXT:[r(2)] PREV:[<START>]
@@ -160,54 +133,36 @@ l4:
l6: l6:
<END> NEXT:[<SINK>] PREV:[ret l4, read (Unit)] <END> NEXT:[<SINK>] PREV:[ret l4, read (Unit)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== anonymous_1 == == anonymous_0 ==
{ () => { () =>
try { if (2 > 3) {
1 return@
if (2 > 3) { }
return@
}
} finally {
2
} }
}
--------------------- ---------------------
l3: l3:
<START> NEXT:[r(())] PREV:[] <START> NEXT:[r(())] PREV:[]
r(()) NEXT:[r(try { 1 if (2 > 3) { retur..)] PREV:[<START>] r(()) NEXT:[r(2)] PREV:[<START>]
r(try { r(2) NEXT:[r(3)] PREV:[r(())]
1 r(3) NEXT:[r(>)] PREV:[r(2)]
if (2 > 3) { r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
return@ r(2 > 3) NEXT:[jf(l5)] PREV:[r(>)]
} jf(l5) NEXT:[read (Unit), ret l4] PREV:[r(2 > 3)]
} finally { ret l4 NEXT:[<END>] PREV:[jf(l5)]
2 - jmp(l6) NEXT:[<END>] PREV:[]
}) NEXT:[r(1)] PREV:[r(())]
r(1) NEXT:[r(2)] PREV:[r(try { 1 if (2 > 3) { retur..)]
r(2) NEXT:[r(3)] PREV:[r(1)]
r(3) NEXT:[r(>)] PREV:[r(2)]
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
r(2 > 3) NEXT:[jf(l5)] PREV:[r(>)]
jf(l5) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
r(2) NEXT:[ret l4] PREV:[jf(l5)]
ret l4 NEXT:[<END>] PREV:[r(2)]
- jmp(l6) NEXT:[r(2)] PREV:[]
l5: l5:
read (Unit) NEXT:[r(2)] PREV:[jf(l5)] read (Unit) NEXT:[<END>] PREV:[jf(l5)]
l6:
l7:
r(2) NEXT:[<END>] PREV:[read (Unit)]
l4: l4:
l8: l6:
<END> NEXT:[<SINK>] PREV:[ret l4, r(2)] <END> NEXT:[<SINK>] PREV:[ret l4, read (Unit)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== t4 == == t4 ==
fun t4() { fun t4() {
@@ -250,9 +205,9 @@ l2:
l1: l1:
<END> NEXT:[<SINK>] PREV:[r({ () => try { 1 if (2 > 3)..)] <END> NEXT:[<SINK>] PREV:[r({ () => try { 1 if (2 > 3)..)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[d({ () => try { 1 if (2 > 3)..), <END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>, d({ () => try { 1 if (2 > 3)..)]
l3: l3:
<START> NEXT:[r(())] PREV:[] <START> NEXT:[r(())] PREV:[]
r(()) NEXT:[r(try { 1 if (2 > 3) { retur..)] PREV:[<START>] r(()) NEXT:[r(try { 1 if (2 > 3) { retur..)] PREV:[<START>]
@@ -282,9 +237,54 @@ l4:
l8: l8:
<END> NEXT:[<SINK>] PREV:[ret l4, r(2)] <END> NEXT:[<SINK>] PREV:[ret l4, r(2)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
=====================
== anonymous_1 ==
{ () =>
try {
1
if (2 > 3) {
return@
}
} finally {
2
}
}
---------------------
l3:
<START> NEXT:[r(())] PREV:[]
r(()) NEXT:[r(try { 1 if (2 > 3) { retur..)] PREV:[<START>]
r(try {
1
if (2 > 3) {
return@
}
} finally {
2
}) NEXT:[r(1)] PREV:[r(())]
r(1) NEXT:[r(2)] PREV:[r(try { 1 if (2 > 3) { retur..)]
r(2) NEXT:[r(3)] PREV:[r(1)]
r(3) NEXT:[r(>)] PREV:[r(2)]
r(>) NEXT:[r(2 > 3)] PREV:[r(3)]
r(2 > 3) NEXT:[jf(l5)] PREV:[r(>)]
jf(l5) NEXT:[read (Unit), r(2)] PREV:[r(2 > 3)]
r(2) NEXT:[ret l4] PREV:[jf(l5)]
ret l4 NEXT:[<END>] PREV:[r(2)]
- jmp(l6) NEXT:[r(2)] PREV:[]
l5:
read (Unit) NEXT:[r(2)] PREV:[jf(l5)]
l6:
l7:
r(2) NEXT:[<END>] PREV:[read (Unit)]
l4:
l8:
<END> NEXT:[<SINK>] PREV:[ret l4, r(2)]
error:
<ERROR> NEXT:[<SINK>] PREV:[]
sink:
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== t5 == == t5 ==
fun t5() { fun t5() {
@@ -346,9 +346,9 @@ l3:
l1: l1:
<END> NEXT:[<SINK>] PREV:[read (Unit)] <END> NEXT:[<SINK>] PREV:[read (Unit)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== t6 == == t6 ==
fun t6() { fun t6() {
@@ -410,9 +410,9 @@ l1:
l9: l9:
<END> NEXT:[<SINK>] PREV:[r(2)] <END> NEXT:[<SINK>] PREV:[r(2)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== t7 == == t7 ==
fun t7() { fun t7() {
@@ -471,9 +471,9 @@ l1:
l9: l9:
<END> NEXT:[<SINK>] PREV:[r(2)] <END> NEXT:[<SINK>] PREV:[r(2)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== t8 == == t8 ==
fun t8(a : Int) { fun t8(a : Int) {
@@ -542,9 +542,9 @@ l2:
l1: l1:
<END> NEXT:[<SINK>] PREV:[read (Unit)] <END> NEXT:[<SINK>] PREV:[read (Unit)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== t9 == == t9 ==
fun t9(a : Int) { fun t9(a : Int) {
@@ -613,9 +613,9 @@ l1:
l9: l9:
<END> NEXT:[<SINK>] PREV:[r(2)] <END> NEXT:[<SINK>] PREV:[r(2)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== t10 == == t10 ==
fun t10(a : Int) { fun t10(a : Int) {
@@ -681,9 +681,9 @@ l1:
l9: l9:
<END> NEXT:[<SINK>] PREV:[r(2)] <END> NEXT:[<SINK>] PREV:[r(2)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== t11 == == t11 ==
fun t11() { fun t11() {
@@ -714,9 +714,9 @@ l1:
l3: l3:
<END> NEXT:[<SINK>] PREV:[ret(*) l1] <END> NEXT:[<SINK>] PREV:[ret(*) l1]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== t12 == == t12 ==
fun t12() : Int { fun t12() : Int {
@@ -749,9 +749,9 @@ l1:
l3: l3:
<END> NEXT:[<SINK>] PREV:[ret(*) l1] <END> NEXT:[<SINK>] PREV:[ret(*) l1]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== t13 == == t13 ==
fun t13() : Int { fun t13() : Int {
@@ -802,9 +802,9 @@ l1:
l6: l6:
<END> NEXT:[<SINK>] PREV:[ret(*) l1, r(doSmth(3))] <END> NEXT:[<SINK>] PREV:[ret(*) l1, r(doSmth(3))]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== t14 == == t14 ==
fun t14() : Int { fun t14() : Int {
@@ -843,9 +843,9 @@ l4:
l6: l6:
<END> NEXT:[<SINK>] PREV:[ret(*) l1, jmp(l4)] <END> NEXT:[<SINK>] PREV:[ret(*) l1, jmp(l4)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== t15 == == t15 ==
fun t15() : Int { fun t15() : Int {
@@ -898,9 +898,9 @@ l1:
l6: l6:
<END> NEXT:[<SINK>] PREV:[ret(*) l1, ret(*) l1] <END> NEXT:[<SINK>] PREV:[ret(*) l1, ret(*) l1]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== t16 == == t16 ==
fun t16() : Int { fun t16() : Int {
@@ -951,9 +951,9 @@ l1:
l6: l6:
<END> NEXT:[<SINK>] PREV:[ret(*) l1, r(doSmth(3))] <END> NEXT:[<SINK>] PREV:[ret(*) l1, r(doSmth(3))]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== doSmth == == doSmth ==
fun doSmth(i: Int) { fun doSmth(i: Int) {
@@ -967,7 +967,7 @@ l0:
l1: l1:
<END> NEXT:[<SINK>] PREV:[read (Unit)] <END> NEXT:[<SINK>] PREV:[read (Unit)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
+4 -4
View File
@@ -29,9 +29,9 @@ l2:
l1: l1:
<END> NEXT:[<SINK>] PREV:[read (Unit)] <END> NEXT:[<SINK>] PREV:[read (Unit)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== doSmth == == doSmth ==
fun doSmth(i: Int) {} fun doSmth(i: Int) {}
@@ -44,7 +44,7 @@ l0:
l1: l1:
<END> NEXT:[<SINK>] PREV:[read (Unit)] <END> NEXT:[<SINK>] PREV:[read (Unit)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
+6 -6
View File
@@ -48,9 +48,9 @@ l5:
l1: l1:
<END> NEXT:[<SINK>] PREV:[r(doSmth(r))] <END> NEXT:[<SINK>] PREV:[r(doSmth(r))]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== t2 == == t2 ==
fun t2(b: Boolean) { fun t2(b: Boolean) {
@@ -92,9 +92,9 @@ l1:
l5: l5:
<END> NEXT:[<SINK>] PREV:[ret l1, ret l1, read (Unit)] <END> NEXT:[<SINK>] PREV:[ret l1, ret l1, read (Unit)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== doSmth == == doSmth ==
fun doSmth(s: String) {} fun doSmth(s: String) {}
@@ -107,7 +107,7 @@ l0:
l1: l1:
<END> NEXT:[<SINK>] PREV:[read (Unit)] <END> NEXT:[<SINK>] PREV:[read (Unit)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
@@ -72,7 +72,7 @@ l13:
l1: l1:
<END> NEXT:[<SINK>] PREV:[r(14)] <END> NEXT:[<SINK>] PREV:[r(14)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
@@ -25,56 +25,9 @@ l0:
l1: l1:
<END> NEXT:[<SINK>] PREV:[w(a)] <END> NEXT:[<SINK>] PREV:[w(a)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
=====================
== O ==
object O {
val x : Int
{
$x = 1
}
}
---------------------
l0:
<START> NEXT:[v(val x : Int)] PREV:[]
v(val x : Int) NEXT:[r(1)] PREV:[<START>]
r(1) NEXT:[w($x)] PREV:[v(val x : Int)]
w($x) NEXT:[<END>] PREV:[r(1)]
l1:
<END> NEXT:[<SINK>] PREV:[w($x)]
error:
<ERROR> NEXT:[] PREV:[]
sink:
<SINK> NEXT:[] PREV:[<END>]
=====================
== null ==
object {
val x : Int
{
$x = 1
}
fun foo() {
val b : Int = 1
doSmth(b)
}
}
---------------------
l0:
<START> NEXT:[v(val x : Int)] PREV:[]
v(val x : Int) NEXT:[r(1)] PREV:[<START>]
r(1) NEXT:[w($x)] PREV:[v(val x : Int)]
w($x) NEXT:[<END>] PREV:[r(1)]
l1:
<END> NEXT:[<SINK>] PREV:[w($x)]
error:
<ERROR> NEXT:[] PREV:[]
sink:
<SINK> NEXT:[] PREV:[<END>]
===================== =====================
== doSmth == == doSmth ==
fun doSmth(i: Int) {} fun doSmth(i: Int) {}
@@ -87,9 +40,9 @@ l0:
l1: l1:
<END> NEXT:[<SINK>] PREV:[read (Unit)] <END> NEXT:[<SINK>] PREV:[read (Unit)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== test1 == == test1 ==
fun test1() { fun test1() {
@@ -122,9 +75,29 @@ l0:
l1: l1:
<END> NEXT:[<SINK>] PREV:[w(a)] <END> NEXT:[<SINK>] PREV:[w(a)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
=====================
== O ==
object O {
val x : Int
{
$x = 1
}
}
---------------------
l0:
<START> NEXT:[v(val x : Int)] PREV:[]
v(val x : Int) NEXT:[r(1)] PREV:[<START>]
r(1) NEXT:[w($x)] PREV:[v(val x : Int)]
w($x) NEXT:[<END>] PREV:[r(1)]
l1:
<END> NEXT:[<SINK>] PREV:[w($x)]
error:
<ERROR> NEXT:[<SINK>] PREV:[]
sink:
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== test2 == == test2 ==
fun test2() { fun test2() {
@@ -152,25 +125,9 @@ l0:
l1: l1:
<END> NEXT:[<SINK>] PREV:[w(a)] <END> NEXT:[<SINK>] PREV:[w(a)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
=====================
== inner_bar ==
fun inner_bar() {
y = 10
}
---------------------
l3:
<START> NEXT:[r(10)] PREV:[]
r(10) NEXT:[w(y)] PREV:[<START>]
w(y) NEXT:[<END>] PREV:[r(10)]
l4:
<END> NEXT:[<SINK>] PREV:[w(y)]
error:
<ERROR> NEXT:[] PREV:[]
sink:
<SINK> NEXT:[] PREV:[<END>]
===================== =====================
== test3 == == test3 ==
fun test3() { fun test3() {
@@ -206,9 +163,9 @@ l2:
l1: l1:
<END> NEXT:[<SINK>] PREV:[w(a)] <END> NEXT:[<SINK>] PREV:[w(a)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[d(fun inner_bar() { y = 10 }) , <END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>, d(fun inner_bar() { y = 10 }) ]
l3: l3:
<START> NEXT:[r(10)] PREV:[] <START> NEXT:[r(10)] PREV:[]
r(10) NEXT:[w(y)] PREV:[<START>] r(10) NEXT:[w(y)] PREV:[<START>]
@@ -216,12 +173,12 @@ l3:
l4: l4:
<END> NEXT:[<SINK>] PREV:[w(y)] <END> NEXT:[<SINK>] PREV:[w(y)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== ggg == == inner_bar ==
fun ggg() { fun inner_bar() {
y = 10 y = 10
} }
--------------------- ---------------------
@@ -232,9 +189,9 @@ l3:
l4: l4:
<END> NEXT:[<SINK>] PREV:[w(y)] <END> NEXT:[<SINK>] PREV:[w(y)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== test4 == == test4 ==
fun test4() { fun test4() {
@@ -285,9 +242,9 @@ l2:
l1: l1:
<END> NEXT:[<SINK>] PREV:[w(a)] <END> NEXT:[<SINK>] PREV:[w(a)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[d(fun ggg() { y = 10 }) , <END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>, d(fun ggg() { y = 10 }) ]
l3: l3:
<START> NEXT:[r(10)] PREV:[] <START> NEXT:[r(10)] PREV:[]
r(10) NEXT:[w(y)] PREV:[<START>] r(10) NEXT:[w(y)] PREV:[<START>]
@@ -295,41 +252,25 @@ l3:
l4: l4:
<END> NEXT:[<SINK>] PREV:[w(y)] <END> NEXT:[<SINK>] PREV:[w(y)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== foo == == ggg ==
fun foo() { fun ggg() {
x = 3 y = 10
} }
--------------------- ---------------------
l3: l3:
<START> NEXT:[r(3)] PREV:[] <START> NEXT:[r(10)] PREV:[]
r(3) NEXT:[w(x)] PREV:[<START>] r(10) NEXT:[w(y)] PREV:[<START>]
w(x) NEXT:[<END>] PREV:[r(3)] w(y) NEXT:[<END>] PREV:[r(10)]
l4: l4:
<END> NEXT:[<SINK>] PREV:[w(x)] <END> NEXT:[<SINK>] PREV:[w(y)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
=====================
== bar ==
fun bar() {
x = 4
}
---------------------
l6:
<START> NEXT:[r(4)] PREV:[]
r(4) NEXT:[w(x)] PREV:[<START>]
w(x) NEXT:[<END>] PREV:[r(4)]
l7:
<END> NEXT:[<SINK>] PREV:[w(x)]
error:
<ERROR> NEXT:[] PREV:[]
sink:
<SINK> NEXT:[] PREV:[<END>]
===================== =====================
== test5 == == test5 ==
fun test5() { fun test5() {
@@ -392,9 +333,9 @@ l5:
l1: l1:
<END> NEXT:[<SINK>] PREV:[w(a)] <END> NEXT:[<SINK>] PREV:[w(a)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[d(fun foo() { x = 3 }) , d(fun bar() { x = 4 }) , <END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>, d(fun foo() { x = 3 }) , d(fun bar() { x = 4 }) ]
l3: l3:
<START> NEXT:[r(3)] PREV:[] <START> NEXT:[r(3)] PREV:[]
r(3) NEXT:[w(x)] PREV:[<START>] r(3) NEXT:[w(x)] PREV:[<START>]
@@ -402,9 +343,9 @@ l3:
l4: l4:
<END> NEXT:[<SINK>] PREV:[w(x)] <END> NEXT:[<SINK>] PREV:[w(x)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
l6: l6:
<START> NEXT:[r(4)] PREV:[] <START> NEXT:[r(4)] PREV:[]
r(4) NEXT:[w(x)] PREV:[<START>] r(4) NEXT:[w(x)] PREV:[<START>]
@@ -412,28 +353,39 @@ l6:
l7: l7:
<END> NEXT:[<SINK>] PREV:[w(x)] <END> NEXT:[<SINK>] PREV:[w(x)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== foo == == foo ==
fun foo() { fun foo() {
val b : Int = 1 x = 3
doSmth(b)
} }
--------------------- ---------------------
l0: l3:
<START> NEXT:[v(val b : Int = 1)] PREV:[] <START> NEXT:[r(3)] PREV:[]
v(val b : Int = 1) NEXT:[r(1)] PREV:[<START>] r(3) NEXT:[w(x)] PREV:[<START>]
r(1) NEXT:[w(b)] PREV:[v(val b : Int = 1)] w(x) NEXT:[<END>] PREV:[r(3)]
w(b) NEXT:[r(b)] PREV:[r(1)] l4:
r(b) NEXT:[r(doSmth)] PREV:[w(b)] <END> NEXT:[<SINK>] PREV:[w(x)]
r(doSmth) NEXT:[r(doSmth(b))] PREV:[r(b)]
r(doSmth(b)) NEXT:[<END>] PREV:[r(doSmth)]
l1:
<END> NEXT:[<SINK>] PREV:[r(doSmth(b))]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
=====================
== bar ==
fun bar() {
x = 4
}
---------------------
l6:
<START> NEXT:[r(4)] PREV:[]
r(4) NEXT:[w(x)] PREV:[<START>]
w(x) NEXT:[<END>] PREV:[r(4)]
l7:
<END> NEXT:[<SINK>] PREV:[w(x)]
error:
<ERROR> NEXT:[<SINK>] PREV:[]
sink:
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
@@ -25,9 +25,9 @@ l3:
l1: l1:
<END> NEXT:[<SINK>] PREV:[read (Unit)] <END> NEXT:[<SINK>] PREV:[read (Unit)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
== dowhile == == dowhile ==
fun dowhile() { fun dowhile() {
@@ -53,7 +53,7 @@ l3:
l1: l1:
<END> NEXT:[<SINK>] PREV:[ret l1] <END> NEXT:[<SINK>] PREV:[ret l1]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
@@ -15,7 +15,7 @@ l2:
l1: l1:
<END> NEXT:[<SINK>] PREV:[ret(*) l1, r(false || (return false))] <END> NEXT:[<SINK>] PREV:[ret(*) l1, r(false || (return false))]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
@@ -7,7 +7,7 @@ l0:
l1: l1:
<END> NEXT:[<SINK>] PREV:[r(1)] <END> NEXT:[<SINK>] PREV:[r(1)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[<SINK>] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<ERROR>, <END>]
===================== =====================
@@ -175,12 +175,12 @@ class B() {
fun testFunctionLiterals() { fun testFunctionLiterals() {
val <!UNUSED_VARIABLE!>endsWithVarDeclaration<!> : () -> Boolean = { val <!UNUSED_VARIABLE!>endsWithVarDeclaration<!> : () -> Boolean = {
<!EXPECTED_TYPE_MISMATCH!>val x = 2<!> <!EXPECTED_TYPE_MISMATCH!>val <!UNUSED_VARIABLE!>x<!> = 2<!>
} }
val <!UNUSED_VARIABLE!>endsWithAssignment<!> = { () : Int -> val <!UNUSED_VARIABLE!>endsWithAssignment<!> = { () : Int ->
var x = 1 var <!ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE!>x<!> = 1
<!EXPECTED_TYPE_MISMATCH!>x = 333<!> <!EXPECTED_TYPE_MISMATCH!>x = <!UNUSED_VALUE!>333<!><!>
} }
val <!UNUSED_VARIABLE!>endsWithReAssignment<!> = { () : Int -> val <!UNUSED_VARIABLE!>endsWithReAssignment<!> = { () : Int ->
@@ -189,19 +189,19 @@ fun testFunctionLiterals() {
} }
val <!UNUSED_VARIABLE!>endsWithFunDeclaration<!> : () -> String = { val <!UNUSED_VARIABLE!>endsWithFunDeclaration<!> : () -> String = {
var x = 1 var <!ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE!>x<!> = 1
x = 333 x = <!UNUSED_VALUE!>333<!>
<!EXPECTED_TYPE_MISMATCH!>fun meow() : Unit {}<!> <!EXPECTED_TYPE_MISMATCH!>fun meow() : Unit {}<!>
} }
val <!UNUSED_VARIABLE!>endsWithObjectDeclaration<!> : () -> Int = { val <!UNUSED_VARIABLE!>endsWithObjectDeclaration<!> : () -> Int = {
var x = 1 var <!ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE!>x<!> = 1
x = 333 x = <!UNUSED_VALUE!>333<!>
<!EXPECTED_TYPE_MISMATCH!>object A {}<!> <!EXPECTED_TYPE_MISMATCH!>object A {}<!>
} }
val <!UNUSED_VARIABLE!>expectedUnitReturnType1<!> = { () : Unit -> val <!UNUSED_VARIABLE!>expectedUnitReturnType1<!> = { () : Unit ->
val x = 1 val <!UNUSED_VARIABLE!>x<!> = 1
} }
val <!UNUSED_VARIABLE!>expectedUnitReturnType2<!> = { () : Unit -> val <!UNUSED_VARIABLE!>expectedUnitReturnType2<!> = { () : Unit ->
@@ -3,8 +3,8 @@ fun demo() {
val a = "" val a = ""
val asd = 1 val asd = 1
val bar = 5 val bar = 5
fun map(f : () -> Any?) : Int = 1 fun map(<!UNUSED_PARAMETER!>f<!> : () -> Any?) : Int = 1
fun buzz(f : () -> Any?) : Int = 1 fun buzz(<!UNUSED_PARAMETER!>f<!> : () -> Any?) : Int = 1
val sdf = 1 val sdf = 1
val foo = 3; val foo = 3;
<!UNUSED_EXPRESSION!>"$abc"<!> <!UNUSED_EXPRESSION!>"$abc"<!>
@@ -101,7 +101,7 @@ fun t5() {
for (i in 0..2) { for (i in 0..2) {
<!VAL_REASSIGNMENT!>i<!> += 1 <!VAL_REASSIGNMENT!>i<!> += 1
fun t5() { fun t5() {
<!VAL_REASSIGNMENT!>i<!> += 3 i += 3
} }
} }
} }
@@ -297,8 +297,8 @@ class TestObjectExpression() {
<!VAL_REASSIGNMENT!>a<!> = 231 <!VAL_REASSIGNMENT!>a<!> = 231
} }
fun inner2() { fun inner2() {
<!VAL_REASSIGNMENT!>y<!> = 101 y = 101
<!VAL_REASSIGNMENT!>a<!> = 231 a = 231
} }
} }
} }
@@ -0,0 +1,12 @@
package c
fun test() {
val x = 10
fun inner1() {
fun inner2() {
fun inner3() {
val <!UNUSED_VARIABLE!>y<!> = x
}
}
}
}
@@ -12,8 +12,8 @@ fun main(args: Array<String>) {
<!EXPECTED_TYPE_MISMATCH!>x += 2<!> //no error, but it should be here <!EXPECTED_TYPE_MISMATCH!>x += 2<!> //no error, but it should be here
} }
val <!UNUSED_VARIABLE!>h<!> = {(): String -> val <!UNUSED_VARIABLE!>h<!> = {(): String ->
var x = 1 var <!ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE!>x<!> = 1
<!EXPECTED_TYPE_MISMATCH!>x = 2<!> //the same <!EXPECTED_TYPE_MISMATCH!>x = <!UNUSED_VALUE!>2<!><!> //the same
} }
val array1 = MyArray1() val array1 = MyArray1()
val <!UNUSED_VARIABLE!>i<!> = { (): String -> val <!UNUSED_VARIABLE!>i<!> = { (): String ->
@@ -1,7 +1,7 @@
fun f(<!UNUSED_PARAMETER!>i<!>: Int) { fun f(<!UNUSED_PARAMETER!>i<!>: Int) {
for (j in 1..100) { for (j in 1..100) {
<!UNUSED_FUNCTION_LITERAL!>{ <!UNUSED_FUNCTION_LITERAL!>{
var <!NAME_SHADOWING!>i<!> = 12 var <!NAME_SHADOWING, UNUSED_VARIABLE!>i<!> = 12
}<!> }<!>
} }
} }
@@ -1,7 +1,7 @@
fun ff(): Int { fun ff(): Int {
var i = 1 var i = 1
<!UNUSED_FUNCTION_LITERAL!>{ <!UNUSED_FUNCTION_LITERAL!>{
val <!NAME_SHADOWING!>i<!> = 2 val <!NAME_SHADOWING, UNUSED_VARIABLE!>i<!> = 2
}<!> }<!>
return i return i
} }
@@ -1,5 +1,5 @@
fun f(): Int { fun f(): Int {
var i = 17 var i = 17
<!UNUSED_FUNCTION_LITERAL!>{ (): Unit -> var <!NAME_SHADOWING!>i<!> = 18 }<!> <!UNUSED_FUNCTION_LITERAL!>{ (): Unit -> var <!NAME_SHADOWING, UNUSED_VARIABLE!>i<!> = 18 }<!>
return i return i
} }
@@ -33,7 +33,6 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.analyzer.AnalyzeExhaust; import org.jetbrains.jet.analyzer.AnalyzeExhaust;
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment; import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.diagnostics.UnresolvedReferenceDiagnosticFactory; import org.jetbrains.jet.lang.diagnostics.UnresolvedReferenceDiagnosticFactory;
import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.diagnostics.Severity; import org.jetbrains.jet.lang.diagnostics.Severity;
@@ -170,8 +169,8 @@ public class JetTestUtils {
private JetTestUtils() { private JetTestUtils() {
} }
public static AnalyzeExhaust analyzeFile(@NotNull JetFile namespace, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) { public static AnalyzeExhaust analyzeFile(@NotNull JetFile namespace) {
return AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegration(namespace, flowDataTraceFactory, return AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegration(namespace,
CompileCompilerDependenciesTest.compilerDependenciesForTests(CompilerSpecialMode.REGULAR, true)); CompileCompilerDependenciesTest.compilerDependenciesForTests(CompilerSpecialMode.REGULAR, true));
} }
@@ -28,9 +28,10 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetLiteFixture; import org.jetbrains.jet.JetLiteFixture;
import org.jetbrains.jet.JetTestCaseBuilder; import org.jetbrains.jet.JetTestCaseBuilder;
import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.lang.cfg.LoopInfo; import org.jetbrains.jet.analyzer.AnalyzeExhaust;
import org.jetbrains.jet.lang.cfg.pseudocode.*; import org.jetbrains.jet.lang.cfg.pseudocode.*;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.java.CompilerSpecialMode; import org.jetbrains.jet.lang.resolve.java.CompilerSpecialMode;
import java.io.File; import java.io.File;
@@ -72,37 +73,17 @@ public class JetControlFlowTest extends JetLiteFixture {
JetFile file = loadPsiFile(myName + ".jet"); JetFile file = loadPsiFile(myName + ".jet");
final Map<JetElement, Pseudocode> data = new LinkedHashMap<JetElement, Pseudocode>(); final Map<JetElement, Pseudocode> data = new LinkedHashMap<JetElement, Pseudocode>();
final JetPseudocodeTrace pseudocodeTrace = new JetPseudocodeTrace() { AnalyzeExhaust analyzeExhaust = JetTestUtils.analyzeFile(file);
List<JetDeclaration> declarations = file.getDeclarations();
@Override BindingContext bindingContext = analyzeExhaust.getBindingContext();
public void recordControlFlowData(@NotNull JetElement element, @NotNull Pseudocode pseudocode) { for (JetDeclaration declaration : declarations) {
data.put(element, pseudocode); Pseudocode pseudocode = PseudocodeUtil.generatePseudocode(declaration, bindingContext);
data.put(declaration, pseudocode);
for (LocalDeclarationInstruction instruction : pseudocode.getLocalDeclarations()) {
Pseudocode localPseudocode = instruction.getBody();
data.put(localPseudocode.getCorrespondingElement(), localPseudocode);
} }
}
@Override
public void close() {
for (Pseudocode pseudocode : data.values()) {
pseudocode.postProcess();
}
}
@Override
public void recordLoopInfo(JetExpression expression, LoopInfo blockInfo) {
}
@Override
public void recordRepresentativeInstruction(@NotNull JetElement element, @NotNull Instruction instruction) {
}
};
JetTestUtils.analyzeFile(file, new JetControlFlowDataTraceFactory() {
@NotNull
@Override
public JetPseudocodeTrace createTrace(JetElement element) {
return pseudocodeTrace;
}
});
try { try {
processCFData(myName, data); processCFData(myName, data);
@@ -123,6 +104,7 @@ public class JetControlFlowTest extends JetLiteFixture {
StringBuilder instructionDump = new StringBuilder(); StringBuilder instructionDump = new StringBuilder();
int i = 0; int i = 0;
for (Pseudocode pseudocode : pseudocodes) { for (Pseudocode pseudocode : pseudocodes) {
JetElement correspondingElement = pseudocode.getCorrespondingElement(); JetElement correspondingElement = pseudocode.getCorrespondingElement();
String label = ""; String label = "";
assert (correspondingElement instanceof JetNamedDeclaration || correspondingElement instanceof JetSecondaryConstructor || correspondingElement instanceof JetPropertyAccessor) : assert (correspondingElement instanceof JetNamedDeclaration || correspondingElement instanceof JetSecondaryConstructor || correspondingElement instanceof JetPropertyAccessor) :
@@ -146,11 +128,11 @@ public class JetControlFlowTest extends JetLiteFixture {
instructionDump.append(correspondingElement.getText()); instructionDump.append(correspondingElement.getText());
instructionDump.append("\n---------------------\n"); instructionDump.append("\n---------------------\n");
dumpInstructions(pseudocode, instructionDump); dumpInstructions((PseudocodeImpl) pseudocode, instructionDump);
instructionDump.append("=====================\n"); instructionDump.append("=====================\n");
//check edges directions //check edges directions
Collection<Instruction> instructions = pseudocode.getMutableInstructionList(); Collection<Instruction> instructions = ((PseudocodeImpl)pseudocode).getAllInstructions();
for (Instruction instruction : instructions) { for (Instruction instruction : instructions) {
if (!((InstructionImpl)instruction).isDead()) { if (!((InstructionImpl)instruction).isDead()) {
for (Instruction nextInstruction : instruction.getNextInstructions()) { for (Instruction nextInstruction : instruction.getNextInstructions()) {
@@ -181,8 +163,8 @@ public class JetControlFlowTest extends JetLiteFixture {
// } // }
} }
public void dfsDump(Pseudocode pseudocode, StringBuilder nodes, StringBuilder edges, Map<Instruction, String> nodeNames) { public void dfsDump(PseudocodeImpl pseudocode, StringBuilder nodes, StringBuilder edges, Map<Instruction, String> nodeNames) {
dfsDump(nodes, edges, pseudocode.getMutableInstructionList().get(0), nodeNames); dfsDump(nodes, edges, pseudocode.getAllInstructions().get(0), nodeNames);
} }
private void dfsDump(StringBuilder nodes, StringBuilder edges, Instruction instruction, Map<Instruction, String> nodeNames) { private void dfsDump(StringBuilder nodes, StringBuilder edges, Instruction instruction, Map<Instruction, String> nodeNames) {
@@ -243,11 +225,11 @@ public class JetControlFlowTest extends JetLiteFixture {
return sb.toString(); return sb.toString();
} }
public void dumpInstructions(Pseudocode pseudocode, @NotNull StringBuilder out) { public void dumpInstructions(PseudocodeImpl pseudocode, @NotNull StringBuilder out) {
List<Instruction> instructions = pseudocode.getMutableInstructionList(); List<Instruction> instructions = pseudocode.getAllInstructions();
Set<Instruction> remainedAfterPostProcessInstructions = Sets.newHashSet(pseudocode.getInstructions()); Set<Instruction> remainedAfterPostProcessInstructions = Sets.newHashSet(pseudocode.getInstructions());
List<Pseudocode.PseudocodeLabel> labels = pseudocode.getLabels(); List<PseudocodeImpl.PseudocodeLabel> labels = pseudocode.getLabels();
List<Pseudocode> locals = new ArrayList<Pseudocode>(); List<PseudocodeImpl> locals = new ArrayList<PseudocodeImpl>();
int maxLength = 0; int maxLength = 0;
int maxNextLength = 0; int maxNextLength = 0;
for (Instruction instruction : instructions) { for (Instruction instruction : instructions) {
@@ -276,9 +258,9 @@ public class JetControlFlowTest extends JetLiteFixture {
Instruction instruction = instructions.get(i); Instruction instruction = instructions.get(i);
if (instruction instanceof LocalDeclarationInstruction) { if (instruction instanceof LocalDeclarationInstruction) {
LocalDeclarationInstruction localDeclarationInstruction = (LocalDeclarationInstruction) instruction; LocalDeclarationInstruction localDeclarationInstruction = (LocalDeclarationInstruction) instruction;
locals.add(localDeclarationInstruction.getBody()); locals.add((PseudocodeImpl) localDeclarationInstruction.getBody());
} }
for (Pseudocode.PseudocodeLabel label: labels) { for (PseudocodeImpl.PseudocodeLabel label: labels) {
if (label.getTargetInstructionIndex() == i) { if (label.getTargetInstructionIndex() == i) {
out.append(label.getName()).append(":\n"); out.append(label.getName()).append(":\n");
} }
@@ -288,7 +270,7 @@ public class JetControlFlowTest extends JetLiteFixture {
append(" NEXT:").append(String.format("%1$-" + maxNextLength + "s", formatInstructionList(instruction.getNextInstructions()))). append(" NEXT:").append(String.format("%1$-" + maxNextLength + "s", formatInstructionList(instruction.getNextInstructions()))).
append(" PREV:").append(formatInstructionList(instruction.getPreviousInstructions())).append("\n"); append(" PREV:").append(formatInstructionList(instruction.getPreviousInstructions())).append("\n");
} }
for (Pseudocode local : locals) { for (PseudocodeImpl local : locals) {
dumpInstructions(local, out); dumpInstructions(local, out);
} }
} }
@@ -300,7 +282,7 @@ public class JetControlFlowTest extends JetLiteFixture {
public void visitLocalDeclarationInstruction(LocalDeclarationInstruction instruction) { public void visitLocalDeclarationInstruction(LocalDeclarationInstruction instruction) {
int index = count[0]; int index = count[0];
// instruction.getBody().dumpSubgraph(out, "subgraph cluster_" + index, count, "color=blue;\nlabel = \"f" + index + "\";", nodeToName); // instruction.getBody().dumpSubgraph(out, "subgraph cluster_" + index, count, "color=blue;\nlabel = \"f" + index + "\";", nodeToName);
printEdge(out, nodeToName.get(instruction), nodeToName.get(instruction.getBody().getMutableInstructionList().get(0)), null); printEdge(out, nodeToName.get(instruction), nodeToName.get(((PseudocodeImpl)instruction.getBody()).getAllInstructions().get(0)), null);
visitInstructionWithNext(instruction); visitInstructionWithNext(instruction);
} }
@@ -415,7 +397,7 @@ public class JetControlFlowTest extends JetLiteFixture {
int[] count = new int[1]; int[] count = new int[1];
Map<Instruction, String> nodeToName = new HashMap<Instruction, String>(); Map<Instruction, String> nodeToName = new HashMap<Instruction, String>();
for (Pseudocode pseudocode : pseudocodes) { for (Pseudocode pseudocode : pseudocodes) {
dumpNodes(pseudocode.getMutableInstructionList(), out, count, nodeToName, Sets.newHashSet(pseudocode.getInstructions())); dumpNodes(((PseudocodeImpl)pseudocode).getAllInstructions(), out, count, nodeToName, Sets.newHashSet(pseudocode.getInstructions()));
} }
int i = 0; int i = 0;
for (Pseudocode pseudocode : pseudocodes) { for (Pseudocode pseudocode : pseudocodes) {
@@ -431,7 +413,7 @@ public class JetControlFlowTest extends JetLiteFixture {
out.println("subgraph cluster_" + i + " {\n" + out.println("subgraph cluster_" + i + " {\n" +
"label=\"" + label + "\";\n" + "label=\"" + label + "\";\n" +
"color=blue;\n"); "color=blue;\n");
dumpEdges(pseudocode.getMutableInstructionList(), out, count, nodeToName); dumpEdges(((PseudocodeImpl)pseudocode).getAllInstructions(), out, count, nodeToName);
out.println("}"); out.println("}");
i++; i++;
} }
@@ -21,7 +21,6 @@ import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.CompileCompilerDependenciesTest; import org.jetbrains.jet.CompileCompilerDependenciesTest;
import org.jetbrains.jet.JetLiteFixture; import org.jetbrains.jet.JetLiteFixture;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.diagnostics.Diagnostic; 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.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
@@ -107,8 +106,7 @@ public class CheckerTestUtilTest extends JetLiteFixture {
public void test(final @NotNull PsiFile psiFile) { public void test(final @NotNull PsiFile psiFile) {
BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegration( BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegration(
(JetFile) psiFile, JetControlFlowDataTraceFactory.EMPTY, (JetFile) psiFile, CompileCompilerDependenciesTest.compilerDependenciesForTests(CompilerSpecialMode.REGULAR, true))
CompileCompilerDependenciesTest.compilerDependenciesForTests(CompilerSpecialMode.REGULAR, true))
.getBindingContext(); .getBindingContext();
String expectedText = CheckerTestUtil.addDiagnosticMarkersToText(psiFile, CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, psiFile)).toString(); String expectedText = CheckerTestUtil.addDiagnosticMarkersToText(psiFile, CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, psiFile)).toString();
@@ -29,7 +29,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetLiteFixture; import org.jetbrains.jet.JetLiteFixture;
import org.jetbrains.jet.JetTestCaseBuilder; import org.jetbrains.jet.JetTestCaseBuilder;
import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.AnalyzingUtils; import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
@@ -172,9 +171,7 @@ public class JetDiagnosticsTest extends JetLiteFixture {
} }
BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration( BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
getProject(), jetFiles, Predicates.<PsiFile>alwaysTrue(), JetControlFlowDataTraceFactory.EMPTY, getProject(), jetFiles, Predicates.<PsiFile>alwaysTrue(), myEnvironment.getCompilerDependencies()).getBindingContext();
myEnvironment.getCompilerDependencies())
.getBindingContext();
boolean ok = true; boolean ok = true;
@@ -26,7 +26,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetTestCaseBuilder; import org.jetbrains.jet.JetTestCaseBuilder;
import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.di.InjectorForJavaSemanticServices; import org.jetbrains.jet.di.InjectorForJavaSemanticServices;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
@@ -87,8 +86,7 @@ public class ReadJavaBinaryClassTest extends TestCaseWithTmpdir {
JetFile psiFile = (JetFile) ((PsiFileFactoryImpl) PsiFileFactory.getInstance(jetCoreEnvironment.getProject())).trySetupPsiForFile(virtualFile, JetLanguage.INSTANCE, true, false); JetFile psiFile = (JetFile) ((PsiFileFactoryImpl) PsiFileFactory.getInstance(jetCoreEnvironment.getProject())).trySetupPsiForFile(virtualFile, JetLanguage.INSTANCE, true, false);
BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegrationAndCheckForErrors( BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegrationAndCheckForErrors(
psiFile, JetControlFlowDataTraceFactory.EMPTY, psiFile, jetCoreEnvironment.getCompilerDependencies())
jetCoreEnvironment.getCompilerDependencies())
.getBindingContext(); .getBindingContext();
return bindingContext.get(BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR, FqName.topLevel(Name.identifier("test"))); return bindingContext.get(BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR, FqName.topLevel(Name.identifier("test")));
} }
@@ -24,7 +24,6 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.analyzer.AnalyzeExhaust; import org.jetbrains.jet.analyzer.AnalyzeExhaust;
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment; import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetPsiUtil; import org.jetbrains.jet.lang.psi.JetPsiUtil;
import org.jetbrains.jet.lang.resolve.AnalyzingUtils; import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
@@ -186,8 +185,7 @@ public abstract class CodegenTestCase extends UsefulTestCase {
private GenerationState generateCommon(ClassBuilderFactory classBuilderFactory) { private GenerationState generateCommon(ClassBuilderFactory classBuilderFactory) {
final AnalyzeExhaust analyzeExhaust = AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegrationAndCheckForErrors( final AnalyzeExhaust analyzeExhaust = AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegrationAndCheckForErrors(
myFile, JetControlFlowDataTraceFactory.EMPTY, myFile, myEnvironment.getCompilerDependencies());
myEnvironment.getCompilerDependencies());
analyzeExhaust.throwIfError(); analyzeExhaust.throwIfError();
AnalyzingUtils.throwExceptionOnErrors(analyzeExhaust.getBindingContext()); AnalyzingUtils.throwExceptionOnErrors(analyzeExhaust.getBindingContext());
GenerationState state = new GenerationState(myEnvironment.getProject(), classBuilderFactory, analyzeExhaust, Collections.singletonList(myFile)); GenerationState state = new GenerationState(myEnvironment.getProject(), classBuilderFactory, analyzeExhaust, Collections.singletonList(myFile));
@@ -19,7 +19,6 @@ package org.jetbrains.jet.codegen;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.CompileCompilerDependenciesTest; import org.jetbrains.jet.CompileCompilerDependenciesTest;
import org.jetbrains.jet.analyzer.AnalyzeExhaust; import org.jetbrains.jet.analyzer.AnalyzeExhaust;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM; import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM;
import org.jetbrains.jet.lang.resolve.java.CompilerSpecialMode; import org.jetbrains.jet.lang.resolve.java.CompilerSpecialMode;
@@ -37,8 +36,7 @@ public class GenerationUtils {
public static GenerationState compileFileGetGenerationStateForTest(JetFile psiFile, @NotNull CompilerSpecialMode compilerSpecialMode) { public static GenerationState compileFileGetGenerationStateForTest(JetFile psiFile, @NotNull CompilerSpecialMode compilerSpecialMode) {
final AnalyzeExhaust analyzeExhaust = AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegrationAndCheckForErrors( final AnalyzeExhaust analyzeExhaust = AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegrationAndCheckForErrors(
psiFile, JetControlFlowDataTraceFactory.EMPTY, psiFile, CompileCompilerDependenciesTest.compilerDependenciesForTests(compilerSpecialMode, true));
CompileCompilerDependenciesTest.compilerDependenciesForTests(compilerSpecialMode, true));
analyzeExhaust.throwIfError(); analyzeExhaust.throwIfError();
GenerationState state = new GenerationState(psiFile.getProject(), ClassBuilderFactories.binaries(false), analyzeExhaust, Collections.singletonList(psiFile)); GenerationState state = new GenerationState(psiFile.getProject(), ClassBuilderFactories.binaries(false), analyzeExhaust, Collections.singletonList(psiFile));
state.compileCorrectFiles(CompilationErrorHandler.THROW_EXCEPTION); state.compileCorrectFiles(CompilationErrorHandler.THROW_EXCEPTION);
@@ -22,7 +22,6 @@ import org.jetbrains.jet.JetLiteFixture;
import org.jetbrains.jet.JetTestCaseBuilder; import org.jetbrains.jet.JetTestCaseBuilder;
import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.analyzer.AnalyzeExhaust; import org.jetbrains.jet.analyzer.AnalyzeExhaust;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.psi.JetElement; import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
@@ -78,8 +77,7 @@ public class DescriptorRendererTest extends JetLiteFixture {
JetFile psiFile = createPsiFile(null, fileName, loadFile(fileName)); JetFile psiFile = createPsiFile(null, fileName, loadFile(fileName));
AnalyzeExhaust analyzeExhaust = AnalyzeExhaust analyzeExhaust =
AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegration( AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegration(
(JetFile) psiFile, JetControlFlowDataTraceFactory.EMPTY, (JetFile) psiFile, myEnvironment.getCompilerDependencies());
myEnvironment.getCompilerDependencies());
final BindingContext bindingContext = analyzeExhaust.getBindingContext(); final BindingContext bindingContext = analyzeExhaust.getBindingContext();
final List<DeclarationDescriptor> descriptors = new ArrayList<DeclarationDescriptor>(); final List<DeclarationDescriptor> descriptors = new ArrayList<DeclarationDescriptor>();
psiFile.acceptChildren(new JetVisitorVoid() { psiFile.acceptChildren(new JetVisitorVoid() {
@@ -27,7 +27,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.analyzer.AnalyzeExhaust; import org.jetbrains.jet.analyzer.AnalyzeExhaust;
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment; import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
@@ -154,8 +153,7 @@ public abstract class ExpectedResolveData {
JetStandardLibrary lib = JetStandardLibrary.getInstance(); JetStandardLibrary lib = JetStandardLibrary.getInstance();
AnalyzeExhaust analyzeExhaust = AnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(project, files, AnalyzeExhaust analyzeExhaust = AnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(project, files,
Predicates.<PsiFile>alwaysTrue(), JetControlFlowDataTraceFactory.EMPTY, Predicates.<PsiFile>alwaysTrue(), jetCoreEnvironment.getCompilerDependencies());
jetCoreEnvironment.getCompilerDependencies());
BindingContext bindingContext = analyzeExhaust.getBindingContext(); BindingContext bindingContext = analyzeExhaust.getBindingContext();
for (Diagnostic diagnostic : bindingContext.getDiagnostics()) { for (Diagnostic diagnostic : bindingContext.getDiagnostics()) {
if (diagnostic.getFactory() instanceof UnresolvedReferenceDiagnosticFactory) { if (diagnostic.getFactory() instanceof UnresolvedReferenceDiagnosticFactory) {
@@ -20,7 +20,6 @@ import org.jetbrains.jet.JetLiteFixture;
import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.analyzer.AnalyzeExhaust; import org.jetbrains.jet.analyzer.AnalyzeExhaust;
import org.jetbrains.jet.di.InjectorForTests; import org.jetbrains.jet.di.InjectorForTests;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
@@ -66,7 +65,6 @@ public class JetDefaultModalityModifiersTest extends JetLiteFixture {
JetDeclaration aClass = declarations.get(0); JetDeclaration aClass = declarations.get(0);
assert aClass instanceof JetClass; assert aClass instanceof JetClass;
AnalyzeExhaust bindingContext = AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegration(file, AnalyzeExhaust bindingContext = AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegration(file,
JetControlFlowDataTraceFactory.EMPTY,
myEnvironment.getCompilerDependencies()); myEnvironment.getCompilerDependencies());
DeclarationDescriptor classDescriptor = bindingContext.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, aClass); DeclarationDescriptor classDescriptor = bindingContext.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, aClass);
WritableScopeImpl scope = new WritableScopeImpl(libraryScope, root, RedeclarationHandler.DO_NOTHING); WritableScopeImpl scope = new WritableScopeImpl(libraryScope, root, RedeclarationHandler.DO_NOTHING);
@@ -698,7 +698,7 @@ public class JetTypeCheckerTest extends JetLiteFixture {
parameterScope.changeLockLevel(WritableScope.LockLevel.BOTH); parameterScope.changeLockLevel(WritableScope.LockLevel.BOTH);
// This call has side-effects on the parameterScope (fills it in) // This call has side-effects on the parameterScope (fills it in)
List<TypeParameterDescriptor> typeParameters List<TypeParameterDescriptorImpl> typeParameters
= descriptorResolver.resolveTypeParameters(classDescriptor, parameterScope, classElement.getTypeParameters(), JetTestUtils.DUMMY_TRACE); = descriptorResolver.resolveTypeParameters(classDescriptor, parameterScope, classElement.getTypeParameters(), JetTestUtils.DUMMY_TRACE);
descriptorResolver.resolveGenericBounds(classElement, parameterScope, typeParameters, JetTestUtils.DUMMY_TRACE); descriptorResolver.resolveGenericBounds(classElement, parameterScope, typeParameters, JetTestUtils.DUMMY_TRACE);
@@ -110,7 +110,7 @@ public final class JetDescriptorIconProvider {
return ((PropertyDescriptor)descriptor).isVar() ? JetIcons.FIELD_VAR : JetIcons.FIELD_VAL; return ((PropertyDescriptor)descriptor).isVar() ? JetIcons.FIELD_VAR : JetIcons.FIELD_VAL;
} }
if (descriptor instanceof TypeParameterDescriptor) { if (descriptor instanceof TypeParameterDescriptorImpl) {
return PlatformIcons.CLASS_ICON; return PlatformIcons.CLASS_ICON;
} }
@@ -183,7 +183,7 @@ public class JetCompletionContributor extends CompletionContributor {
DeclarationDescriptor descriptor = ((JetLookupObject)object).getDescriptor(); DeclarationDescriptor descriptor = ((JetLookupObject)object).getDescriptor();
return (descriptor instanceof ClassDescriptor) || return (descriptor instanceof ClassDescriptor) ||
(descriptor instanceof NamespaceDescriptor) || (descriptor instanceof NamespaceDescriptor) ||
(descriptor instanceof TypeParameterDescriptor); (descriptor instanceof TypeParameterDescriptorImpl);
} }
} }
@@ -33,7 +33,6 @@ import com.intellij.psi.util.PsiTreeUtil;
import jet.Tuple2; import jet.Tuple2;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
@@ -74,8 +73,7 @@ public class JetSourceNavigationHelper {
BindingContext bindingContext = AnalyzerFacadeProvider.getAnalyzerFacadeForProject(project).analyzeFiles( BindingContext bindingContext = AnalyzerFacadeProvider.getAnalyzerFacadeForProject(project).analyzeFiles(
project, project,
libraryFiles, libraryFiles,
Predicates.<PsiFile>alwaysTrue(), Predicates.<PsiFile>alwaysTrue()).getBindingContext();
JetControlFlowDataTraceFactory.EMPTY).getBindingContext();
D descriptor = bindingContext.get(slice, fqName); D descriptor = bindingContext.get(slice, fqName);
if (descriptor != null) { if (descriptor != null) {
return new Tuple2<BindingContext, D>(bindingContext, descriptor); return new Tuple2<BindingContext, D>(bindingContext, descriptor);
@@ -28,7 +28,6 @@ import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.util.Function; import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.analyzer.AnalyzeExhaust; import org.jetbrains.jet.analyzer.AnalyzeExhaust;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
import org.jetbrains.jet.lang.diagnostics.Errors; import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
@@ -94,7 +93,6 @@ public final class AnalyzerFacadeWithCache {
AnalyzeExhaust exhaust = AnalyzerFacadeProvider.getAnalyzerFacadeForFile(file).analyzeBodiesInFiles( AnalyzeExhaust exhaust = AnalyzerFacadeProvider.getAnalyzerFacadeForFile(file).analyzeBodiesInFiles(
file.getProject(), file.getProject(),
Predicates.<PsiFile>equalTo(file), Predicates.<PsiFile>equalTo(file),
JetControlFlowDataTraceFactory.EMPTY,
new DelegatingBindingTrace(analyzeExhaustHeaders.getBindingContext()), new DelegatingBindingTrace(analyzeExhaustHeaders.getBindingContext()),
context); context);
@@ -137,8 +135,7 @@ public final class AnalyzerFacadeWithCache {
AnalyzeExhaust exhaust = AnalyzerFacadeProvider.getAnalyzerFacadeForFile(fileToCache) AnalyzeExhaust exhaust = AnalyzerFacadeProvider.getAnalyzerFacadeForFile(fileToCache)
.analyzeFiles(fileToCache.getProject(), .analyzeFiles(fileToCache.getProject(),
headerFiles, headerFiles,
Predicates.<PsiFile>alwaysFalse(), Predicates.<PsiFile>alwaysFalse());
JetControlFlowDataTraceFactory.EMPTY);
return new Result<AnalyzeExhaust>(exhaust, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT); return new Result<AnalyzeExhaust>(exhaust, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
} }
@@ -22,7 +22,6 @@ import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.analyzer.AnalyzeExhaust; import org.jetbrains.jet.analyzer.AnalyzeExhaust;
import org.jetbrains.jet.analyzer.AnalyzerFacade; import org.jetbrains.jet.analyzer.AnalyzerFacade;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.BodiesResolveContext; import org.jetbrains.jet.lang.resolve.BodiesResolveContext;
@@ -44,8 +43,7 @@ public enum JSAnalyzerFacadeForIDEA implements AnalyzerFacade {
@Override @Override
public AnalyzeExhaust analyzeFiles(@NotNull Project project, public AnalyzeExhaust analyzeFiles(@NotNull Project project,
@NotNull Collection<JetFile> files, @NotNull Collection<JetFile> files,
@NotNull Predicate<PsiFile> filesToAnalyzeCompletely, @NotNull Predicate<PsiFile> filesToAnalyzeCompletely) {
@NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) {
return AnalyzerFacadeForJS.analyzeFiles(files, filesToAnalyzeCompletely, new IDEAConfig(project), true); return AnalyzerFacadeForJS.analyzeFiles(files, filesToAnalyzeCompletely, new IDEAConfig(project), true);
} }
@@ -53,7 +51,6 @@ public enum JSAnalyzerFacadeForIDEA implements AnalyzerFacade {
@Override @Override
public AnalyzeExhaust analyzeBodiesInFiles(@NotNull Project project, public AnalyzeExhaust analyzeBodiesInFiles(@NotNull Project project,
@NotNull Predicate<PsiFile> filesForBodiesResolve, @NotNull Predicate<PsiFile> filesForBodiesResolve,
@NotNull JetControlFlowDataTraceFactory flowDataTraceFactory,
@NotNull BindingTrace traceContext, @NotNull BindingTrace traceContext,
@NotNull BodiesResolveContext bodiesResolveContext) { @NotNull BodiesResolveContext bodiesResolveContext) {
return AnalyzerFacadeForJS.analyzeBodiesInFiles(filesForBodiesResolve, new IDEAConfig(project), traceContext, bodiesResolveContext); return AnalyzerFacadeForJS.analyzeBodiesInFiles(filesForBodiesResolve, new IDEAConfig(project), traceContext, bodiesResolveContext);

Some files were not shown because too many files have changed in this diff Show More