Merge branch 'master' of github.com:JetBrains/kotlin
This commit is contained in:
+3
@@ -410,6 +410,9 @@
|
||||
<inspection_tool class="UtilityClassWithPublicConstructor" 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="ignorableAnnotations">
|
||||
<value />
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="VolatileLongOrDoubleField" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="WaitNotInLoop" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
|
||||
+1
-3
@@ -26,8 +26,6 @@
|
||||
<RunnerSettings RunnerId="Run" />
|
||||
<ConfigurationWrapper RunnerId="Debug" />
|
||||
<ConfigurationWrapper RunnerId="Run" />
|
||||
<method>
|
||||
<option name="AntTarget" enabled="false" antfile="file://$PROJECT_DIR$/js_backend_tests.xml" target="copy_lib" />
|
||||
</method>
|
||||
<method />
|
||||
</configuration>
|
||||
</component>
|
||||
@@ -198,7 +198,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
||||
private Type generateBody(FunctionDescriptor funDescriptor, ClassBuilder cv, JetDeclarationWithBody body) {
|
||||
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());
|
||||
FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state);
|
||||
JvmMethodSignature jvmMethodSignature = invokeSignature(funDescriptor);
|
||||
|
||||
@@ -35,25 +35,6 @@ import java.util.LinkedHashMap;
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
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;
|
||||
|
||||
@@ -121,31 +102,31 @@ public abstract class CodegenContext {
|
||||
}
|
||||
|
||||
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) {
|
||||
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) {
|
||||
return new AnonymousClassContext(descriptor, kind, this, closure, typeMapper);
|
||||
return new CodegenContexts.AnonymousClassContext(descriptor, kind, this, closure, typeMapper);
|
||||
}
|
||||
|
||||
public MethodContext intoFunction(FunctionDescriptor descriptor) {
|
||||
return new MethodContext(descriptor, getContextKind(), this);
|
||||
public CodegenContexts.MethodContext intoFunction(FunctionDescriptor descriptor) {
|
||||
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) {
|
||||
descriptor = new ConstructorDescriptorImpl(getThisDescriptor(), Collections.<AnnotationDescriptor>emptyList(), true)
|
||||
.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) {
|
||||
return new ClosureContext(funDescriptor, classDescriptor, this, closureCodegen, internalClassName, typeMapper);
|
||||
public CodegenContexts.ClosureContext intoClosure(FunctionDescriptor funDescriptor, ClassDescriptor classDescriptor, String internalClassName, ClosureCodegen closureCodegen, JetTypeMapper typeMapper) {
|
||||
return new CodegenContexts.ClosureContext(funDescriptor, classDescriptor, this, closureCodegen, internalClassName, typeMapper);
|
||||
}
|
||||
|
||||
public FrameMap prepareFrame(JetTypeMapper mapper) {
|
||||
@@ -190,7 +171,7 @@ public abstract class CodegenContext {
|
||||
}
|
||||
|
||||
public int getTypeInfoConstantIndex(JetType type) {
|
||||
if (parentContext != STATIC) { return parentContext.getTypeInfoConstantIndex(type); }
|
||||
if (parentContext != CodegenContexts.STATIC) { return parentContext.getTypeInfoConstantIndex(type); }
|
||||
|
||||
if(typeInfoConstants == null) {
|
||||
typeInfoConstants = new LinkedHashMap<JetType, Integer>();
|
||||
@@ -242,7 +223,7 @@ public abstract class CodegenContext {
|
||||
CallableMemberDescriptor.Kind.DECLARATION
|
||||
);
|
||||
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(
|
||||
myAccessor, Collections.<AnnotationDescriptor>emptyList(), myAccessor.getModality(),
|
||||
@@ -280,174 +261,4 @@ public abstract class CodegenContext {
|
||||
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,
|
||||
fd.getExpectedThisObject(),
|
||||
Collections.<TypeParameterDescriptor>emptyList(),
|
||||
Collections.<TypeParameterDescriptorImpl>emptyList(),
|
||||
fd.getValueParameters(),
|
||||
fd.getReturnType(),
|
||||
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;
|
||||
v.invokevirtual("jet/TypeInfo", "getClassObject", "()Ljava/lang/Object;");
|
||||
v.checkcast(asmType(typeParameterDescriptor.getClassObjectType()));
|
||||
@@ -1162,7 +1162,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
boolean isStatic = containingDeclaration instanceof NamespaceDescriptor;
|
||||
propertyDescriptor = propertyDescriptor.getOriginal();
|
||||
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;
|
||||
Method getter;
|
||||
Method setter;
|
||||
@@ -1438,8 +1438,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
}
|
||||
|
||||
private StackValue generateReceiver(DeclarationDescriptor provided) {
|
||||
assert context instanceof CodegenContext.ReceiverContext;
|
||||
CodegenContext.ReceiverContext cur = (CodegenContext.ReceiverContext) context;
|
||||
assert context instanceof CodegenContexts.ReceiverContext;
|
||||
CodegenContexts.ReceiverContext cur = (CodegenContexts.ReceiverContext) context;
|
||||
if (cur.getReceiverDescriptor() == provided) {
|
||||
StackValue result = cur.getReceiverExpression(typeMapper);
|
||||
return castToRequiredTypeOfInterfaceIfNeeded(result, provided, null);
|
||||
@@ -1458,7 +1458,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
cur = context;
|
||||
StackValue result = StackValue.local(0, TYPE_OBJECT);
|
||||
while (cur != null) {
|
||||
if(cur instanceof CodegenContext.MethodContext && !(cur instanceof CodegenContext.ConstructorContext))
|
||||
if(cur instanceof CodegenContexts.MethodContext && !(cur instanceof CodegenContexts.ConstructorContext))
|
||||
cur = cur.getParentContext();
|
||||
|
||||
if (DescriptorUtils.isSubclass(cur.getThisDescriptor(), calleeContainingClass)) {
|
||||
@@ -1474,7 +1474,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
|
||||
result = cur.getOuterExpression(result);
|
||||
|
||||
if(cur instanceof CodegenContext.ConstructorContext) {
|
||||
if(cur instanceof CodegenContexts.ConstructorContext) {
|
||||
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();
|
||||
JetType leftType = bindingContext.get(BindingContext.EXPRESSION_TYPE, left);
|
||||
DeclarationDescriptor descriptor = rightType.getConstructor().getDeclarationDescriptor();
|
||||
if (descriptor instanceof ClassDescriptor || descriptor instanceof TypeParameterDescriptor) {
|
||||
if (descriptor instanceof ClassDescriptor || descriptor instanceof TypeParameterDescriptorImpl) {
|
||||
StackValue value = genQualified(receiver, left);
|
||||
value.put(JetTypeMapper.boxType(value.type), v);
|
||||
assert leftType != null;
|
||||
|
||||
@@ -69,7 +69,7 @@ public class FunctionCodegen {
|
||||
JvmMethodSignature jvmMethod, boolean needJetAnnotations,
|
||||
@Nullable String propertyTypeSignature, FunctionDescriptor functionDescriptor) {
|
||||
|
||||
CodegenContext.MethodContext funContext = owner.intoFunction(functionDescriptor);
|
||||
CodegenContexts.MethodContext funContext = owner.intoFunction(functionDescriptor);
|
||||
|
||||
final JetExpression bodyExpression = f.getBodyExpression();
|
||||
generatedMethod(bodyExpression, jvmMethod, needJetAnnotations, propertyTypeSignature, funContext, functionDescriptor, f);
|
||||
@@ -78,7 +78,7 @@ public class FunctionCodegen {
|
||||
private void generatedMethod(JetExpression bodyExpressions,
|
||||
JvmMethodSignature jvmSignature,
|
||||
boolean needJetAnnotations, @Nullable String propertyTypeSignature,
|
||||
CodegenContext.MethodContext context,
|
||||
CodegenContexts.MethodContext context,
|
||||
FunctionDescriptor functionDescriptor,
|
||||
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();
|
||||
|
||||
if(kind != OwnerKind.TRAIT_IMPL) {
|
||||
|
||||
@@ -449,7 +449,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, myClass);
|
||||
|
||||
CodegenContext.ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor, typeMapper);
|
||||
CodegenContexts.ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor, typeMapper);
|
||||
|
||||
JvmMethodSignature constructorMethod;
|
||||
CallableMethod callableMethod;
|
||||
|
||||
@@ -463,7 +463,7 @@ public class JetTypeMapper {
|
||||
return asmType;
|
||||
}
|
||||
|
||||
if (descriptor instanceof TypeParameterDescriptor) {
|
||||
if (descriptor instanceof TypeParameterDescriptorImpl) {
|
||||
|
||||
Type type = mapType(((TypeParameterDescriptor) descriptor).getUpperBoundsAsType(), kind);
|
||||
if (signatureVisitor != null) {
|
||||
@@ -722,7 +722,7 @@ public class JetTypeMapper {
|
||||
signatureVisitor.writeInterfaceBoundEnd();
|
||||
}
|
||||
}
|
||||
if (jetType.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) {
|
||||
if (jetType.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptorImpl) {
|
||||
signatureVisitor.writeInterfaceBound();
|
||||
mapType(jetType, signatureVisitor, MapTypeMode.TYPE_PARAMETER);
|
||||
signatureVisitor.writeInterfaceBoundEnd();
|
||||
@@ -966,7 +966,7 @@ public class JetTypeMapper {
|
||||
|
||||
public boolean isGenericsArray(JetType type) {
|
||||
DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor();
|
||||
if(declarationDescriptor instanceof TypeParameterDescriptor)
|
||||
if(declarationDescriptor instanceof TypeParameterDescriptorImpl)
|
||||
return true;
|
||||
|
||||
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.resolve.BindingContext;
|
||||
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.JvmClassName;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
@@ -57,7 +56,7 @@ public class NamespaceCodegen {
|
||||
|
||||
public void generate(JetFile 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 PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, state);
|
||||
@@ -100,7 +99,7 @@ public class NamespaceCodegen {
|
||||
mv.visitCode();
|
||||
|
||||
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()) {
|
||||
if (declaration instanceof JetProperty) {
|
||||
|
||||
@@ -106,9 +106,9 @@ public class ObjectOrClosureCodegen {
|
||||
FunctionDescriptor fd = (FunctionDescriptor) d;
|
||||
|
||||
// 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)
|
||||
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.CompilerMessageLocation;
|
||||
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.JetPsiUtil;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
@@ -246,7 +245,6 @@ public class KotlinToJVMBytecodeCompiler {
|
||||
public AnalyzeExhaust invoke() {
|
||||
return AnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
|
||||
environment.getProject(), environment.getSourceFiles(), filesToAnalyzeCompletely,
|
||||
JetControlFlowDataTraceFactory.EMPTY,
|
||||
configuration.getEnvironment().getCompilerDependencies());
|
||||
}
|
||||
}, environment.getSourceFiles()
|
||||
|
||||
+32
-10
@@ -17,16 +17,42 @@
|
||||
|
||||
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 org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||
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.*;
|
||||
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.OverloadingConflictResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.*;
|
||||
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;
|
||||
|
||||
/* 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 ObservableBindingTrace observableBindingTrace;
|
||||
private final ModuleDescriptor moduleDescriptor;
|
||||
private final JetControlFlowDataTraceFactory jetControlFlowDataTraceFactory;
|
||||
private final CompilerDependencies compilerDependencies;
|
||||
private CompilerSpecialMode compilerSpecialMode;
|
||||
private JavaBridgeConfiguration javaBridgeConfiguration;
|
||||
@@ -69,7 +94,6 @@ public class InjectorForTopDownAnalyzerForJvm {
|
||||
@NotNull TopDownAnalysisParameters topDownAnalysisParameters,
|
||||
@NotNull ObservableBindingTrace observableBindingTrace,
|
||||
@NotNull ModuleDescriptor moduleDescriptor,
|
||||
JetControlFlowDataTraceFactory jetControlFlowDataTraceFactory,
|
||||
@NotNull CompilerDependencies compilerDependencies
|
||||
) {
|
||||
this.topDownAnalyzer = new TopDownAnalyzer();
|
||||
@@ -82,7 +106,6 @@ public class InjectorForTopDownAnalyzerForJvm {
|
||||
this.topDownAnalysisParameters = topDownAnalysisParameters;
|
||||
this.observableBindingTrace = observableBindingTrace;
|
||||
this.moduleDescriptor = moduleDescriptor;
|
||||
this.jetControlFlowDataTraceFactory = jetControlFlowDataTraceFactory;
|
||||
this.compilerDependencies = compilerDependencies;
|
||||
this.compilerSpecialMode = compilerDependencies.getCompilerSpecialMode();
|
||||
this.javaBridgeConfiguration = new JavaBridgeConfiguration();
|
||||
@@ -126,7 +149,6 @@ public class InjectorForTopDownAnalyzerForJvm {
|
||||
this.bodyResolver.setTopDownAnalysisParameters(topDownAnalysisParameters);
|
||||
this.bodyResolver.setTrace(observableBindingTrace);
|
||||
|
||||
this.controlFlowAnalyzer.setFlowDataTraceFactory(jetControlFlowDataTraceFactory);
|
||||
this.controlFlowAnalyzer.setTopDownAnalysisParameters(topDownAnalysisParameters);
|
||||
this.controlFlowAnalyzer.setTrace(observableBindingTrace);
|
||||
|
||||
|
||||
+11
-24
@@ -24,7 +24,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.analyzer.AnalyzeExhaust;
|
||||
import org.jetbrains.jet.analyzer.AnalyzerFacade;
|
||||
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.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.resolve.*;
|
||||
@@ -50,9 +49,8 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade {
|
||||
@NotNull
|
||||
public AnalyzeExhaust analyzeFiles(@NotNull Project project,
|
||||
@NotNull Collection<JetFile> files,
|
||||
@NotNull Predicate<PsiFile> filesToAnalyzeCompletely,
|
||||
@NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) {
|
||||
return analyzeFilesWithJavaIntegration(project, files, filesToAnalyzeCompletely, flowDataTraceFactory,
|
||||
@NotNull Predicate<PsiFile> filesToAnalyzeCompletely) {
|
||||
return analyzeFilesWithJavaIntegration(project, files, filesToAnalyzeCompletely,
|
||||
compilerDependenciesForProduction(CompilerSpecialMode.REGULAR), true);
|
||||
}
|
||||
|
||||
@@ -60,22 +58,19 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade {
|
||||
@Override
|
||||
public AnalyzeExhaust analyzeBodiesInFiles(@NotNull Project project,
|
||||
@NotNull Predicate<PsiFile> filesForBodiesResolve,
|
||||
@NotNull JetControlFlowDataTraceFactory flowDataTraceFactory,
|
||||
@NotNull BindingTrace headersTraceContext,
|
||||
@NotNull BodiesResolveContext bodiesResolveContext
|
||||
) {
|
||||
return analyzeBodiesInFilesWithJavaIntegration(
|
||||
project, filesForBodiesResolve, flowDataTraceFactory,
|
||||
compilerDependenciesForProduction(CompilerSpecialMode.REGULAR),
|
||||
project, filesForBodiesResolve, compilerDependenciesForProduction(CompilerSpecialMode.REGULAR),
|
||||
headersTraceContext, bodiesResolveContext);
|
||||
}
|
||||
|
||||
public static AnalyzeExhaust analyzeOneFileWithJavaIntegrationAndCheckForErrors(
|
||||
JetFile file, JetControlFlowDataTraceFactory flowDataTraceFactory,
|
||||
@NotNull CompilerDependencies compilerDependencies) {
|
||||
JetFile file, @NotNull CompilerDependencies compilerDependencies) {
|
||||
AnalyzingUtils.checkForSyntacticErrors(file);
|
||||
|
||||
AnalyzeExhaust analyzeExhaust = analyzeOneFileWithJavaIntegration(file, flowDataTraceFactory, compilerDependencies);
|
||||
AnalyzeExhaust analyzeExhaust = analyzeOneFileWithJavaIntegration(file, compilerDependencies);
|
||||
|
||||
AnalyzingUtils.throwExceptionOnErrors(analyzeExhaust.getBindingContext());
|
||||
|
||||
@@ -83,24 +78,20 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade {
|
||||
}
|
||||
|
||||
public static AnalyzeExhaust analyzeOneFileWithJavaIntegration(
|
||||
JetFile file, JetControlFlowDataTraceFactory flowDataTraceFactory,
|
||||
@NotNull CompilerDependencies compilerDependencies) {
|
||||
JetFile file, @NotNull CompilerDependencies compilerDependencies) {
|
||||
return analyzeFilesWithJavaIntegration(file.getProject(), Collections.singleton(file),
|
||||
Predicates.<PsiFile>alwaysTrue(), flowDataTraceFactory, compilerDependencies);
|
||||
Predicates.<PsiFile>alwaysTrue(), compilerDependencies);
|
||||
}
|
||||
|
||||
public static AnalyzeExhaust analyzeFilesWithJavaIntegration(
|
||||
Project project, Collection<JetFile> files, Predicate<PsiFile> filesToAnalyzeCompletely,
|
||||
JetControlFlowDataTraceFactory flowDataTraceFactory,
|
||||
@NotNull CompilerDependencies compilerDependencies) {
|
||||
return analyzeFilesWithJavaIntegration(
|
||||
project, files, filesToAnalyzeCompletely,
|
||||
flowDataTraceFactory, compilerDependencies, false);
|
||||
project, files, filesToAnalyzeCompletely, compilerDependencies, false);
|
||||
}
|
||||
|
||||
public static AnalyzeExhaust analyzeFilesWithJavaIntegration(
|
||||
Project project, Collection<JetFile> files, Predicate<PsiFile> filesToAnalyzeCompletely,
|
||||
JetControlFlowDataTraceFactory flowDataTraceFactory,
|
||||
@NotNull CompilerDependencies compilerDependencies,
|
||||
boolean storeContextForBodiesResolve) {
|
||||
BindingTraceContext bindingTraceContext = new BindingTraceContext();
|
||||
@@ -112,8 +103,7 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade {
|
||||
|
||||
InjectorForTopDownAnalyzerForJvm injector = new InjectorForTopDownAnalyzerForJvm(
|
||||
project, topDownAnalysisParameters,
|
||||
new ObservableBindingTrace(bindingTraceContext), owner, flowDataTraceFactory,
|
||||
compilerDependencies);
|
||||
new ObservableBindingTrace(bindingTraceContext), owner, compilerDependencies);
|
||||
try {
|
||||
injector.getTopDownAnalyzer().analyzeFiles(files);
|
||||
BodiesResolveContext bodiesResolveContext = storeContextForBodiesResolve ?
|
||||
@@ -127,7 +117,6 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade {
|
||||
|
||||
public static AnalyzeExhaust analyzeBodiesInFilesWithJavaIntegration(
|
||||
Project project, Predicate<PsiFile> filesToAnalyzeCompletely,
|
||||
JetControlFlowDataTraceFactory flowDataTraceFactory,
|
||||
@NotNull CompilerDependencies compilerDependencies,
|
||||
@NotNull BindingTrace traceContext,
|
||||
@NotNull BodiesResolveContext bodiesResolveContext) {
|
||||
@@ -140,8 +129,7 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade {
|
||||
|
||||
InjectorForTopDownAnalyzerForJvm injector = new InjectorForTopDownAnalyzerForJvm(
|
||||
project, topDownAnalysisParameters,
|
||||
new ObservableBindingTrace(traceContext), owner, flowDataTraceFactory,
|
||||
compilerDependencies);
|
||||
new ObservableBindingTrace(traceContext), owner, compilerDependencies);
|
||||
|
||||
try {
|
||||
injector.getTopDownAnalyzer().doProcessForBodies(bodiesResolveContext);
|
||||
@@ -157,7 +145,6 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade {
|
||||
|
||||
Project project = files.iterator().next().getProject();
|
||||
|
||||
return analyzeFilesWithJavaIntegration(project, files, Predicates.<PsiFile>alwaysFalse(),
|
||||
JetControlFlowDataTraceFactory.EMPTY, compilerDependencies);
|
||||
return analyzeFilesWithJavaIntegration(project, files, Predicates.<PsiFile>alwaysFalse(), compilerDependencies);
|
||||
}
|
||||
}
|
||||
|
||||
+19
-9
@@ -49,7 +49,7 @@ import java.util.*;
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class JavaDescriptorResolver {
|
||||
public class JavaDescriptorResolver implements DependencyClassByQualifiedNameResolver {
|
||||
|
||||
public static final Name JAVA_ROOT = Name.special("<java_root>");
|
||||
|
||||
@@ -107,14 +107,14 @@ public class JavaDescriptorResolver {
|
||||
@NotNull
|
||||
private final TypeParameterDescriptorOrigin origin;
|
||||
@NotNull
|
||||
final TypeParameterDescriptor descriptor;
|
||||
final TypeParameterDescriptorImpl descriptor;
|
||||
final PsiTypeParameter psiTypeParameter;
|
||||
@Nullable
|
||||
private final List<JetType> upperBoundsForKotlin;
|
||||
@Nullable
|
||||
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.descriptor = descriptor;
|
||||
this.psiTypeParameter = psiTypeParameter;
|
||||
@@ -122,7 +122,7 @@ public class JavaDescriptorResolver {
|
||||
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) {
|
||||
this.origin = TypeParameterDescriptorOrigin.KOTLIN;
|
||||
this.descriptor = descriptor;
|
||||
@@ -307,6 +307,11 @@ public class JavaDescriptorResolver {
|
||||
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) {
|
||||
if (qualifiedName.getFqName().endsWith(JvmAbi.TRAIT_IMPL_SUFFIX)) {
|
||||
// TODO: only if -$$TImpl class is created by Kotlin
|
||||
@@ -603,10 +608,10 @@ public class JavaDescriptorResolver {
|
||||
@NotNull
|
||||
private final TypeVariableResolver typeVariableResolver;
|
||||
@NotNull
|
||||
private final TypeParameterDescriptor typeParameterDescriptor;
|
||||
private final TypeParameterDescriptorImpl typeParameterDescriptor;
|
||||
|
||||
protected JetSignatureTypeParameterVisitor(PsiTypeParameterListOwner psiOwner,
|
||||
String name, TypeVariableResolver typeVariableResolver, TypeParameterDescriptor typeParameterDescriptor)
|
||||
String name, TypeVariableResolver typeVariableResolver, TypeParameterDescriptorImpl typeParameterDescriptor)
|
||||
{
|
||||
if (name.isEmpty()) {
|
||||
throw new IllegalStateException();
|
||||
@@ -682,7 +687,7 @@ public class JavaDescriptorResolver {
|
||||
|
||||
@Override
|
||||
public JetSignatureVisitor visitFormalTypeParameter(final String name, final TypeInfoVariance variance, boolean reified) {
|
||||
TypeParameterDescriptor typeParameter = TypeParameterDescriptor.createForFurtherModification(
|
||||
TypeParameterDescriptorImpl typeParameter = TypeParameterDescriptorImpl.createForFurtherModification(
|
||||
containingDeclaration,
|
||||
Collections.<AnnotationDescriptor>emptyList(), // TODO: wrong
|
||||
reified,
|
||||
@@ -757,7 +762,7 @@ public class JavaDescriptorResolver {
|
||||
|
||||
@NotNull
|
||||
private TypeParameterDescriptorInitialization makeUninitializedTypeParameter(@NotNull DeclarationDescriptor containingDeclaration, @NotNull PsiTypeParameter psiTypeParameter) {
|
||||
TypeParameterDescriptor typeParameterDescriptor = TypeParameterDescriptor.createForFurtherModification(
|
||||
TypeParameterDescriptorImpl typeParameterDescriptor = TypeParameterDescriptorImpl.createForFurtherModification(
|
||||
containingDeclaration,
|
||||
Collections.<AnnotationDescriptor>emptyList(), // TODO
|
||||
false,
|
||||
@@ -769,7 +774,7 @@ public class JavaDescriptorResolver {
|
||||
}
|
||||
|
||||
private void initializeTypeParameter(TypeParameterDescriptorInitialization typeParameter, TypeVariableResolver typeVariableByPsiResolver) {
|
||||
TypeParameterDescriptor typeParameterDescriptor = typeParameter.descriptor;
|
||||
TypeParameterDescriptorImpl typeParameterDescriptor = typeParameter.descriptor;
|
||||
if (typeParameter.origin == TypeParameterDescriptorOrigin.KOTLIN) {
|
||||
List<?> upperBounds = typeParameter.upperBoundsForKotlin;
|
||||
if (upperBounds.size() == 0){
|
||||
@@ -947,6 +952,11 @@ public class JavaDescriptorResolver {
|
||||
return scopeData.namespaceDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NamespaceDescriptor resolveNamespace(@NotNull FqName qualifiedName) {
|
||||
return resolveNamespace(qualifiedName, DescriptorSearchRule.ERROR_IF_FOUND_IN_KOTLIN);
|
||||
}
|
||||
|
||||
private NamespaceDescriptorParent resolveParentNamespace(FqName fqName) {
|
||||
if (fqName.isRoot()) {
|
||||
return FAKE_ROOT_MODULE;
|
||||
|
||||
-1
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.jet.lang.resolve.java;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassOrNamespaceDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||
|
||||
+1
-6
@@ -17,12 +17,7 @@
|
||||
package org.jetbrains.jet.lang.resolve.java;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
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 org.jetbrains.jet.lang.descriptors.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -20,7 +20,6 @@ import com.google.common.base.Predicate;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiFile;
|
||||
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.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.BodiesResolveContext;
|
||||
@@ -35,13 +34,11 @@ public interface AnalyzerFacade {
|
||||
@NotNull
|
||||
AnalyzeExhaust analyzeFiles(@NotNull Project project,
|
||||
@NotNull Collection<JetFile> files,
|
||||
@NotNull Predicate<PsiFile> filesToAnalyzeCompletely,
|
||||
@NotNull JetControlFlowDataTraceFactory flowDataTraceFactory);
|
||||
@NotNull Predicate<PsiFile> filesToAnalyzeCompletely);
|
||||
|
||||
@NotNull
|
||||
AnalyzeExhaust analyzeBodiesInFiles(@NotNull Project project,
|
||||
@NotNull Predicate<PsiFile> filesForBodiesResolve,
|
||||
@NotNull JetControlFlowDataTraceFactory flowDataTraceFactory,
|
||||
@NotNull BindingTrace traceContext,
|
||||
@NotNull BodiesResolveContext bodiesResolveContext);
|
||||
}
|
||||
|
||||
@@ -17,16 +17,36 @@
|
||||
|
||||
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 org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.ModuleConfiguration;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||
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.*;
|
||||
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.OverloadingConflictResolver;
|
||||
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;
|
||||
|
||||
/* 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 ObservableBindingTrace observableBindingTrace;
|
||||
private final ModuleDescriptor moduleDescriptor;
|
||||
private final JetControlFlowDataTraceFactory jetControlFlowDataTraceFactory;
|
||||
private final ModuleConfiguration moduleConfiguration;
|
||||
private DeclarationResolver declarationResolver;
|
||||
private AnnotationResolver annotationResolver;
|
||||
@@ -63,7 +82,6 @@ public class InjectorForTopDownAnalyzerBasic {
|
||||
@NotNull TopDownAnalysisParameters topDownAnalysisParameters,
|
||||
@NotNull ObservableBindingTrace observableBindingTrace,
|
||||
@NotNull ModuleDescriptor moduleDescriptor,
|
||||
JetControlFlowDataTraceFactory jetControlFlowDataTraceFactory,
|
||||
@NotNull ModuleConfiguration moduleConfiguration
|
||||
) {
|
||||
this.topDownAnalyzer = new TopDownAnalyzer();
|
||||
@@ -76,7 +94,6 @@ public class InjectorForTopDownAnalyzerBasic {
|
||||
this.topDownAnalysisParameters = topDownAnalysisParameters;
|
||||
this.observableBindingTrace = observableBindingTrace;
|
||||
this.moduleDescriptor = moduleDescriptor;
|
||||
this.jetControlFlowDataTraceFactory = jetControlFlowDataTraceFactory;
|
||||
this.moduleConfiguration = moduleConfiguration;
|
||||
this.declarationResolver = new DeclarationResolver();
|
||||
this.annotationResolver = new AnnotationResolver();
|
||||
@@ -114,7 +131,6 @@ public class InjectorForTopDownAnalyzerBasic {
|
||||
this.bodyResolver.setTopDownAnalysisParameters(topDownAnalysisParameters);
|
||||
this.bodyResolver.setTrace(observableBindingTrace);
|
||||
|
||||
this.controlFlowAnalyzer.setFlowDataTraceFactory(jetControlFlowDataTraceFactory);
|
||||
this.controlFlowAnalyzer.setTopDownAnalysisParameters(topDownAnalysisParameters);
|
||||
this.controlFlowAnalyzer.setTrace(observableBindingTrace);
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.cfg;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
|
||||
import java.util.List;
|
||||
@@ -64,7 +65,7 @@ public interface JetControlFlowBuilder {
|
||||
// Subroutines
|
||||
void enterSubroutine(@NotNull JetDeclaration subroutine);
|
||||
|
||||
void exitSubroutine(@NotNull JetDeclaration subroutine);
|
||||
Pseudocode exitSubroutine(@NotNull JetDeclaration subroutine);
|
||||
|
||||
@NotNull
|
||||
JetElement getCurrentSubroutine();
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.cfg;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
|
||||
import java.util.List;
|
||||
@@ -157,9 +158,9 @@ public class JetControlFlowBuilderAdapter implements JetControlFlowBuilder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitSubroutine(@NotNull JetDeclaration subroutine) {
|
||||
public Pseudocode exitSubroutine(@NotNull JetDeclaration subroutine) {
|
||||
assert builder != null;
|
||||
builder.exitSubroutine(subroutine);
|
||||
return builder.exitSubroutine(subroutine);
|
||||
}
|
||||
|
||||
@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 org.jetbrains.annotations.NotNull;
|
||||
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.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||
@@ -45,12 +49,21 @@ public class JetControlFlowProcessor {
|
||||
private final JetControlFlowBuilder builder;
|
||||
private final BindingTrace trace;
|
||||
|
||||
public JetControlFlowProcessor(BindingTrace trace, JetControlFlowBuilder builder) {
|
||||
this.builder = builder;
|
||||
public JetControlFlowProcessor(BindingTrace trace) {
|
||||
this.builder = new JetControlFlowInstructionsGenerator();
|
||||
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);
|
||||
if (subroutine instanceof JetDeclarationWithBody) {
|
||||
JetDeclarationWithBody declarationWithBody = (JetDeclarationWithBody) subroutine;
|
||||
@@ -67,7 +80,7 @@ public class JetControlFlowProcessor {
|
||||
else {
|
||||
subroutine.accept(new CFPVisitor(false));
|
||||
}
|
||||
builder.exitSubroutine(subroutine);
|
||||
return builder.exitSubroutine(subroutine);
|
||||
}
|
||||
|
||||
private void processLocalDeclaration(@NotNull JetDeclaration subroutine) {
|
||||
|
||||
+117
-434
@@ -17,15 +17,16 @@
|
||||
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 com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
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.diagnostics.Errors;
|
||||
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.BindingTrace;
|
||||
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.lang.JetStandardClasses;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.jetbrains.jet.plugin.JetMainDetector;
|
||||
|
||||
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.resolve.BindingContext.CAPTURED_IN_CLOSURE;
|
||||
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 {
|
||||
|
||||
private final Map<JetElement, Pseudocode> pseudocodeMap;
|
||||
private final JetDeclaration subroutine;
|
||||
private final Pseudocode pseudocode;
|
||||
private final PseudocodeVariablesData pseudocodeVariablesData;
|
||||
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;
|
||||
final JetPseudocodeTrace pseudocodeTrace = flowDataTraceFactory.createTrace(declaration);
|
||||
pseudocodeMap = new HashMap<JetElement, Pseudocode>();
|
||||
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();
|
||||
pseudocode = new JetControlFlowProcessor(trace).generatePseudocode(declaration);
|
||||
pseudocodeVariablesData = new PseudocodeVariablesData(pseudocode, trace.getBindingContext());
|
||||
}
|
||||
|
||||
private void collectReturnExpressions(@NotNull JetElement subroutine, @NotNull final Collection<JetElement> returnedExpressions) {
|
||||
Pseudocode pseudocode = pseudocodeMap.get(subroutine);
|
||||
assert pseudocode != null;
|
||||
|
||||
private void collectReturnExpressions(@NotNull final Collection<JetElement> returnedExpressions) {
|
||||
final Set<Instruction> instructions = Sets.newHashSet(pseudocode.getInstructions());
|
||||
SubroutineExitInstruction exitInstruction = pseudocode.getExitInstruction();
|
||||
for (Instruction previousInstruction : exitInstruction.getPreviousInstructions()) {
|
||||
@@ -148,15 +120,16 @@ public class JetFlowInformationProvider {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void checkDefiniteReturn(@NotNull final JetDeclarationWithBody function, final @NotNull JetType expectedReturnType) {
|
||||
assert function instanceof JetDeclaration;
|
||||
|
||||
public void checkDefiniteReturn(final @NotNull JetType expectedReturnType) {
|
||||
assert subroutine instanceof JetDeclarationWithBody;
|
||||
JetDeclarationWithBody function = (JetDeclarationWithBody) subroutine;
|
||||
|
||||
JetExpression bodyExpression = function.getBodyExpression();
|
||||
if (bodyExpression == null) return;
|
||||
|
||||
|
||||
List<JetElement> returnedExpressions = Lists.newArrayList();
|
||||
collectReturnExpressions(function.asElement(), returnedExpressions);
|
||||
collectReturnExpressions(returnedExpressions);
|
||||
|
||||
boolean nothingReturned = returnedExpressions.isEmpty();
|
||||
|
||||
@@ -166,8 +139,8 @@ public class JetFlowInformationProvider {
|
||||
trace.report(RETURN_TYPE_MISMATCH.on(bodyExpression, expectedReturnType));
|
||||
}
|
||||
final boolean blockBody = function.hasBlockBody();
|
||||
|
||||
final Set<JetElement> rootUnreachableElements = collectUnreachableCode(function.asElement());
|
||||
|
||||
final Set<JetElement> rootUnreachableElements = collectUnreachableCode();
|
||||
for (JetElement element : rootUnreachableElements) {
|
||||
trace.report(UNREACHABLE_CODE.on(element));
|
||||
}
|
||||
@@ -195,10 +168,7 @@ public class JetFlowInformationProvider {
|
||||
}
|
||||
}
|
||||
|
||||
private Set<JetElement> collectUnreachableCode(@NotNull JetElement subroutine) {
|
||||
Pseudocode pseudocode = pseudocodeMap.get(subroutine);
|
||||
assert pseudocode != null;
|
||||
|
||||
private Set<JetElement> collectUnreachableCode() {
|
||||
Collection<JetElement> unreachableElements = Lists.newArrayList();
|
||||
for (Instruction deadInstruction : pseudocode.getDeadInstructions()) {
|
||||
if (deadInstruction instanceof JetElementInstruction &&
|
||||
@@ -213,73 +183,61 @@ public class JetFlowInformationProvider {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Uninitialized variables analysis
|
||||
|
||||
public void markUninitializedVariables(@NotNull JetElement subroutine, 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);
|
||||
}
|
||||
});
|
||||
|
||||
public void markUninitializedVariables(final boolean processLocalDeclaration) {
|
||||
final Collection<VariableDescriptor> varWithUninitializedErrorGenerated = Sets.newHashSet();
|
||||
final Collection<VariableDescriptor> varWithValReassignErrorGenerated = Sets.newHashSet();
|
||||
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
|
||||
public void execute(@NotNull Instruction instruction, @Nullable Map<VariableDescriptor, VariableInitializers> enterData, @Nullable Map<VariableDescriptor, VariableInitializers> exitData) {
|
||||
assert enterData != null && exitData != null;
|
||||
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, true);
|
||||
public void execute(@NotNull Instruction instruction,
|
||||
@Nullable Map<VariableDescriptor, VariableInitState> in,
|
||||
@Nullable Map<VariableDescriptor, PseudocodeVariablesData.VariableInitState> out) {
|
||||
assert in != null && out != null;
|
||||
VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, true, trace.getBindingContext());
|
||||
if (variableDescriptor == null) return;
|
||||
if (!(instruction instanceof ReadValueInstruction) && !(instruction instanceof WriteValueInstruction)) return;
|
||||
VariableInitState outInitState = out.get(variableDescriptor);
|
||||
if (instruction instanceof ReadValueInstruction) {
|
||||
JetElement element = ((ReadValueInstruction) instruction).getElement();
|
||||
boolean error = checkBackingField(variableDescriptor, element);
|
||||
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();
|
||||
boolean error = checkBackingField(variableDescriptor, element);
|
||||
if (!(element instanceof JetExpression)) return;
|
||||
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);
|
||||
}
|
||||
if (!error && processClassOrObject) {
|
||||
error = checkAssignmentBeforeDeclaration(variableDescriptor, (JetExpression) element, enterData.get(variableDescriptor), exitData.get(variableDescriptor));
|
||||
}
|
||||
if (!error && processClassOrObject) {
|
||||
checkInitializationUsingBackingField(variableDescriptor, (JetExpression) element, enterData.get(variableDescriptor), exitData.get(variableDescriptor));
|
||||
}
|
||||
JetElement element = ((WriteValueInstruction) instruction).getlValue();
|
||||
boolean error = checkBackingField(variableDescriptor, element);
|
||||
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
|
||||
error = checkValReassignment(variableDescriptor, (JetExpression) element, inInitState, varWithValReassignErrorGenerated);
|
||||
}
|
||||
if (!error && processClassOrObject) {
|
||||
error = checkAssignmentBeforeDeclaration(variableDescriptor, (JetExpression) element, inInitState, outInitState);
|
||||
}
|
||||
if (!error && processClassOrObject) {
|
||||
checkInitializationUsingBackingField(variableDescriptor, (JetExpression) element, inInitState, outInitState);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
recordInitializedVariables(declaredVariables, traverser.getResultInfo());
|
||||
analyzeLocalDeclarations(pseudocode, processLocalDeclaration);
|
||||
Pseudocode pseudocode = pseudocodeVariablesData.getPseudocode();
|
||||
recordInitializedVariables(pseudocode, initializers);
|
||||
for (LocalDeclarationInstruction instruction : pseudocode.getLocalDeclarations()) {
|
||||
recordInitializedVariables(instruction.getBody(), initializers);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkIsInitialized(@NotNull VariableDescriptor variableDescriptor,
|
||||
@NotNull JetElement element,
|
||||
@NotNull VariableInitializers variableInitializers,
|
||||
private void checkIsInitialized(@NotNull VariableDescriptor variableDescriptor,
|
||||
@NotNull JetElement element,
|
||||
@NotNull PseudocodeVariablesData.VariableInitState variableInitState,
|
||||
@NotNull Collection<VariableDescriptor> varWithUninitializedErrorGenerated) {
|
||||
if (!(element instanceof JetSimpleNameExpression)) return;
|
||||
|
||||
boolean isInitialized = variableInitializers.isInitialized();
|
||||
boolean isInitialized = variableInitState.isInitialized;
|
||||
if (variableDescriptor instanceof PropertyDescriptor) {
|
||||
if (!trace.get(BindingContext.BACKING_FIELD_REQUIRED, (PropertyDescriptor) variableDescriptor)) {
|
||||
isInitialized = true;
|
||||
@@ -288,7 +246,8 @@ public class JetFlowInformationProvider {
|
||||
if (!isInitialized && !varWithUninitializedErrorGenerated.contains(variableDescriptor)) {
|
||||
varWithUninitializedErrorGenerated.add(variableDescriptor);
|
||||
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 {
|
||||
trace.report(Errors.UNINITIALIZED_VARIABLE.on((JetSimpleNameExpression) element, variableDescriptor));
|
||||
@@ -296,17 +255,13 @@ public class JetFlowInformationProvider {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkValReassignment(@NotNull VariableDescriptor variableDescriptor,
|
||||
@NotNull JetExpression expression,
|
||||
@NotNull VariableInitializers enterInitializers,
|
||||
private boolean checkValReassignment(@NotNull VariableDescriptor variableDescriptor,
|
||||
@NotNull JetExpression expression,
|
||||
@NotNull VariableInitState enterInitState,
|
||||
@NotNull Collection<VariableDescriptor> varWithValReassignErrorGenerated) {
|
||||
boolean isInitializedNotHere = enterInitializers.isInitialized();
|
||||
Set<JetElement> possibleLocalInitializers = enterInitializers.getPossibleLocalInitializers();
|
||||
if (possibleLocalInitializers.size() == 1) {
|
||||
JetElement initializer = possibleLocalInitializers.iterator().next();
|
||||
if (initializer instanceof JetProperty && initializer == expression.getParent()) {
|
||||
isInitializedNotHere = false;
|
||||
}
|
||||
boolean isInitializedNotHere = enterInitState.isInitialized;
|
||||
if (expression.getParent() instanceof JetProperty && ((JetProperty)expression).getInitializer() != null) {
|
||||
isInitializedNotHere = false;
|
||||
}
|
||||
boolean hasBackingField = true;
|
||||
if (variableDescriptor instanceof PropertyDescriptor) {
|
||||
@@ -348,17 +303,17 @@ public class JetFlowInformationProvider {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean checkAssignmentBeforeDeclaration(@NotNull VariableDescriptor variableDescriptor, @NotNull JetExpression expression, @NotNull VariableInitializers enterInitializers, @NotNull VariableInitializers exitInitializers) {
|
||||
if (!enterInitializers.isDeclared() && !exitInitializers.isDeclared() && !enterInitializers.isInitialized() && exitInitializers.isInitialized()) {
|
||||
|
||||
private boolean checkAssignmentBeforeDeclaration(@NotNull VariableDescriptor variableDescriptor, @NotNull JetExpression expression, @NotNull VariableInitState enterInitState, @NotNull VariableInitState exitInitState) {
|
||||
if (!enterInitState.isDeclared && !exitInitState.isDeclared && !enterInitState.isInitialized && exitInitState.isInitialized) {
|
||||
trace.report(Errors.INITIALIZATION_BEFORE_DECLARATION.on(expression, variableDescriptor));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean checkInitializationUsingBackingField(@NotNull VariableDescriptor variableDescriptor, @NotNull JetExpression expression, @NotNull VariableInitializers enterInitializers, @NotNull VariableInitializers exitInitializers) {
|
||||
if (variableDescriptor instanceof PropertyDescriptor && !enterInitializers.isInitialized() && exitInitializers.isInitialized()) {
|
||||
|
||||
private boolean checkInitializationUsingBackingField(@NotNull VariableDescriptor variableDescriptor, @NotNull JetExpression expression, @NotNull VariableInitState enterInitState, @NotNull VariableInitState exitInitState) {
|
||||
if (variableDescriptor instanceof PropertyDescriptor && !enterInitState.isInitialized && exitInitState.isInitialized) {
|
||||
if (!variableDescriptor.isVar()) return false;
|
||||
if (!trace.get(BindingContext.BACKING_FIELD_REQUIRED, (PropertyDescriptor) variableDescriptor)) return false;
|
||||
PsiElement property = BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), variableDescriptor);
|
||||
@@ -397,7 +352,9 @@ public class JetFlowInformationProvider {
|
||||
}
|
||||
PsiElement property = BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), variableDescriptor);
|
||||
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) {
|
||||
trace.report(NO_BACKING_FIELD_ABSTRACT_PROPERTY.on(element));
|
||||
}
|
||||
@@ -436,173 +393,44 @@ public class JetFlowInformationProvider {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void recordInitializedVariables(Collection<VariableDescriptor> declaredVariables, Map<VariableDescriptor, VariableInitializers> resultInfo) {
|
||||
for (Map.Entry<VariableDescriptor, VariableInitializers> entry : resultInfo.entrySet()) {
|
||||
VariableDescriptor variable = entry.getKey();
|
||||
if (variable instanceof PropertyDescriptor && declaredVariables.contains(variable)) {
|
||||
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);
|
||||
|
||||
private void recordInitializedVariables(@NotNull Pseudocode pseudocode, @NotNull Map<Instruction, Edges<Map<VariableDescriptor,PseudocodeVariablesData.VariableInitState>>> initializersMap) {
|
||||
Edges<Map<VariableDescriptor, VariableInitState>> initializers = initializersMap.get(pseudocode.getExitInstruction());
|
||||
Set<VariableDescriptor> usedVariables = pseudocodeVariablesData.getUsedVariables(pseudocode);
|
||||
Set<VariableDescriptor> declaredVariables = pseudocodeVariablesData.getDeclaredVariables(pseudocode);
|
||||
for (VariableDescriptor variable : usedVariables) {
|
||||
if (declaredVariables.contains(variable)) {
|
||||
initialMapForStartInstruction.put(variable, isNotInitializedForDeclaredVariable);
|
||||
}
|
||||
else {
|
||||
initialMapForStartInstruction.put(variable, isInitializedForExternalVariable);
|
||||
if (variable instanceof PropertyDescriptor && declaredVariables.contains(variable)) {
|
||||
PseudocodeVariablesData.VariableInitState variableInitState = initializers.in.get(variable);
|
||||
if (variableInitState == null) return;
|
||||
trace.record(BindingContext.IS_INITIALIZED, (PropertyDescriptor) variable, variableInitState.isInitialized);
|
||||
}
|
||||
}
|
||||
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
|
||||
|
||||
public void markUnusedVariables(@NotNull JetElement subroutine) {
|
||||
Pseudocode pseudocode = pseudocodeMap.get(subroutine);
|
||||
assert pseudocode != null;
|
||||
JetControlFlowGraphTraverser<Map<VariableDescriptor, VariableStatus>> traverser = JetControlFlowGraphTraverser.create(pseudocode, true, false);
|
||||
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>>() {
|
||||
public void markUnusedVariables() {
|
||||
Map<Instruction, Edges<Map<VariableDescriptor, VariableUseState>>> variableStatusData = pseudocodeVariablesData.getVariableUseStatusData();
|
||||
InstructionDataAnalyzeStrategy<Map<VariableDescriptor, VariableUseState>> variableStatusAnalyzeStrategy =
|
||||
new InstructionDataAnalyzeStrategy<Map<VariableDescriptor, PseudocodeVariablesData.VariableUseState>>() {
|
||||
@Override
|
||||
public Pair<Map<VariableDescriptor, VariableStatus>, Map<VariableDescriptor, VariableStatus>> execute(@NotNull Instruction instruction, @NotNull Collection<Map<VariableDescriptor, VariableStatus>> incomingEdgesData) {
|
||||
Map<VariableDescriptor, VariableStatus> enterResult = Maps.newHashMap();
|
||||
for (Map<VariableDescriptor, VariableStatus> edgeData : incomingEdgesData) {
|
||||
for (Map.Entry<VariableDescriptor, VariableStatus> entry : edgeData.entrySet()) {
|
||||
VariableDescriptor variableDescriptor = entry.getKey();
|
||||
VariableStatus variableStatus = entry.getValue();
|
||||
enterResult.put(variableDescriptor, variableStatus.merge(enterResult.get(variableDescriptor)));
|
||||
}
|
||||
}
|
||||
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);
|
||||
public void execute(@NotNull Instruction instruction,
|
||||
@Nullable Map<VariableDescriptor, PseudocodeVariablesData.VariableUseState> in,
|
||||
@Nullable Map<VariableDescriptor, VariableUseState> out) {
|
||||
|
||||
assert in != null && out != null;
|
||||
Set<VariableDescriptor> declaredVariables = pseudocodeVariablesData.getDeclaredVariables(instruction.getOwner());
|
||||
VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, false,
|
||||
trace.getBindingContext());
|
||||
if (variableDescriptor == null || !declaredVariables.contains(variableDescriptor) ||
|
||||
!DescriptorUtils.isLocal(variableDescriptor.getContainingDeclaration(), variableDescriptor)) return;
|
||||
VariableStatus variableStatus = enterData.get(variableDescriptor);
|
||||
PseudocodeVariablesData.VariableUseState variableUseState = in.get(variableDescriptor);
|
||||
if (instruction instanceof WriteValueInstruction) {
|
||||
if (trace.get(CAPTURED_IN_CLOSURE, variableDescriptor)) return;
|
||||
JetElement element = ((WriteValueInstruction) instruction).getElement();
|
||||
if (variableStatus != VariableStatus.READ) {
|
||||
if (element instanceof JetBinaryExpression && ((JetBinaryExpression) element).getOperationToken() == JetTokens.EQ) {
|
||||
if (variableUseState != LAST_READ) {
|
||||
if (element instanceof JetBinaryExpression &&
|
||||
((JetBinaryExpression) element).getOperationToken() == JetTokens.EQ) {
|
||||
JetExpression right = ((JetBinaryExpression) element).getRight();
|
||||
if (right != null) {
|
||||
trace.report(Errors.UNUSED_VALUE.on(right, right, variableDescriptor));
|
||||
@@ -621,7 +449,7 @@ public class JetFlowInformationProvider {
|
||||
if (element instanceof JetNamedDeclaration) {
|
||||
PsiElement nameIdentifier = ((JetNamedDeclaration) element).getNameIdentifier();
|
||||
if (nameIdentifier == null) return;
|
||||
if (variableStatus == null || variableStatus == VariableStatus.UNUSED) {
|
||||
if (!VariableUseState.isUsed(variableUseState)) {
|
||||
if (element instanceof JetProperty) {
|
||||
trace.report(Errors.UNUSED_VARIABLE.on((JetProperty) element, variableDescriptor));
|
||||
}
|
||||
@@ -629,8 +457,9 @@ public class JetFlowInformationProvider {
|
||||
PsiElement psiElement = element.getParent().getParent();
|
||||
if (psiElement instanceof JetFunction) {
|
||||
boolean isMain = (psiElement instanceof JetNamedFunction) && JetMainDetector.isMain((JetNamedFunction) psiElement);
|
||||
if (psiElement instanceof JetFunctionLiteral) return;
|
||||
DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, psiElement);
|
||||
assert descriptor instanceof FunctionDescriptor;
|
||||
assert descriptor instanceof FunctionDescriptor : psiElement.getText();
|
||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
|
||||
if (!isMain && !functionDescriptor.getModality().isOverridable() && functionDescriptor.getOverriddenDescriptors().isEmpty()) {
|
||||
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));
|
||||
}
|
||||
else if (variableStatus == VariableStatus.WRITTEN && element instanceof JetProperty) {
|
||||
else if (variableUseState == LAST_WRITTEN && element instanceof JetProperty) {
|
||||
JetExpression initializer = ((JetProperty) element).getInitializer();
|
||||
if (initializer != null) {
|
||||
trace.report(Errors.VARIABLE_WITH_REDUNDANT_INITIALIZER.on(initializer, variableDescriptor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
||||
PseudocodeTraverser.traverse(pseudocode, false, true, variableStatusData, variableStatusAnalyzeStrategy);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// "Unused literals" in block
|
||||
|
||||
public void markUnusedLiteralsInBlock(@NotNull JetElement subroutine) {
|
||||
Pseudocode pseudocode = pseudocodeMap.get(subroutine);
|
||||
|
||||
public void markUnusedLiteralsInBlock() {
|
||||
assert pseudocode != null;
|
||||
JetControlFlowGraphTraverser<Void> traverser = JetControlFlowGraphTraverser.create(pseudocode, true, true);
|
||||
traverser.traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy<Void>() {
|
||||
PseudocodeTraverser.traverse(
|
||||
pseudocode, true, new InstructionAnalyzeStrategy() {
|
||||
@Override
|
||||
public void execute(@NotNull Instruction instruction, @Nullable Void enterData, @Nullable Void exitData) {
|
||||
public void execute(@NotNull Instruction instruction) {
|
||||
if (!(instruction instanceof ReadValueInstruction)) return;
|
||||
JetElement element = ((ReadValueInstruction) instruction).getElement();
|
||||
JetElement element =
|
||||
((ReadValueInstruction) instruction).getElement();
|
||||
if (!(element instanceof JetFunctionLiteralExpression
|
||||
|| element instanceof JetConstantExpression
|
||||
|| element instanceof JetStringTemplateExpression
|
||||
@@ -694,7 +505,8 @@ public class JetFlowInformationProvider {
|
||||
if (parent instanceof JetBlockExpression) {
|
||||
if (!JetPsiUtil.isImplicitlyUsed(element)) {
|
||||
if (element instanceof JetFunctionLiteralExpression) {
|
||||
trace.report(Errors.UNUSED_FUNCTION_LITERAL.on((JetFunctionLiteralExpression) element));
|
||||
trace.report(Errors.UNUSED_FUNCTION_LITERAL
|
||||
.on((JetFunctionLiteralExpression) element));
|
||||
}
|
||||
else {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
-17
@@ -35,12 +35,6 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
||||
|
||||
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) {
|
||||
JetControlFlowInstructionsGeneratorWorker worker = new JetControlFlowInstructionsGeneratorWorker(scopingElement, subroutine);
|
||||
builders.push(worker);
|
||||
@@ -49,7 +43,6 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
||||
|
||||
private JetControlFlowInstructionsGeneratorWorker popBuilder(@NotNull JetElement element) {
|
||||
JetControlFlowInstructionsGeneratorWorker worker = builders.pop();
|
||||
trace.recordControlFlowData(element, worker.getPseudocode());
|
||||
if (!builders.isEmpty()) {
|
||||
builder = builders.peek();
|
||||
}
|
||||
@@ -72,7 +65,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitSubroutine(@NotNull JetDeclaration subroutine) {
|
||||
public Pseudocode exitSubroutine(@NotNull JetDeclaration subroutine) {
|
||||
super.exitSubroutine(subroutine);
|
||||
JetControlFlowInstructionsGeneratorWorker worker = popBuilder(subroutine);
|
||||
if (!builders.empty()) {
|
||||
@@ -80,32 +73,29 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
||||
LocalDeclarationInstruction instruction = new LocalDeclarationInstruction(subroutine, worker.getPseudocode());
|
||||
builder.add(instruction);
|
||||
}
|
||||
return worker.getPseudocode();
|
||||
}
|
||||
|
||||
private class JetControlFlowInstructionsGeneratorWorker implements JetControlFlowBuilder {
|
||||
|
||||
private final Pseudocode pseudocode;
|
||||
private final PseudocodeImpl pseudocode;
|
||||
private final Label error;
|
||||
private final Label sink;
|
||||
private final 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.sink = pseudocode.createLabel("sink");
|
||||
this.returnSubroutine = returnSubroutine;
|
||||
}
|
||||
|
||||
public Pseudocode getPseudocode() {
|
||||
public PseudocodeImpl getPseudocode() {
|
||||
return pseudocode;
|
||||
}
|
||||
|
||||
private void add(@NotNull Instruction instruction) {
|
||||
pseudocode.addInstruction(instruction);
|
||||
if (instruction instanceof JetElementInstruction) {
|
||||
JetElementInstruction elementInstruction = (JetElementInstruction) instruction;
|
||||
trace.recordRepresentativeInstruction(elementInstruction.getElement(), instruction);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -127,7 +117,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
||||
loopInfo.push(blockInfo);
|
||||
elementToBlockInfo.put(expression, blockInfo);
|
||||
allBlocks.push(blockInfo);
|
||||
trace.recordLoopInfo(expression, blockInfo);
|
||||
pseudocode.recordLoopInfo(expression, blockInfo);
|
||||
return blockInfo;
|
||||
}
|
||||
|
||||
@@ -202,7 +192,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitSubroutine(@NotNull JetDeclaration subroutine) {
|
||||
public Pseudocode exitSubroutine(@NotNull JetDeclaration subroutine) {
|
||||
bindLabel(getExitPoint(subroutine));
|
||||
pseudocode.addExitInstruction(new SubroutineExitInstruction(subroutine, "<END>"));
|
||||
bindLabel(error);
|
||||
@@ -211,6 +201,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
||||
pseudocode.addSinkInstruction(new SubroutineSinkInstruction(subroutine, "<SINK>"));
|
||||
elementToBlockInfo.remove(subroutine);
|
||||
allBlocks.pop();
|
||||
return null;
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
+7
@@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.cfg.pseudocode;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.psi.JetDeclaration;
|
||||
import org.jetbrains.jet.lang.psi.JetElement;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -40,6 +41,12 @@ public class LocalDeclarationInstruction extends InstructionWithNext {
|
||||
return body;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JetDeclaration getElement() {
|
||||
return (JetDeclaration) super.getElement();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<Instruction> getNextInstructions() {
|
||||
|
||||
@@ -16,343 +16,37 @@
|
||||
|
||||
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.Nullable;
|
||||
import org.jetbrains.jet.lang.cfg.Label;
|
||||
import org.jetbrains.jet.lang.psi.JetElement;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class 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> 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);
|
||||
}
|
||||
* @author svtk
|
||||
*/
|
||||
public interface Pseudocode {
|
||||
@NotNull
|
||||
JetElement getCorrespondingElement();
|
||||
|
||||
@NotNull
|
||||
public List<Instruction> getInstructions() {
|
||||
return instructions;
|
||||
}
|
||||
|
||||
@Deprecated //for tests only
|
||||
@NotNull
|
||||
public List<Instruction> getMutableInstructionList() {
|
||||
return mutableInstructionList;
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
Set<LocalDeclarationInstruction> getLocalDeclarations();
|
||||
|
||||
@NotNull
|
||||
public SubroutineExitInstruction getExitInstruction() {
|
||||
return exitInstruction;
|
||||
}
|
||||
List<Instruction> getInstructions();
|
||||
|
||||
@NotNull
|
||||
public SubroutineSinkInstruction getSinkInstruction() {
|
||||
return sinkInstruction;
|
||||
}
|
||||
|
||||
List<Instruction> getReversedInstructions();
|
||||
|
||||
@NotNull
|
||||
public SubroutineEnterInstruction getEnterInstruction() {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
List<Instruction> getDeadInstructions();
|
||||
|
||||
@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;
|
||||
}
|
||||
SubroutineExitInstruction getExitInstruction();
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
}
|
||||
SubroutineSinkInstruction getSinkInstruction();
|
||||
|
||||
@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);
|
||||
}
|
||||
SubroutineEnterInstruction getEnterInstruction();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
+2
-4
@@ -46,10 +46,8 @@ public class SubroutineExitInstruction extends InstructionImpl {
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<Instruction> getNextInstructions() {
|
||||
if (sinkInstruction != null) {
|
||||
return Collections.<Instruction>singleton(sinkInstruction);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
assert sinkInstruction != null;
|
||||
return Collections.<Instruction>singleton(sinkInstruction);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -48,7 +48,7 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl
|
||||
}
|
||||
|
||||
public final ClassDescriptorImpl initialize(boolean sealed,
|
||||
@NotNull List<TypeParameterDescriptor> typeParameters,
|
||||
@NotNull List<? extends TypeParameterDescriptor> typeParameters,
|
||||
@NotNull Collection<JetType> supertypes,
|
||||
@NotNull JetScope memberDeclarations,
|
||||
@NotNull Set<ConstructorDescriptor> constructors,
|
||||
@@ -57,7 +57,7 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl
|
||||
}
|
||||
|
||||
public final ClassDescriptorImpl initialize(boolean sealed,
|
||||
@NotNull List<TypeParameterDescriptor> typeParameters,
|
||||
@NotNull List<? extends TypeParameterDescriptor> typeParameters,
|
||||
@NotNull Collection<JetType> supertypes,
|
||||
@NotNull JetScope memberDeclarations,
|
||||
@NotNull Set<ConstructorDescriptor> constructors,
|
||||
|
||||
+2
-2
@@ -77,12 +77,12 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorImpl i
|
||||
protected FunctionDescriptorImpl initialize(
|
||||
@Nullable JetType receiverType,
|
||||
@NotNull ReceiverDescriptor expectedThisObject,
|
||||
@NotNull List<TypeParameterDescriptor> typeParameters,
|
||||
@NotNull List<? extends TypeParameterDescriptor> typeParameters,
|
||||
@NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters,
|
||||
@Nullable JetType unsubstitutedReturnType,
|
||||
@Nullable Modality modality,
|
||||
@NotNull Visibility visibility) {
|
||||
this.typeParameters = typeParameters;
|
||||
this.typeParameters = Lists.newArrayList(typeParameters);
|
||||
this.unsubstitutedValueParameters = unsubstitutedValueParameters;
|
||||
this.unsubstitutedReturnType = unsubstitutedReturnType;
|
||||
this.modality = modality;
|
||||
|
||||
+1
-1
@@ -126,7 +126,7 @@ public class FunctionDescriptorUtil {
|
||||
assert JetStandardClasses.isFunctionType(functionType);
|
||||
functionDescriptor.initialize(JetStandardClasses.getReceiverType(functionType),
|
||||
expectedThisObject,
|
||||
Collections.<TypeParameterDescriptor>emptyList(),
|
||||
Collections.<TypeParameterDescriptorImpl>emptyList(),
|
||||
JetStandardClasses.getValueParameters(functionDescriptor, functionType),
|
||||
JetStandardClasses.getReturnTypeFromFunctionType(functionType),
|
||||
modality,
|
||||
|
||||
@@ -112,17 +112,17 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
|
||||
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
|
||||
? NO_RECEIVER
|
||||
: new ExtensionReceiver(this, receiverType);
|
||||
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);
|
||||
|
||||
this.typeParameters = typeParameters;
|
||||
this.typeParameters = Lists.newArrayList(typeParameters);
|
||||
|
||||
this.receiver = receiver;
|
||||
this.expectedThisObject = expectedThisObject;
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ public class SimpleFunctionDescriptorImpl extends FunctionDescriptorImpl impleme
|
||||
public SimpleFunctionDescriptorImpl initialize(
|
||||
@Nullable JetType receiverType,
|
||||
@NotNull ReceiverDescriptor expectedThisObject,
|
||||
@NotNull List<TypeParameterDescriptor> typeParameters,
|
||||
@NotNull List<? extends TypeParameterDescriptor> typeParameters,
|
||||
@NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters,
|
||||
@Nullable JetType unsubstitutedReturnType,
|
||||
@Nullable Modality modality,
|
||||
|
||||
+16
-222
@@ -16,251 +16,45 @@
|
||||
|
||||
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 org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeConstructor;
|
||||
import org.jetbrains.jet.lang.types.TypeSubstitutor;
|
||||
import org.jetbrains.jet.lang.types.Variance;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class TypeParameterDescriptor extends DeclarationDescriptorImpl implements ClassifierDescriptor {
|
||||
public static TypeParameterDescriptor createWithDefaultBound(
|
||||
@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 interface TypeParameterDescriptor extends ClassifierDescriptor {
|
||||
boolean isReified();
|
||||
|
||||
public static TypeParameterDescriptor createForFurtherModification(
|
||||
@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());
|
||||
}
|
||||
}
|
||||
Variance getVariance();
|
||||
|
||||
@NotNull
|
||||
public Set<JetType> getUpperBounds() {
|
||||
checkInitialized();
|
||||
return upperBounds;
|
||||
}
|
||||
Set<JetType> getUpperBounds();
|
||||
|
||||
@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;
|
||||
}
|
||||
JetType getUpperBoundsAsType();
|
||||
|
||||
@NotNull
|
||||
public Set<JetType> getLowerBounds() {
|
||||
//checkInitialized();
|
||||
return Collections.singleton(JetStandardClasses.getNothingType());
|
||||
}
|
||||
Set<JetType> getLowerBounds();
|
||||
|
||||
@NotNull
|
||||
public JetType getLowerBoundsAsType() {
|
||||
checkInitialized();
|
||||
return JetStandardClasses.getNothingType();
|
||||
}
|
||||
|
||||
|
||||
JetType getLowerBoundsAsType();
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
TypeConstructor getTypeConstructor();
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
@Deprecated // Use the static method TypeParameterDescriptor.substitute()
|
||||
public TypeParameterDescriptor substitute(TypeSubstitutor substitutor) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
TypeParameterDescriptor substitute(TypeSubstitutor substitutor);
|
||||
|
||||
@Override
|
||||
public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
|
||||
checkInitialized();
|
||||
return visitor.visitTypeParameterDescriptor(this, data);
|
||||
}
|
||||
int getIndex();
|
||||
|
||||
@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?
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
TypeParameterDescriptor copy(@NotNull DeclarationDescriptor newOwner);
|
||||
}
|
||||
|
||||
+275
@@ -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;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.PsiErrorElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
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.DiagnosticHolder;
|
||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.jetbrains.jet.lang.resolve;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
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.PropertyDescriptor;
|
||||
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 {
|
||||
private TopDownAnalysisParameters topDownAnalysisParameters;
|
||||
private BindingTrace trace;
|
||||
private JetControlFlowDataTraceFactory flowDataTraceFactory;
|
||||
|
||||
@Inject
|
||||
public void setTopDownAnalysisParameters(TopDownAnalysisParameters topDownAnalysisParameters) {
|
||||
@@ -49,11 +47,6 @@ public class ControlFlowAnalyzer {
|
||||
this.trace = trace;
|
||||
}
|
||||
|
||||
@Inject
|
||||
public void setFlowDataTraceFactory(JetControlFlowDataTraceFactory flowDataTraceFactory) {
|
||||
this.flowDataTraceFactory = flowDataTraceFactory;
|
||||
}
|
||||
|
||||
public void process(@NotNull BodiesResolveContext bodiesResolveContext) {
|
||||
for (JetClass aClass : bodiesResolveContext.getClasses().keySet()) {
|
||||
if (!bodiesResolveContext.completeAnalysisNeeded(aClass)) continue;
|
||||
@@ -86,8 +79,8 @@ public class ControlFlowAnalyzer {
|
||||
|
||||
private void checkClassOrObject(JetClassOrObject klass) {
|
||||
// A pseudocode of class initialization corresponds to a class
|
||||
JetFlowInformationProvider flowInformationProvider = new JetFlowInformationProvider((JetDeclaration) klass, (JetExpression) klass, flowDataTraceFactory, trace);
|
||||
flowInformationProvider.markUninitializedVariables((JetElement) klass, topDownAnalysisParameters.isDeclaredLocally());
|
||||
JetFlowInformationProvider flowInformationProvider = new JetFlowInformationProvider((JetDeclaration) klass, trace);
|
||||
flowInformationProvider.markUninitializedVariables(topDownAnalysisParameters.isDeclaredLocally());
|
||||
}
|
||||
|
||||
private void checkProperty(JetProperty property, PropertyDescriptor propertyDescriptor) {
|
||||
@@ -105,16 +98,16 @@ public class ControlFlowAnalyzer {
|
||||
|
||||
JetExpression bodyExpression = function.getBodyExpression();
|
||||
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')
|
||||
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();
|
||||
int index = 0;
|
||||
for (JetTypeParameter typeParameter : classElement.getTypeParameters()) {
|
||||
TypeParameterDescriptor typeParameterDescriptor = TypeParameterDescriptor.createForFurtherModification(
|
||||
TypeParameterDescriptor typeParameterDescriptor = TypeParameterDescriptorImpl.createForFurtherModification(
|
||||
descriptor,
|
||||
annotationResolver.createAnnotationStubs(typeParameter.getModifierList(), trace),
|
||||
!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");
|
||||
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);
|
||||
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) {
|
||||
List<TypeParameterDescriptor> result = new ArrayList<TypeParameterDescriptor>();
|
||||
public List<TypeParameterDescriptorImpl> resolveTypeParameters(DeclarationDescriptor containingDescriptor, WritableScope extensibleScope, List<JetTypeParameter> typeParameters, BindingTrace trace) {
|
||||
List<TypeParameterDescriptorImpl> result = new ArrayList<TypeParameterDescriptorImpl>();
|
||||
for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) {
|
||||
JetTypeParameter typeParameter = typeParameters.get(i);
|
||||
result.add(resolveTypeParameter(containingDescriptor, extensibleScope, typeParameter, i, trace));
|
||||
@@ -316,12 +316,12 @@ public class DescriptorResolver {
|
||||
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();
|
||||
// JetType bound = extendsBound == null
|
||||
// ? JetStandardClasses.getDefaultBound()
|
||||
// : typeResolver.resolveType(extensibleScope, extendsBound);
|
||||
TypeParameterDescriptor typeParameterDescriptor = TypeParameterDescriptor.createForFurtherModification(
|
||||
TypeParameterDescriptorImpl typeParameterDescriptor = TypeParameterDescriptorImpl.createForFurtherModification(
|
||||
containingDescriptor,
|
||||
annotationResolver.createAnnotationStubs(typeParameter.getModifierList(), trace),
|
||||
!typeParameter.hasModifier(JetTokens.ERASED_KEYWORD),
|
||||
@@ -346,14 +346,15 @@ public class DescriptorResolver {
|
||||
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<JetTypeParameter> typeParameters = declaration.getTypeParameters();
|
||||
Map<Name, TypeParameterDescriptor> parameterByName = Maps.newHashMap();
|
||||
Map<Name, TypeParameterDescriptorImpl> parameterByName = Maps.newHashMap();
|
||||
for (int i = 0; i < typeParameters.size(); i++) {
|
||||
JetTypeParameter jetTypeParameter = typeParameters.get(i);
|
||||
TypeParameterDescriptor typeParameterDescriptor = parameters.get(i);
|
||||
TypeParameterDescriptorImpl typeParameterDescriptor = parameters.get(i);
|
||||
|
||||
parameterByName.put(typeParameterDescriptor.getName(), typeParameterDescriptor);
|
||||
|
||||
@@ -373,7 +374,7 @@ public class DescriptorResolver {
|
||||
if (referencedName == null) {
|
||||
continue;
|
||||
}
|
||||
TypeParameterDescriptor typeParameterDescriptor = parameterByName.get(referencedName);
|
||||
TypeParameterDescriptorImpl typeParameterDescriptor = parameterByName.get(referencedName);
|
||||
JetTypeReference boundTypeReference = constraint.getBoundTypeReference();
|
||||
JetType bound = null;
|
||||
if (boundTypeReference != null) {
|
||||
@@ -405,7 +406,7 @@ public class DescriptorResolver {
|
||||
}
|
||||
}
|
||||
|
||||
for (TypeParameterDescriptor parameter : parameters) {
|
||||
for (TypeParameterDescriptorImpl parameter : parameters) {
|
||||
parameter.addDefaultUpperBound();
|
||||
|
||||
parameter.setInitialized();
|
||||
@@ -551,7 +552,7 @@ public class DescriptorResolver {
|
||||
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) {
|
||||
WritableScopeImpl result = new WritableScopeImpl(outerScope, outerScope.getContainingDeclaration(), new TraceBasedRedeclarationHandler(trace)).setDebugName("Property declaration inner scope");
|
||||
for (TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
|
||||
@@ -583,7 +584,7 @@ public class DescriptorResolver {
|
||||
CallableMemberDescriptor.Kind.DECLARATION
|
||||
);
|
||||
|
||||
List<TypeParameterDescriptor> typeParameterDescriptors;
|
||||
List<TypeParameterDescriptorImpl> typeParameterDescriptors;
|
||||
JetScope scopeWithTypeParameters;
|
||||
JetType receiverType = null;
|
||||
|
||||
|
||||
@@ -275,7 +275,7 @@ public class DescriptorUtils {
|
||||
ClassDescriptor clazz = (ClassDescriptor) classifier;
|
||||
return clazz.getKind() == ClassKind.OBJECT || clazz.getKind() == ClassKind.ENUM_ENTRY;
|
||||
}
|
||||
else if (classifier instanceof TypeParameterDescriptor) {
|
||||
else if (classifier instanceof TypeParameterDescriptorImpl) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -212,7 +212,7 @@ public class OverridingUtil {
|
||||
if (type.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) {
|
||||
return type;
|
||||
}
|
||||
else if (type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) {
|
||||
else if (type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptorImpl) {
|
||||
return ((TypeParameterDescriptor) type.getConstructor().getDeclarationDescriptor()).getUpperBoundsAsType();
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -23,7 +23,6 @@ import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.di.InjectorForTopDownAnalyzerBasic;
|
||||
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.psi.JetDeclaration;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
@@ -188,7 +187,7 @@ public class TopDownAnalyzer {
|
||||
TopDownAnalysisParameters topDownAnalysisParameters = new TopDownAnalysisParameters(Predicates.<PsiFile>alwaysFalse(), true, false);
|
||||
InjectorForTopDownAnalyzerBasic injector = new InjectorForTopDownAnalyzerBasic(
|
||||
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);
|
||||
}
|
||||
@@ -220,7 +219,7 @@ public class TopDownAnalyzer {
|
||||
|
||||
InjectorForTopDownAnalyzerBasic injector = new InjectorForTopDownAnalyzerBasic(
|
||||
project, topDownAnalysisParameters, new ObservableBindingTrace(trace), moduleDescriptor,
|
||||
JetControlFlowDataTraceFactory.EMPTY, ModuleConfiguration.EMPTY);
|
||||
ModuleConfiguration.EMPTY);
|
||||
|
||||
injector.getTopDownAnalyzer().doProcess(outerScope, new NamespaceLikeBuilder() {
|
||||
|
||||
|
||||
@@ -395,7 +395,7 @@ public class TypeHierarchyResolver {
|
||||
JetClass jetClass = entry.getKey();
|
||||
MutableClassDescriptor descriptor = entry.getValue();
|
||||
descriptorResolver.resolveGenericBounds(jetClass, descriptor.getScopeForSupertypeResolution(),
|
||||
descriptor.getTypeConstructor().getParameters(), trace);
|
||||
(List) descriptor.getTypeConstructor().getParameters(), trace);
|
||||
descriptorResolver.resolveSupertypes(jetClass, descriptor, trace);
|
||||
}
|
||||
for (Map.Entry<JetObjectDeclaration, MutableClassDescriptor> entry : context.getObjects().entrySet()) {
|
||||
@@ -528,7 +528,7 @@ public class TypeHierarchyResolver {
|
||||
if (projections.size() > 1) {
|
||||
TypeConstructor typeConstructor = entry.getKey();
|
||||
DeclarationDescriptor declarationDescriptor = typeConstructor.getDeclarationDescriptor();
|
||||
assert declarationDescriptor instanceof TypeParameterDescriptor : declarationDescriptor;
|
||||
assert declarationDescriptor instanceof TypeParameterDescriptorImpl : declarationDescriptor;
|
||||
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) declarationDescriptor;
|
||||
|
||||
// Immediate arguments of supertypes cannot be projected
|
||||
|
||||
@@ -95,7 +95,7 @@ public class TypeResolver {
|
||||
return;
|
||||
}
|
||||
|
||||
if (classifierDescriptor instanceof TypeParameterDescriptor) {
|
||||
if (classifierDescriptor instanceof TypeParameterDescriptorImpl) {
|
||||
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) classifierDescriptor;
|
||||
|
||||
trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, typeParameterDescriptor);
|
||||
|
||||
+3
-2
@@ -21,6 +21,7 @@ import com.google.common.collect.Sets;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
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.checker.JetTypeChecker;
|
||||
import org.jetbrains.jet.lang.types.checker.TypeCheckingProcedure;
|
||||
@@ -88,7 +89,7 @@ public class ConstraintSystemWithPriorities implements ConstraintSystem {
|
||||
@NotNull
|
||||
private TypeValue getTypeValueFor(@NotNull JetType type) {
|
||||
DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor();
|
||||
if (declarationDescriptor instanceof TypeParameterDescriptor) {
|
||||
if (declarationDescriptor instanceof TypeParameterDescriptorImpl) {
|
||||
TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) declarationDescriptor;
|
||||
// Checking that this is not a T?, but exactly T
|
||||
if (typeParameterDescriptor.getDefaultType().isNullable() == type.isNullable()) {
|
||||
@@ -488,7 +489,7 @@ public class ConstraintSystemWithPriorities implements ConstraintSystem {
|
||||
@Override
|
||||
public TypeProjection get(TypeConstructor key) {
|
||||
DeclarationDescriptor declarationDescriptor = key.getDeclarationDescriptor();
|
||||
if (declarationDescriptor instanceof TypeParameterDescriptor) {
|
||||
if (declarationDescriptor instanceof TypeParameterDescriptorImpl) {
|
||||
TypeParameterDescriptor descriptor = (TypeParameterDescriptor) declarationDescriptor;
|
||||
|
||||
if (!unknownTypes.containsKey(descriptor)) return null;
|
||||
|
||||
+12
-13
@@ -14,23 +14,22 @@
|
||||
* 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.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 {
|
||||
JetControlFlowDataTraceFactory EMPTY = new JetControlFlowDataTraceFactory() {
|
||||
@NotNull
|
||||
@Override
|
||||
public JetPseudocodeTrace createTrace(JetElement element) {
|
||||
return JetPseudocodeTrace.EMPTY;
|
||||
}
|
||||
};
|
||||
public interface DependencyClassByQualifiedNameResolver {
|
||||
|
||||
@Nullable
|
||||
ClassDescriptor resolveClass(@NotNull FqName qualifiedName);
|
||||
@Nullable
|
||||
NamespaceDescriptor resolveNamespace(@NotNull FqName qualifiedName);
|
||||
|
||||
@NotNull
|
||||
JetPseudocodeTrace createTrace(JetElement element);
|
||||
}
|
||||
+37
@@ -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.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptorImpl;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -58,7 +59,7 @@ public class DescriptorSubstitutor {
|
||||
});
|
||||
|
||||
for (TypeParameterDescriptor descriptor : typeParameters) {
|
||||
TypeParameterDescriptor substituted = TypeParameterDescriptor.createForFurtherModification(
|
||||
TypeParameterDescriptorImpl substituted = TypeParameterDescriptorImpl.createForFurtherModification(
|
||||
newContainingDeclaration,
|
||||
descriptor.getAnnotations(),
|
||||
descriptor.isReified(),
|
||||
|
||||
@@ -170,7 +170,7 @@ public class ErrorUtils {
|
||||
function.initialize(
|
||||
null,
|
||||
ReceiverDescriptor.NO_RECEIVER,
|
||||
Collections.<TypeParameterDescriptor>emptyList(), // TODO
|
||||
Collections.<TypeParameterDescriptorImpl>emptyList(), // TODO
|
||||
Collections.<ValueParameterDescriptor>emptyList(), // TODO
|
||||
createErrorType("<ERROR FUNCTION RETURN TYPE>"),
|
||||
Modality.OPEN,
|
||||
@@ -223,7 +223,7 @@ public class ErrorUtils {
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.google.common.collect.Multimap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
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.util.CommonSuppliers;
|
||||
|
||||
@@ -95,6 +96,9 @@ public class SubstitutionUtils {
|
||||
}
|
||||
|
||||
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++) {
|
||||
TypeParameterDescriptor parameter = parameters.get(i);
|
||||
TypeProjection value = contextArguments.get(i);
|
||||
@@ -108,7 +112,7 @@ public class SubstitutionUtils {
|
||||
}
|
||||
|
||||
public static boolean hasUnsubstitutedTypeParameters(JetType type) {
|
||||
if (type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) {
|
||||
if (type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptorImpl) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ public class TypeConstructorImpl extends AnnotatedImpl implements TypeConstructo
|
||||
@NotNull List<AnnotationDescriptor> annotations,
|
||||
boolean sealed,
|
||||
@NotNull String debugName,
|
||||
@NotNull List<TypeParameterDescriptor> parameters,
|
||||
@NotNull List<? extends TypeParameterDescriptor> parameters,
|
||||
@NotNull Collection<JetType> supertypes) {
|
||||
super(annotations);
|
||||
this.classifierDescriptor = classifierDescriptor;
|
||||
|
||||
@@ -22,10 +22,7 @@ import com.google.common.collect.Sets;
|
||||
import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
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.*;
|
||||
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.ConstraintSystemSolution;
|
||||
@@ -222,7 +219,7 @@ public class TypeUtils {
|
||||
|
||||
private static void processAllTypeParameters(JetType type, Variance howThiTypeIsUsed, Processor<TypeParameterUsage> result) {
|
||||
ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
|
||||
if (descriptor instanceof TypeParameterDescriptor) {
|
||||
if (descriptor instanceof TypeParameterDescriptorImpl) {
|
||||
result.process(new TypeParameterUsage((TypeParameterDescriptor)descriptor, howThiTypeIsUsed));
|
||||
}
|
||||
for (TypeProjection projection : type.getArguments()) {
|
||||
|
||||
+1
-1
@@ -149,7 +149,7 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
functionDescriptor.initialize(effectiveReceiverType,
|
||||
NO_RECEIVER,
|
||||
Collections.<TypeParameterDescriptor>emptyList(),
|
||||
Collections.<TypeParameterDescriptorImpl>emptyList(),
|
||||
valueParameterDescriptors,
|
||||
/*unsubstitutedReturnType = */ null,
|
||||
Modality.FINAL,
|
||||
|
||||
@@ -157,13 +157,13 @@ public class JetStandardClasses {
|
||||
Name.identifier("Tuple" + i));
|
||||
WritableScopeImpl writableScope = new WritableScopeImpl(JetScope.EMPTY, classDescriptor, RedeclarationHandler.THROW_EXCEPTION);
|
||||
for (int j = 0; j < i; j++) {
|
||||
TypeParameterDescriptor typeParameterDescriptor = TypeParameterDescriptor.createWithDefaultBound(
|
||||
TypeParameterDescriptor typeParameterDescriptor = TypeParameterDescriptorImpl.createWithDefaultBound(
|
||||
classDescriptor,
|
||||
Collections.<AnnotationDescriptor>emptyList(),
|
||||
true, Variance.OUT_VARIANCE, Name.identifier("T" + (j + 1)), j);
|
||||
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.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);
|
||||
getterDescriptor.initialize(typeParameterDescriptor.getDefaultType());
|
||||
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);
|
||||
WritableScope scopeForInvokeWithReceiver = createScopeForInvokeFunction(receiverFunction, invokeWithReceiver);
|
||||
List<TypeParameterDescriptor> parameters = createTypeParameters(i, receiverFunction);
|
||||
parameters.add(0, TypeParameterDescriptor.createWithDefaultBound(
|
||||
parameters.add(0, TypeParameterDescriptorImpl.createWithDefaultBound(
|
||||
receiverFunction,
|
||||
Collections.<AnnotationDescriptor>emptyList(),
|
||||
true, Variance.IN_VARIANCE, Name.identifier("T"), 0));
|
||||
@@ -238,12 +238,12 @@ public class JetStandardClasses {
|
||||
private static List<TypeParameterDescriptor> createTypeParameters(int parameterCount, ClassDescriptorImpl function) {
|
||||
List<TypeParameterDescriptor> parameters = new ArrayList<TypeParameterDescriptor>();
|
||||
for (int j = 1; j <= parameterCount; j++) {
|
||||
parameters.add(TypeParameterDescriptor.createWithDefaultBound(
|
||||
parameters.add(TypeParameterDescriptorImpl.createWithDefaultBound(
|
||||
function,
|
||||
Collections.<AnnotationDescriptor>emptyList(),
|
||||
true, Variance.IN_VARIANCE, Name.identifier("P" + j), j));
|
||||
}
|
||||
parameters.add(TypeParameterDescriptor.createWithDefaultBound(
|
||||
parameters.add(TypeParameterDescriptorImpl.createWithDefaultBound(
|
||||
function,
|
||||
Collections.<AnnotationDescriptor>emptyList(),
|
||||
true, Variance.OUT_VARIANCE, Name.identifier("R"), parameterCount + 1));
|
||||
|
||||
@@ -146,7 +146,7 @@ public class DescriptorRenderer implements Renderer<DeclarationDescriptor> {
|
||||
|
||||
Object typeNameObject;
|
||||
|
||||
if (cd == null || cd instanceof TypeParameterDescriptor) {
|
||||
if (cd == null || cd instanceof TypeParameterDescriptorImpl) {
|
||||
typeNameObject = type.getConstructor();
|
||||
}
|
||||
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 ==
|
||||
class AnonymousInitializers() {
|
||||
val k = 34
|
||||
@@ -46,16 +33,29 @@ l2:
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[w($i)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[d(get() = 20), <END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>, d(get() = 20)]
|
||||
l3:
|
||||
<START> NEXT:[r(20)] PREV:[]
|
||||
r(20) NEXT:[<END>] PREV:[<START>]
|
||||
l4:
|
||||
<END> NEXT:[<SINK>] PREV:[r(20)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
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:
|
||||
<END> NEXT:[<SINK>] PREV:[w(a[10])]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
|
||||
@@ -9,9 +9,9 @@ l0:
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[v(var x : Int;)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== assignments ==
|
||||
fun assignments() : Unit {
|
||||
@@ -72,7 +72,7 @@ l5:
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[w(t.x)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
|
||||
@@ -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 ==
|
||||
fun f(a : Boolean) : Unit {
|
||||
1
|
||||
@@ -78,18 +65,31 @@ l6:
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[r(a || false)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[d({1}), <END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>, d({1})]
|
||||
l3:
|
||||
<START> NEXT:[r(1)] PREV:[]
|
||||
r(1) NEXT:[<END>] PREV:[<START>]
|
||||
l4:
|
||||
<END> NEXT:[<SINK>] PREV:[r(1)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
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 ==
|
||||
fun foo(a : Boolean, b : Int) : Unit {}
|
||||
@@ -104,9 +104,9 @@ l0:
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[read (Unit)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== genfun ==
|
||||
fun genfun<T>() : Unit {}
|
||||
@@ -117,9 +117,9 @@ l0:
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[read (Unit)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== flfun ==
|
||||
fun flfun(f : () -> Any) : Unit {}
|
||||
@@ -132,7 +132,7 @@ l0:
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[read (Unit)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
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>]
|
||||
=====================
|
||||
@@ -0,0 +1,4 @@
|
||||
fun test() {
|
||||
throw Exception()
|
||||
test()
|
||||
}
|
||||
@@ -7,7 +7,7 @@ l0:
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[read (Unit)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
|
||||
@@ -15,7 +15,7 @@ l0:
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[jmp(error)]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[jmp(error)]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
|
||||
@@ -21,9 +21,9 @@ l1:
|
||||
l3:
|
||||
<END> NEXT:[<SINK>] PREV:[r(2)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== t2 ==
|
||||
fun t2() {
|
||||
@@ -65,36 +65,9 @@ l1:
|
||||
l5:
|
||||
<END> NEXT:[<SINK>] PREV:[ret l1, r(2)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<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>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== t3 ==
|
||||
fun t3() {
|
||||
@@ -141,9 +114,9 @@ l1:
|
||||
l8:
|
||||
<END> NEXT:[<SINK>] PREV:[r(2)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[d({ () => if (2 > 3) { retur..), <END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>, d({ () => if (2 > 3) { retur..)]
|
||||
l3:
|
||||
<START> NEXT:[r(())] PREV:[]
|
||||
r(()) NEXT:[r(2)] PREV:[<START>]
|
||||
@@ -160,54 +133,36 @@ l4:
|
||||
l6:
|
||||
<END> NEXT:[<SINK>] PREV:[ret l4, read (Unit)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== anonymous_1 ==
|
||||
== anonymous_0 ==
|
||||
{ () =>
|
||||
try {
|
||||
1
|
||||
if (2 > 3) {
|
||||
return@
|
||||
}
|
||||
} finally {
|
||||
2
|
||||
if (2 > 3) {
|
||||
return@
|
||||
}
|
||||
}
|
||||
}
|
||||
---------------------
|
||||
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:[]
|
||||
<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:[r(2)] PREV:[jf(l5)]
|
||||
l6:
|
||||
l7:
|
||||
r(2) NEXT:[<END>] PREV:[read (Unit)]
|
||||
read (Unit) NEXT:[<END>] PREV:[jf(l5)]
|
||||
l4:
|
||||
l8:
|
||||
<END> NEXT:[<SINK>] PREV:[ret l4, r(2)]
|
||||
l6:
|
||||
<END> NEXT:[<SINK>] PREV:[ret l4, read (Unit)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== t4 ==
|
||||
fun t4() {
|
||||
@@ -250,9 +205,9 @@ l2:
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[r({ () => try { 1 if (2 > 3)..)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[d({ () => try { 1 if (2 > 3)..), <END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>, d({ () => try { 1 if (2 > 3)..)]
|
||||
l3:
|
||||
<START> NEXT:[r(())] PREV:[]
|
||||
r(()) NEXT:[r(try { 1 if (2 > 3) { retur..)] PREV:[<START>]
|
||||
@@ -282,9 +237,54 @@ l4:
|
||||
l8:
|
||||
<END> NEXT:[<SINK>] PREV:[ret l4, r(2)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
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 ==
|
||||
fun t5() {
|
||||
@@ -346,9 +346,9 @@ l3:
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[read (Unit)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== t6 ==
|
||||
fun t6() {
|
||||
@@ -410,9 +410,9 @@ l1:
|
||||
l9:
|
||||
<END> NEXT:[<SINK>] PREV:[r(2)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== t7 ==
|
||||
fun t7() {
|
||||
@@ -471,9 +471,9 @@ l1:
|
||||
l9:
|
||||
<END> NEXT:[<SINK>] PREV:[r(2)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== t8 ==
|
||||
fun t8(a : Int) {
|
||||
@@ -542,9 +542,9 @@ l2:
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[read (Unit)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== t9 ==
|
||||
fun t9(a : Int) {
|
||||
@@ -613,9 +613,9 @@ l1:
|
||||
l9:
|
||||
<END> NEXT:[<SINK>] PREV:[r(2)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== t10 ==
|
||||
fun t10(a : Int) {
|
||||
@@ -681,9 +681,9 @@ l1:
|
||||
l9:
|
||||
<END> NEXT:[<SINK>] PREV:[r(2)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== t11 ==
|
||||
fun t11() {
|
||||
@@ -714,9 +714,9 @@ l1:
|
||||
l3:
|
||||
<END> NEXT:[<SINK>] PREV:[ret(*) l1]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== t12 ==
|
||||
fun t12() : Int {
|
||||
@@ -749,9 +749,9 @@ l1:
|
||||
l3:
|
||||
<END> NEXT:[<SINK>] PREV:[ret(*) l1]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== t13 ==
|
||||
fun t13() : Int {
|
||||
@@ -802,9 +802,9 @@ l1:
|
||||
l6:
|
||||
<END> NEXT:[<SINK>] PREV:[ret(*) l1, r(doSmth(3))]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== t14 ==
|
||||
fun t14() : Int {
|
||||
@@ -843,9 +843,9 @@ l4:
|
||||
l6:
|
||||
<END> NEXT:[<SINK>] PREV:[ret(*) l1, jmp(l4)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== t15 ==
|
||||
fun t15() : Int {
|
||||
@@ -898,9 +898,9 @@ l1:
|
||||
l6:
|
||||
<END> NEXT:[<SINK>] PREV:[ret(*) l1, ret(*) l1]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== t16 ==
|
||||
fun t16() : Int {
|
||||
@@ -951,9 +951,9 @@ l1:
|
||||
l6:
|
||||
<END> NEXT:[<SINK>] PREV:[ret(*) l1, r(doSmth(3))]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== doSmth ==
|
||||
fun doSmth(i: Int) {
|
||||
@@ -967,7 +967,7 @@ l0:
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[read (Unit)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
|
||||
@@ -29,9 +29,9 @@ l2:
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[read (Unit)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== doSmth ==
|
||||
fun doSmth(i: Int) {}
|
||||
@@ -44,7 +44,7 @@ l0:
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[read (Unit)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
|
||||
@@ -48,9 +48,9 @@ l5:
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[r(doSmth(r))]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== t2 ==
|
||||
fun t2(b: Boolean) {
|
||||
@@ -92,9 +92,9 @@ l1:
|
||||
l5:
|
||||
<END> NEXT:[<SINK>] PREV:[ret l1, ret l1, read (Unit)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== doSmth ==
|
||||
fun doSmth(s: String) {}
|
||||
@@ -107,7 +107,7 @@ l0:
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[read (Unit)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
|
||||
@@ -72,7 +72,7 @@ l13:
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[r(14)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
|
||||
@@ -25,56 +25,9 @@ l0:
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[w(a)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<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>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== doSmth ==
|
||||
fun doSmth(i: Int) {}
|
||||
@@ -87,9 +40,9 @@ l0:
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[read (Unit)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== test1 ==
|
||||
fun test1() {
|
||||
@@ -122,9 +75,29 @@ l0:
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[w(a)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
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 ==
|
||||
fun test2() {
|
||||
@@ -152,25 +125,9 @@ l0:
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[w(a)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<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>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== test3 ==
|
||||
fun test3() {
|
||||
@@ -206,9 +163,9 @@ l2:
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[w(a)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[d(fun inner_bar() { y = 10 }) , <END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>, d(fun inner_bar() { y = 10 }) ]
|
||||
l3:
|
||||
<START> NEXT:[r(10)] PREV:[]
|
||||
r(10) NEXT:[w(y)] PREV:[<START>]
|
||||
@@ -216,12 +173,12 @@ l3:
|
||||
l4:
|
||||
<END> NEXT:[<SINK>] PREV:[w(y)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== ggg ==
|
||||
fun ggg() {
|
||||
== inner_bar ==
|
||||
fun inner_bar() {
|
||||
y = 10
|
||||
}
|
||||
---------------------
|
||||
@@ -232,9 +189,9 @@ l3:
|
||||
l4:
|
||||
<END> NEXT:[<SINK>] PREV:[w(y)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== test4 ==
|
||||
fun test4() {
|
||||
@@ -285,9 +242,9 @@ l2:
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[w(a)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[d(fun ggg() { y = 10 }) , <END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>, d(fun ggg() { y = 10 }) ]
|
||||
l3:
|
||||
<START> NEXT:[r(10)] PREV:[]
|
||||
r(10) NEXT:[w(y)] PREV:[<START>]
|
||||
@@ -295,41 +252,25 @@ l3:
|
||||
l4:
|
||||
<END> NEXT:[<SINK>] PREV:[w(y)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== foo ==
|
||||
fun foo() {
|
||||
x = 3
|
||||
== ggg ==
|
||||
fun ggg() {
|
||||
y = 10
|
||||
}
|
||||
---------------------
|
||||
l3:
|
||||
<START> NEXT:[r(3)] PREV:[]
|
||||
r(3) NEXT:[w(x)] PREV:[<START>]
|
||||
w(x) NEXT:[<END>] PREV:[r(3)]
|
||||
<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(x)]
|
||||
<END> NEXT:[<SINK>] PREV:[w(y)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<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>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== test5 ==
|
||||
fun test5() {
|
||||
@@ -392,9 +333,9 @@ l5:
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[w(a)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
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:
|
||||
<START> NEXT:[r(3)] PREV:[]
|
||||
r(3) NEXT:[w(x)] PREV:[<START>]
|
||||
@@ -402,9 +343,9 @@ l3:
|
||||
l4:
|
||||
<END> NEXT:[<SINK>] PREV:[w(x)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
l6:
|
||||
<START> NEXT:[r(4)] PREV:[]
|
||||
r(4) NEXT:[w(x)] PREV:[<START>]
|
||||
@@ -412,28 +353,39 @@ l6:
|
||||
l7:
|
||||
<END> NEXT:[<SINK>] PREV:[w(x)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== foo ==
|
||||
fun foo() {
|
||||
val b : Int = 1
|
||||
doSmth(b)
|
||||
x = 3
|
||||
}
|
||||
---------------------
|
||||
l0:
|
||||
<START> NEXT:[v(val b : Int = 1)] PREV:[]
|
||||
v(val b : Int = 1) NEXT:[r(1)] PREV:[<START>]
|
||||
r(1) NEXT:[w(b)] PREV:[v(val b : Int = 1)]
|
||||
w(b) NEXT:[r(b)] PREV:[r(1)]
|
||||
r(b) NEXT:[r(doSmth)] PREV:[w(b)]
|
||||
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))]
|
||||
l3:
|
||||
<START> NEXT:[r(3)] PREV:[]
|
||||
r(3) NEXT:[w(x)] PREV:[<START>]
|
||||
w(x) NEXT:[<END>] PREV:[r(3)]
|
||||
l4:
|
||||
<END> NEXT:[<SINK>] PREV:[w(x)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
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:
|
||||
<END> NEXT:[<SINK>] PREV:[read (Unit)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== dowhile ==
|
||||
fun dowhile() {
|
||||
@@ -53,7 +53,7 @@ l3:
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[ret l1]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
|
||||
@@ -15,7 +15,7 @@ l2:
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[ret(*) l1, r(false || (return false))]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
|
||||
@@ -7,7 +7,7 @@ l0:
|
||||
l1:
|
||||
<END> NEXT:[<SINK>] PREV:[r(1)]
|
||||
error:
|
||||
<ERROR> NEXT:[] PREV:[]
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<END>]
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
|
||||
@@ -175,12 +175,12 @@ class B() {
|
||||
|
||||
fun testFunctionLiterals() {
|
||||
val <!UNUSED_VARIABLE!>endsWithVarDeclaration<!> : () -> Boolean = {
|
||||
<!EXPECTED_TYPE_MISMATCH!>val x = 2<!>
|
||||
<!EXPECTED_TYPE_MISMATCH!>val <!UNUSED_VARIABLE!>x<!> = 2<!>
|
||||
}
|
||||
|
||||
val <!UNUSED_VARIABLE!>endsWithAssignment<!> = { () : Int ->
|
||||
var x = 1
|
||||
<!EXPECTED_TYPE_MISMATCH!>x = 333<!>
|
||||
var <!ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE!>x<!> = 1
|
||||
<!EXPECTED_TYPE_MISMATCH!>x = <!UNUSED_VALUE!>333<!><!>
|
||||
}
|
||||
|
||||
val <!UNUSED_VARIABLE!>endsWithReAssignment<!> = { () : Int ->
|
||||
@@ -189,19 +189,19 @@ fun testFunctionLiterals() {
|
||||
}
|
||||
|
||||
val <!UNUSED_VARIABLE!>endsWithFunDeclaration<!> : () -> String = {
|
||||
var x = 1
|
||||
x = 333
|
||||
var <!ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE!>x<!> = 1
|
||||
x = <!UNUSED_VALUE!>333<!>
|
||||
<!EXPECTED_TYPE_MISMATCH!>fun meow() : Unit {}<!>
|
||||
}
|
||||
|
||||
val <!UNUSED_VARIABLE!>endsWithObjectDeclaration<!> : () -> Int = {
|
||||
var x = 1
|
||||
x = 333
|
||||
var <!ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE!>x<!> = 1
|
||||
x = <!UNUSED_VALUE!>333<!>
|
||||
<!EXPECTED_TYPE_MISMATCH!>object A {}<!>
|
||||
}
|
||||
|
||||
val <!UNUSED_VARIABLE!>expectedUnitReturnType1<!> = { () : Unit ->
|
||||
val x = 1
|
||||
val <!UNUSED_VARIABLE!>x<!> = 1
|
||||
}
|
||||
|
||||
val <!UNUSED_VARIABLE!>expectedUnitReturnType2<!> = { () : Unit ->
|
||||
|
||||
@@ -3,8 +3,8 @@ fun demo() {
|
||||
val a = ""
|
||||
val asd = 1
|
||||
val bar = 5
|
||||
fun map(f : () -> Any?) : Int = 1
|
||||
fun buzz(f : () -> Any?) : Int = 1
|
||||
fun map(<!UNUSED_PARAMETER!>f<!> : () -> Any?) : Int = 1
|
||||
fun buzz(<!UNUSED_PARAMETER!>f<!> : () -> Any?) : Int = 1
|
||||
val sdf = 1
|
||||
val foo = 3;
|
||||
<!UNUSED_EXPRESSION!>"$abc"<!>
|
||||
@@ -19,4 +19,4 @@ fun demo() {
|
||||
<!UNUSED_EXPRESSION!>"foo${bar + map {
|
||||
"foo$sdf${ buzz{}}" }}sdfsdf"<!>
|
||||
<!UNUSED_EXPRESSION!>"a<!ILLEGAL_ESCAPE_SEQUENCE!>\u<!> <!ILLEGAL_ESCAPE_SEQUENCE!>\u<!>0 <!ILLEGAL_ESCAPE_SEQUENCE!>\u<!>00 <!ILLEGAL_ESCAPE_SEQUENCE!>\u<!>000 \u0000 \u0AaA <!ILLEGAL_ESCAPE_SEQUENCE!>\u<!>0AAz.length( ) + \u0022b"<!>
|
||||
}
|
||||
}
|
||||
@@ -101,7 +101,7 @@ fun t5() {
|
||||
for (i in 0..2) {
|
||||
<!VAL_REASSIGNMENT!>i<!> += 1
|
||||
fun t5() {
|
||||
<!VAL_REASSIGNMENT!>i<!> += 3
|
||||
i += 3
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -297,8 +297,8 @@ class TestObjectExpression() {
|
||||
<!VAL_REASSIGNMENT!>a<!> = 231
|
||||
}
|
||||
fun inner2() {
|
||||
<!VAL_REASSIGNMENT!>y<!> = 101
|
||||
<!VAL_REASSIGNMENT!>a<!> = 231
|
||||
y = 101
|
||||
a = 231
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
@@ -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
|
||||
}
|
||||
val <!UNUSED_VARIABLE!>h<!> = {(): String ->
|
||||
var x = 1
|
||||
<!EXPECTED_TYPE_MISMATCH!>x = 2<!> //the same
|
||||
var <!ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE!>x<!> = 1
|
||||
<!EXPECTED_TYPE_MISMATCH!>x = <!UNUSED_VALUE!>2<!><!> //the same
|
||||
}
|
||||
val array1 = MyArray1()
|
||||
val <!UNUSED_VARIABLE!>i<!> = { (): String ->
|
||||
@@ -46,4 +46,4 @@ class MyArray1() {
|
||||
|
||||
class MyNumber() {
|
||||
fun inc(): MyNumber = MyNumber()
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
fun f(<!UNUSED_PARAMETER!>i<!>: Int) {
|
||||
for (j in 1..100) {
|
||||
<!UNUSED_FUNCTION_LITERAL!>{
|
||||
var <!NAME_SHADOWING!>i<!> = 12
|
||||
var <!NAME_SHADOWING, UNUSED_VARIABLE!>i<!> = 12
|
||||
}<!>
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
fun ff(): Int {
|
||||
var i = 1
|
||||
<!UNUSED_FUNCTION_LITERAL!>{
|
||||
val <!NAME_SHADOWING!>i<!> = 2
|
||||
val <!NAME_SHADOWING, UNUSED_VARIABLE!>i<!> = 2
|
||||
}<!>
|
||||
return i
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fun f(): Int {
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,6 @@ import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.analyzer.AnalyzeExhaust;
|
||||
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.Diagnostic;
|
||||
import org.jetbrains.jet.lang.diagnostics.Severity;
|
||||
@@ -170,8 +169,8 @@ public class JetTestUtils {
|
||||
private JetTestUtils() {
|
||||
}
|
||||
|
||||
public static AnalyzeExhaust analyzeFile(@NotNull JetFile namespace, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) {
|
||||
return AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegration(namespace, flowDataTraceFactory,
|
||||
public static AnalyzeExhaust analyzeFile(@NotNull JetFile namespace) {
|
||||
return AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegration(namespace,
|
||||
CompileCompilerDependenciesTest.compilerDependenciesForTests(CompilerSpecialMode.REGULAR, true));
|
||||
}
|
||||
|
||||
|
||||
@@ -28,9 +28,10 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.JetLiteFixture;
|
||||
import org.jetbrains.jet.JetTestCaseBuilder;
|
||||
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.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.java.CompilerSpecialMode;
|
||||
|
||||
import java.io.File;
|
||||
@@ -72,37 +73,17 @@ public class JetControlFlowTest extends JetLiteFixture {
|
||||
JetFile file = loadPsiFile(myName + ".jet");
|
||||
|
||||
final Map<JetElement, Pseudocode> data = new LinkedHashMap<JetElement, Pseudocode>();
|
||||
final JetPseudocodeTrace pseudocodeTrace = new JetPseudocodeTrace() {
|
||||
|
||||
@Override
|
||||
public void recordControlFlowData(@NotNull JetElement element, @NotNull Pseudocode pseudocode) {
|
||||
data.put(element, pseudocode);
|
||||
AnalyzeExhaust analyzeExhaust = JetTestUtils.analyzeFile(file);
|
||||
List<JetDeclaration> declarations = file.getDeclarations();
|
||||
BindingContext bindingContext = analyzeExhaust.getBindingContext();
|
||||
for (JetDeclaration declaration : declarations) {
|
||||
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 {
|
||||
processCFData(myName, data);
|
||||
@@ -123,6 +104,7 @@ public class JetControlFlowTest extends JetLiteFixture {
|
||||
StringBuilder instructionDump = new StringBuilder();
|
||||
int i = 0;
|
||||
for (Pseudocode pseudocode : pseudocodes) {
|
||||
|
||||
JetElement correspondingElement = pseudocode.getCorrespondingElement();
|
||||
String label = "";
|
||||
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("\n---------------------\n");
|
||||
dumpInstructions(pseudocode, instructionDump);
|
||||
dumpInstructions((PseudocodeImpl) pseudocode, instructionDump);
|
||||
instructionDump.append("=====================\n");
|
||||
|
||||
//check edges directions
|
||||
Collection<Instruction> instructions = pseudocode.getMutableInstructionList();
|
||||
Collection<Instruction> instructions = ((PseudocodeImpl)pseudocode).getAllInstructions();
|
||||
for (Instruction instruction : instructions) {
|
||||
if (!((InstructionImpl)instruction).isDead()) {
|
||||
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) {
|
||||
dfsDump(nodes, edges, pseudocode.getMutableInstructionList().get(0), nodeNames);
|
||||
public void dfsDump(PseudocodeImpl pseudocode, StringBuilder nodes, StringBuilder edges, Map<Instruction, String> nodeNames) {
|
||||
dfsDump(nodes, edges, pseudocode.getAllInstructions().get(0), 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();
|
||||
}
|
||||
|
||||
public void dumpInstructions(Pseudocode pseudocode, @NotNull StringBuilder out) {
|
||||
List<Instruction> instructions = pseudocode.getMutableInstructionList();
|
||||
public void dumpInstructions(PseudocodeImpl pseudocode, @NotNull StringBuilder out) {
|
||||
List<Instruction> instructions = pseudocode.getAllInstructions();
|
||||
Set<Instruction> remainedAfterPostProcessInstructions = Sets.newHashSet(pseudocode.getInstructions());
|
||||
List<Pseudocode.PseudocodeLabel> labels = pseudocode.getLabels();
|
||||
List<Pseudocode> locals = new ArrayList<Pseudocode>();
|
||||
List<PseudocodeImpl.PseudocodeLabel> labels = pseudocode.getLabels();
|
||||
List<PseudocodeImpl> locals = new ArrayList<PseudocodeImpl>();
|
||||
int maxLength = 0;
|
||||
int maxNextLength = 0;
|
||||
for (Instruction instruction : instructions) {
|
||||
@@ -276,9 +258,9 @@ public class JetControlFlowTest extends JetLiteFixture {
|
||||
Instruction instruction = instructions.get(i);
|
||||
if (instruction instanceof LocalDeclarationInstruction) {
|
||||
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) {
|
||||
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(" PREV:").append(formatInstructionList(instruction.getPreviousInstructions())).append("\n");
|
||||
}
|
||||
for (Pseudocode local : locals) {
|
||||
for (PseudocodeImpl local : locals) {
|
||||
dumpInstructions(local, out);
|
||||
}
|
||||
}
|
||||
@@ -300,7 +282,7 @@ public class JetControlFlowTest extends JetLiteFixture {
|
||||
public void visitLocalDeclarationInstruction(LocalDeclarationInstruction instruction) {
|
||||
int index = count[0];
|
||||
// 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);
|
||||
}
|
||||
|
||||
@@ -415,7 +397,7 @@ public class JetControlFlowTest extends JetLiteFixture {
|
||||
int[] count = new int[1];
|
||||
Map<Instruction, String> nodeToName = new HashMap<Instruction, String>();
|
||||
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;
|
||||
for (Pseudocode pseudocode : pseudocodes) {
|
||||
@@ -431,7 +413,7 @@ public class JetControlFlowTest extends JetLiteFixture {
|
||||
out.println("subgraph cluster_" + i + " {\n" +
|
||||
"label=\"" + label + "\";\n" +
|
||||
"color=blue;\n");
|
||||
dumpEdges(pseudocode.getMutableInstructionList(), out, count, nodeToName);
|
||||
dumpEdges(((PseudocodeImpl)pseudocode).getAllInstructions(), out, count, nodeToName);
|
||||
out.println("}");
|
||||
i++;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.CompileCompilerDependenciesTest;
|
||||
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.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
@@ -107,8 +106,7 @@ public class CheckerTestUtilTest extends JetLiteFixture {
|
||||
|
||||
public void test(final @NotNull PsiFile psiFile) {
|
||||
BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegration(
|
||||
(JetFile) psiFile, JetControlFlowDataTraceFactory.EMPTY,
|
||||
CompileCompilerDependenciesTest.compilerDependenciesForTests(CompilerSpecialMode.REGULAR, true))
|
||||
(JetFile) psiFile, CompileCompilerDependenciesTest.compilerDependenciesForTests(CompilerSpecialMode.REGULAR, true))
|
||||
.getBindingContext();
|
||||
|
||||
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.JetTestCaseBuilder;
|
||||
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.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
||||
@@ -172,9 +171,7 @@ public class JetDiagnosticsTest extends JetLiteFixture {
|
||||
}
|
||||
|
||||
BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
|
||||
getProject(), jetFiles, Predicates.<PsiFile>alwaysTrue(), JetControlFlowDataTraceFactory.EMPTY,
|
||||
myEnvironment.getCompilerDependencies())
|
||||
.getBindingContext();
|
||||
getProject(), jetFiles, Predicates.<PsiFile>alwaysTrue(), myEnvironment.getCompilerDependencies()).getBindingContext();
|
||||
|
||||
boolean ok = true;
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.JetTestCaseBuilder;
|
||||
import org.jetbrains.jet.JetTestUtils;
|
||||
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.psi.JetFile;
|
||||
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);
|
||||
|
||||
BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegrationAndCheckForErrors(
|
||||
psiFile, JetControlFlowDataTraceFactory.EMPTY,
|
||||
jetCoreEnvironment.getCompilerDependencies())
|
||||
psiFile, jetCoreEnvironment.getCompilerDependencies())
|
||||
.getBindingContext();
|
||||
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.analyzer.AnalyzeExhaust;
|
||||
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.JetPsiUtil;
|
||||
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
||||
@@ -186,8 +185,7 @@ public abstract class CodegenTestCase extends UsefulTestCase {
|
||||
|
||||
private GenerationState generateCommon(ClassBuilderFactory classBuilderFactory) {
|
||||
final AnalyzeExhaust analyzeExhaust = AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegrationAndCheckForErrors(
|
||||
myFile, JetControlFlowDataTraceFactory.EMPTY,
|
||||
myEnvironment.getCompilerDependencies());
|
||||
myFile, myEnvironment.getCompilerDependencies());
|
||||
analyzeExhaust.throwIfError();
|
||||
AnalyzingUtils.throwExceptionOnErrors(analyzeExhaust.getBindingContext());
|
||||
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.jet.CompileCompilerDependenciesTest;
|
||||
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.resolve.java.AnalyzerFacadeForJVM;
|
||||
import org.jetbrains.jet.lang.resolve.java.CompilerSpecialMode;
|
||||
@@ -37,8 +36,7 @@ public class GenerationUtils {
|
||||
|
||||
public static GenerationState compileFileGetGenerationStateForTest(JetFile psiFile, @NotNull CompilerSpecialMode compilerSpecialMode) {
|
||||
final AnalyzeExhaust analyzeExhaust = AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegrationAndCheckForErrors(
|
||||
psiFile, JetControlFlowDataTraceFactory.EMPTY,
|
||||
CompileCompilerDependenciesTest.compilerDependenciesForTests(compilerSpecialMode, true));
|
||||
psiFile, CompileCompilerDependenciesTest.compilerDependenciesForTests(compilerSpecialMode, true));
|
||||
analyzeExhaust.throwIfError();
|
||||
GenerationState state = new GenerationState(psiFile.getProject(), ClassBuilderFactories.binaries(false), analyzeExhaust, Collections.singletonList(psiFile));
|
||||
state.compileCorrectFiles(CompilationErrorHandler.THROW_EXCEPTION);
|
||||
|
||||
@@ -22,7 +22,6 @@ import org.jetbrains.jet.JetLiteFixture;
|
||||
import org.jetbrains.jet.JetTestCaseBuilder;
|
||||
import org.jetbrains.jet.JetTestUtils;
|
||||
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.psi.JetElement;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
@@ -78,8 +77,7 @@ public class DescriptorRendererTest extends JetLiteFixture {
|
||||
JetFile psiFile = createPsiFile(null, fileName, loadFile(fileName));
|
||||
AnalyzeExhaust analyzeExhaust =
|
||||
AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegration(
|
||||
(JetFile) psiFile, JetControlFlowDataTraceFactory.EMPTY,
|
||||
myEnvironment.getCompilerDependencies());
|
||||
(JetFile) psiFile, myEnvironment.getCompilerDependencies());
|
||||
final BindingContext bindingContext = analyzeExhaust.getBindingContext();
|
||||
final List<DeclarationDescriptor> descriptors = new ArrayList<DeclarationDescriptor>();
|
||||
psiFile.acceptChildren(new JetVisitorVoid() {
|
||||
|
||||
@@ -27,7 +27,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.analyzer.AnalyzeExhaust;
|
||||
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.ClassifierDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
@@ -154,8 +153,7 @@ public abstract class ExpectedResolveData {
|
||||
JetStandardLibrary lib = JetStandardLibrary.getInstance();
|
||||
|
||||
AnalyzeExhaust analyzeExhaust = AnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(project, files,
|
||||
Predicates.<PsiFile>alwaysTrue(), JetControlFlowDataTraceFactory.EMPTY,
|
||||
jetCoreEnvironment.getCompilerDependencies());
|
||||
Predicates.<PsiFile>alwaysTrue(), jetCoreEnvironment.getCompilerDependencies());
|
||||
BindingContext bindingContext = analyzeExhaust.getBindingContext();
|
||||
for (Diagnostic diagnostic : bindingContext.getDiagnostics()) {
|
||||
if (diagnostic.getFactory() instanceof UnresolvedReferenceDiagnosticFactory) {
|
||||
|
||||
@@ -20,7 +20,6 @@ import org.jetbrains.jet.JetLiteFixture;
|
||||
import org.jetbrains.jet.JetTestUtils;
|
||||
import org.jetbrains.jet.analyzer.AnalyzeExhaust;
|
||||
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.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
@@ -66,7 +65,6 @@ public class JetDefaultModalityModifiersTest extends JetLiteFixture {
|
||||
JetDeclaration aClass = declarations.get(0);
|
||||
assert aClass instanceof JetClass;
|
||||
AnalyzeExhaust bindingContext = AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegration(file,
|
||||
JetControlFlowDataTraceFactory.EMPTY,
|
||||
myEnvironment.getCompilerDependencies());
|
||||
DeclarationDescriptor classDescriptor = bindingContext.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, aClass);
|
||||
WritableScopeImpl scope = new WritableScopeImpl(libraryScope, root, RedeclarationHandler.DO_NOTHING);
|
||||
|
||||
@@ -698,7 +698,7 @@ public class JetTypeCheckerTest extends JetLiteFixture {
|
||||
parameterScope.changeLockLevel(WritableScope.LockLevel.BOTH);
|
||||
|
||||
// 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.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;
|
||||
}
|
||||
|
||||
if (descriptor instanceof TypeParameterDescriptor) {
|
||||
if (descriptor instanceof TypeParameterDescriptorImpl) {
|
||||
return PlatformIcons.CLASS_ICON;
|
||||
}
|
||||
|
||||
|
||||
@@ -183,7 +183,7 @@ public class JetCompletionContributor extends CompletionContributor {
|
||||
DeclarationDescriptor descriptor = ((JetLookupObject)object).getDescriptor();
|
||||
return (descriptor instanceof ClassDescriptor) ||
|
||||
(descriptor instanceof NamespaceDescriptor) ||
|
||||
(descriptor instanceof TypeParameterDescriptor);
|
||||
(descriptor instanceof TypeParameterDescriptorImpl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@ import com.intellij.psi.util.PsiTreeUtil;
|
||||
import jet.Tuple2;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
@@ -74,8 +73,7 @@ public class JetSourceNavigationHelper {
|
||||
BindingContext bindingContext = AnalyzerFacadeProvider.getAnalyzerFacadeForProject(project).analyzeFiles(
|
||||
project,
|
||||
libraryFiles,
|
||||
Predicates.<PsiFile>alwaysTrue(),
|
||||
JetControlFlowDataTraceFactory.EMPTY).getBindingContext();
|
||||
Predicates.<PsiFile>alwaysTrue()).getBindingContext();
|
||||
D descriptor = bindingContext.get(slice, fqName);
|
||||
if (descriptor != null) {
|
||||
return new Tuple2<BindingContext, D>(bindingContext, descriptor);
|
||||
|
||||
@@ -28,7 +28,6 @@ import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.util.Function;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
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.Errors;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
@@ -94,7 +93,6 @@ public final class AnalyzerFacadeWithCache {
|
||||
AnalyzeExhaust exhaust = AnalyzerFacadeProvider.getAnalyzerFacadeForFile(file).analyzeBodiesInFiles(
|
||||
file.getProject(),
|
||||
Predicates.<PsiFile>equalTo(file),
|
||||
JetControlFlowDataTraceFactory.EMPTY,
|
||||
new DelegatingBindingTrace(analyzeExhaustHeaders.getBindingContext()),
|
||||
context);
|
||||
|
||||
@@ -137,8 +135,7 @@ public final class AnalyzerFacadeWithCache {
|
||||
AnalyzeExhaust exhaust = AnalyzerFacadeProvider.getAnalyzerFacadeForFile(fileToCache)
|
||||
.analyzeFiles(fileToCache.getProject(),
|
||||
headerFiles,
|
||||
Predicates.<PsiFile>alwaysFalse(),
|
||||
JetControlFlowDataTraceFactory.EMPTY);
|
||||
Predicates.<PsiFile>alwaysFalse());
|
||||
|
||||
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.jet.analyzer.AnalyzeExhaust;
|
||||
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.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.BodiesResolveContext;
|
||||
@@ -44,8 +43,7 @@ public enum JSAnalyzerFacadeForIDEA implements AnalyzerFacade {
|
||||
@Override
|
||||
public AnalyzeExhaust analyzeFiles(@NotNull Project project,
|
||||
@NotNull Collection<JetFile> files,
|
||||
@NotNull Predicate<PsiFile> filesToAnalyzeCompletely,
|
||||
@NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) {
|
||||
@NotNull Predicate<PsiFile> filesToAnalyzeCompletely) {
|
||||
return AnalyzerFacadeForJS.analyzeFiles(files, filesToAnalyzeCompletely, new IDEAConfig(project), true);
|
||||
}
|
||||
|
||||
@@ -53,7 +51,6 @@ public enum JSAnalyzerFacadeForIDEA implements AnalyzerFacade {
|
||||
@Override
|
||||
public AnalyzeExhaust analyzeBodiesInFiles(@NotNull Project project,
|
||||
@NotNull Predicate<PsiFile> filesForBodiesResolve,
|
||||
@NotNull JetControlFlowDataTraceFactory flowDataTraceFactory,
|
||||
@NotNull BindingTrace traceContext,
|
||||
@NotNull BodiesResolveContext 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
Reference in New Issue
Block a user