Merge remote branch 'origin/master'
This commit is contained in:
@@ -10,7 +10,6 @@ import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetDeclarationWithBody;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetFunctionLiteral;
|
||||
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
@@ -100,7 +99,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
||||
generateBridge(name, funDescriptor, fun, cv);
|
||||
captureThis = generateBody(funDescriptor, cv, fun.getFunctionLiteral());
|
||||
ClassDescriptor thisDescriptor = context.getThisDescriptor();
|
||||
final Type enclosingType = thisDescriptor == null ? null : Type.getObjectType(thisDescriptor.getName());
|
||||
final Type enclosingType = thisDescriptor == null ? null : state.getTypeMapper().mapType(thisDescriptor.getDefaultType());
|
||||
if (enclosingType == null)
|
||||
captureThis = false;
|
||||
|
||||
@@ -164,7 +163,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
||||
Collections.<TypeParameterDescriptor>emptyList(),
|
||||
Collections.singleton((funDescriptor.getReceiverParameter().exists() ? JetStandardClasses.getReceiverFunction(arity) : JetStandardClasses.getFunction(arity)).getDefaultType()), JetScope.EMPTY, Collections.<ConstructorDescriptor>emptySet(), null);
|
||||
|
||||
final CodegenContext.ClosureContext closureContext = context.intoClosure(funDescriptor, function, name, this);
|
||||
final CodegenContext.ClosureContext closureContext = context.intoClosure(funDescriptor, function, name, this, state.getTypeMapper());
|
||||
FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state);
|
||||
fc.generateMethod(body, invokeSignature(funDescriptor), funDescriptor);
|
||||
return closureContext.outerWasUsed;
|
||||
|
||||
@@ -104,24 +104,24 @@ public abstract class CodegenContext {
|
||||
return new ClassContext(descriptor, kind, this, typeMapper);
|
||||
}
|
||||
|
||||
public CodegenContext intoAnonymousClass(@NotNull ObjectOrClosureCodegen closure, ClassDescriptor descriptor, OwnerKind kind) {
|
||||
return new AnonymousClassContext(descriptor, kind, this, closure);
|
||||
public CodegenContext intoAnonymousClass(@NotNull ObjectOrClosureCodegen closure, ClassDescriptor descriptor, OwnerKind kind, JetTypeMapper typeMapper) {
|
||||
return new AnonymousClassContext(descriptor, kind, this, closure, typeMapper);
|
||||
}
|
||||
|
||||
public MethodContext intoFunction(FunctionDescriptor descriptor) {
|
||||
return new MethodContext(descriptor, getContextKind(), this);
|
||||
}
|
||||
|
||||
public ConstructorContext intoConstructor(ConstructorDescriptor descriptor) {
|
||||
public ConstructorContext intoConstructor(ConstructorDescriptor descriptor, JetTypeMapper typeMapper) {
|
||||
if(descriptor == null) {
|
||||
descriptor = new ConstructorDescriptorImpl(getThisDescriptor(), Collections.<AnnotationDescriptor>emptyList(), true)
|
||||
.initialize(Collections.<TypeParameterDescriptor>emptyList(), Collections.<ValueParameterDescriptor>emptyList(), Modality.OPEN, Visibility.PUBLIC);
|
||||
}
|
||||
return new ConstructorContext(descriptor, getContextKind(), this);
|
||||
return new ConstructorContext(descriptor, getContextKind(), this, typeMapper);
|
||||
}
|
||||
|
||||
public ClosureContext intoClosure(FunctionDescriptor funDescriptor, ClassDescriptor classDescriptor, String internalClassName, ClosureCodegen closureCodegen) {
|
||||
return new ClosureContext(funDescriptor, classDescriptor, this, closureCodegen, internalClassName);
|
||||
public ClosureContext intoClosure(FunctionDescriptor funDescriptor, ClassDescriptor classDescriptor, String internalClassName, ClosureCodegen closureCodegen, JetTypeMapper typeMapper) {
|
||||
return new ClosureContext(funDescriptor, classDescriptor, this, closureCodegen, internalClassName, typeMapper);
|
||||
}
|
||||
|
||||
public FrameMap prepareFrame(JetTypeMapper mapper) {
|
||||
@@ -170,12 +170,12 @@ public abstract class CodegenContext {
|
||||
return parentContext != null ? parentContext.lookupInContext(d, v, result) : null;
|
||||
}
|
||||
|
||||
public Type enclosingClassType() {
|
||||
public Type enclosingClassType(JetTypeMapper typeMapper) {
|
||||
CodegenContext cur = getParentContext();
|
||||
while(cur != null && !(cur.getContextDescriptor() instanceof ClassDescriptor))
|
||||
cur = cur.getParentContext();
|
||||
|
||||
return cur == null ? null : Type.getObjectType(cur.getContextDescriptor().getName());
|
||||
return cur == null ? null : typeMapper.mapType(((ClassDescriptor)cur.getContextDescriptor()).getDefaultType());
|
||||
}
|
||||
|
||||
public int getTypeInfoConstantIndex(JetType type) {
|
||||
@@ -290,8 +290,8 @@ public abstract class CodegenContext {
|
||||
return getParentContext().lookupInContext(d, v, result);
|
||||
}
|
||||
|
||||
public Type enclosingClassType() {
|
||||
return getParentContext().enclosingClassType();
|
||||
public Type enclosingClassType(JetTypeMapper typeMapper) {
|
||||
return getParentContext().enclosingClassType(typeMapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -305,10 +305,10 @@ public abstract class CodegenContext {
|
||||
}
|
||||
|
||||
public static class ConstructorContext extends MethodContext {
|
||||
public ConstructorContext(ConstructorDescriptor contextType, OwnerKind kind, CodegenContext parent) {
|
||||
public ConstructorContext(ConstructorDescriptor contextType, OwnerKind kind, CodegenContext parent, JetTypeMapper typeMapper) {
|
||||
super(contextType, kind, parent);
|
||||
|
||||
final Type type = enclosingClassType();
|
||||
final Type type = enclosingClassType(typeMapper);
|
||||
outerExpression = type != null
|
||||
? local1
|
||||
: null;
|
||||
@@ -323,7 +323,7 @@ public abstract class CodegenContext {
|
||||
public ClassContext(ClassDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, JetTypeMapper typeMapper) {
|
||||
super(contextType, contextKind, parentContext, null);
|
||||
|
||||
final Type type = enclosingClassType();
|
||||
final Type type = enclosingClassType(typeMapper);
|
||||
outerExpression = type != null
|
||||
? StackValue.field(type, typeMapper.getFQName(contextType), "this$0", false)
|
||||
: null;
|
||||
@@ -341,10 +341,10 @@ public abstract class CodegenContext {
|
||||
}
|
||||
|
||||
public static class AnonymousClassContext extends CodegenContext {
|
||||
public AnonymousClassContext(ClassDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, @NotNull ObjectOrClosureCodegen closure) {
|
||||
public AnonymousClassContext(ClassDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, @NotNull ObjectOrClosureCodegen closure, JetTypeMapper typeMapper) {
|
||||
super(contextType, contextKind, parentContext, closure);
|
||||
|
||||
final Type type = enclosingClassType();
|
||||
final Type type = enclosingClassType(typeMapper);
|
||||
outerExpression = type != null
|
||||
? StackValue.field(type, closure.state.getTypeMapper().mapType(contextType.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "this$0", false)
|
||||
: null;
|
||||
@@ -364,11 +364,11 @@ public abstract class CodegenContext {
|
||||
public static class ClosureContext extends ReceiverContext {
|
||||
private ClassDescriptor classDescriptor;
|
||||
|
||||
public ClosureContext(FunctionDescriptor contextType, ClassDescriptor classDescriptor, CodegenContext parentContext, @NotNull ObjectOrClosureCodegen closureCodegen, String internalClassName) {
|
||||
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();
|
||||
final Type type = enclosingClassType(typeMapper);
|
||||
outerExpression = type != null
|
||||
? StackValue.field(type, internalClassName, "this$0", false)
|
||||
: null;
|
||||
|
||||
@@ -1958,26 +1958,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
} else {
|
||||
ClassDescriptor classDecl = (ClassDescriptor) constructorDescriptor.getContainingDeclaration();
|
||||
|
||||
receiver.put(receiver.type, v);
|
||||
v.anew(type);
|
||||
v.dup();
|
||||
|
||||
// TODO typechecker must verify that we're the outer class of the instance being created
|
||||
//noinspection ConstantConditions
|
||||
if (classDecl.getContainingDeclaration() instanceof ClassDescriptor) {
|
||||
if(!receiver.type.equals(Type.VOID_TYPE)) {
|
||||
// class object is in receiver
|
||||
v.dupX1();
|
||||
v.swap();
|
||||
}
|
||||
else {
|
||||
// this$0 need to be put on stack
|
||||
v.dup();
|
||||
v.load(0, typeMapper.mapType(classDecl.getDefaultType(), OwnerKind.IMPLEMENTATION));
|
||||
}
|
||||
}
|
||||
else {
|
||||
// regular case
|
||||
v.dup();
|
||||
if(!receiver.type.equals(Type.VOID_TYPE)) {
|
||||
receiver.put(receiver.type, v);
|
||||
}
|
||||
|
||||
CallableMethod method = typeMapper.mapToCallableMethod((ConstructorDescriptor) constructorDescriptor, OwnerKind.IMPLEMENTATION);
|
||||
|
||||
@@ -106,7 +106,7 @@ public class FunctionCodegen {
|
||||
for(int i = 0; i != paramDescrs.size(); ++i) {
|
||||
AnnotationVisitor av = mv.visitParameterAnnotation(i + start, "Ljet/typeinfo/JetParameter;", true);
|
||||
ValueParameterDescriptor parameterDescriptor = paramDescrs.get(i);
|
||||
av.visit("value", parameterDescriptor.getName());
|
||||
av.visit("name", parameterDescriptor.getName());
|
||||
if(parameterDescriptor.hasDefaultValue()) {
|
||||
av.visit("hasDefaultValue", true);
|
||||
}
|
||||
|
||||
@@ -82,11 +82,12 @@ public class GenerationState {
|
||||
return factory.forNamespace(namespace);
|
||||
}
|
||||
|
||||
public void compile(JetFile psiFile) {
|
||||
public BindingContext compile(JetFile psiFile) {
|
||||
final JetNamespace namespace = psiFile.getRootNamespace();
|
||||
final BindingContext bindingContext = AnalyzerFacade.analyzeOneNamespaceWithJavaIntegration(namespace, JetControlFlowDataTraceFactory.EMPTY);
|
||||
AnalyzingUtils.throwExceptionOnErrors(bindingContext);
|
||||
compileCorrectNamespaces(bindingContext, Collections.singletonList(namespace));
|
||||
return bindingContext;
|
||||
// NamespaceCodegen codegen = forNamespace(namespace);
|
||||
// bindingContexts.push(bindingContext);
|
||||
// typeMapper = new JetTypeMapper(standardLibrary, bindingContext);
|
||||
@@ -139,7 +140,7 @@ public class GenerationState {
|
||||
|
||||
closure.cv = nameAndVisitor.getSecond();
|
||||
closure.name = nameAndVisitor.getFirst();
|
||||
final CodegenContext objectContext = closure.context.intoAnonymousClass(closure, getBindingContext().get(BindingContext.CLASS, objectDeclaration), OwnerKind.IMPLEMENTATION);
|
||||
final CodegenContext objectContext = closure.context.intoAnonymousClass(closure, getBindingContext().get(BindingContext.CLASS, objectDeclaration), OwnerKind.IMPLEMENTATION, typeMapper);
|
||||
|
||||
new ImplementationBodyCodegen(objectDeclaration, objectContext, nameAndVisitor.getSecond(), this).generate(null);
|
||||
|
||||
|
||||
@@ -267,7 +267,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, myClass);
|
||||
|
||||
CodegenContext.ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor);
|
||||
CodegenContext.ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor, typeMapper);
|
||||
|
||||
Method constructorMethod;
|
||||
CallableMethod callableMethod;
|
||||
|
||||
@@ -24,20 +24,38 @@ public class Increment implements IntrinsicMethod {
|
||||
|
||||
@Override
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||
JetExpression operand = arguments.get(0);
|
||||
while(operand instanceof JetParenthesizedExpression) {
|
||||
operand = ((JetParenthesizedExpression)operand).getExpression();
|
||||
boolean nullable = expectedType.getSort() == Type.OBJECT;
|
||||
if(nullable) {
|
||||
expectedType = JetTypeMapper.unboxType(expectedType);
|
||||
}
|
||||
if (operand instanceof JetReferenceExpression) {
|
||||
final int index = codegen.indexOfLocal((JetReferenceExpression) operand);
|
||||
if (index >= 0 && JetTypeMapper.isIntPrimitive(expectedType)) {
|
||||
return StackValue.preIncrement(index, myDelta);
|
||||
if(arguments.size() > 0) {
|
||||
JetExpression operand = arguments.get(0);
|
||||
while(operand instanceof JetParenthesizedExpression) {
|
||||
operand = ((JetParenthesizedExpression)operand).getExpression();
|
||||
}
|
||||
if (operand instanceof JetReferenceExpression) {
|
||||
final int index = codegen.indexOfLocal((JetReferenceExpression) operand);
|
||||
if (index >= 0 && JetTypeMapper.isIntPrimitive(expectedType)) {
|
||||
return StackValue.preIncrement(index, myDelta);
|
||||
}
|
||||
}
|
||||
StackValue value = codegen.genQualified(receiver, operand);
|
||||
value. dupReceiver(v);
|
||||
value. dupReceiver(v);
|
||||
|
||||
value.put(expectedType, v);
|
||||
plusMinus(v, expectedType);
|
||||
value.store(v);
|
||||
value.put(expectedType, v);
|
||||
}
|
||||
StackValue value = codegen.genQualified(receiver, operand);
|
||||
value. dupReceiver(v);
|
||||
value. dupReceiver(v);
|
||||
value.put(expectedType, v);
|
||||
else {
|
||||
receiver.put(expectedType, v);
|
||||
plusMinus(v, expectedType);
|
||||
}
|
||||
return StackValue.onStack(expectedType);
|
||||
}
|
||||
|
||||
private void plusMinus(InstructionAdapter v, Type expectedType) {
|
||||
if (expectedType == Type.LONG_TYPE) {
|
||||
v.lconst(myDelta);
|
||||
}
|
||||
@@ -51,8 +69,5 @@ public class Increment implements IntrinsicMethod {
|
||||
v.iconst(myDelta);
|
||||
}
|
||||
v.add(expectedType);
|
||||
value.store(v);
|
||||
value.put(expectedType, v);
|
||||
return StackValue.onStack(expectedType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.util.*;
|
||||
*/
|
||||
public class IntrinsicMethods {
|
||||
private static final IntrinsicMethod UNARY_MINUS = new UnaryMinus();
|
||||
private static final IntrinsicMethod UNARY_PLUS = new UnaryPlus();
|
||||
private static final IntrinsicMethod NUMBER_CAST = new NumberCast();
|
||||
private static final IntrinsicMethod INV = new Inv();
|
||||
private static final IntrinsicMethod TYPEINFO = new TypeInfo();
|
||||
@@ -53,6 +54,7 @@ public class IntrinsicMethods {
|
||||
}
|
||||
|
||||
for (String type : PRIMITIVE_NUMBER_TYPES) {
|
||||
declareIntrinsicFunction(type, "plus", 0, UNARY_PLUS);
|
||||
declareIntrinsicFunction(type, "minus", 0, UNARY_MINUS);
|
||||
declareIntrinsicFunction(type, "inv", 0, INV);
|
||||
declareIntrinsicFunction(type, "rangeTo", 1, RANGE_TO);
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.jetbrains.jet.codegen.intrinsics;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.jet.codegen.ExpressionCodegen;
|
||||
import org.jetbrains.jet.codegen.JetTypeMapper;
|
||||
import org.jetbrains.jet.codegen.StackValue;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.objectweb.asm.Type;
|
||||
@@ -11,12 +12,22 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
public class Inv implements IntrinsicMethod {
|
||||
@Override
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||
boolean nullable = expectedType.getSort() == Type.OBJECT;
|
||||
if(nullable) {
|
||||
expectedType = JetTypeMapper.unboxType(expectedType);
|
||||
}
|
||||
receiver.put(expectedType, v);
|
||||
v.iconst(-1);
|
||||
if(expectedType == Type.LONG_TYPE) {
|
||||
v.lconst(-1L);
|
||||
}
|
||||
else {
|
||||
v.iconst(-1);
|
||||
}
|
||||
v.xor(expectedType);
|
||||
return StackValue.onStack(expectedType);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.jetbrains.jet.codegen.intrinsics;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.jet.codegen.ExpressionCodegen;
|
||||
import org.jetbrains.jet.codegen.JetTypeMapper;
|
||||
import org.jetbrains.jet.codegen.StackValue;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.objectweb.asm.Type;
|
||||
@@ -15,6 +16,10 @@ import java.util.List;
|
||||
public class UnaryMinus implements IntrinsicMethod {
|
||||
@Override
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||
boolean nullable = expectedType.getSort() == Type.OBJECT;
|
||||
if(nullable) {
|
||||
expectedType = JetTypeMapper.unboxType(expectedType);
|
||||
}
|
||||
if (arguments.size() == 1) {
|
||||
codegen.gen(arguments.get(0), expectedType);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package org.jetbrains.jet.codegen.intrinsics;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.codegen.ExpressionCodegen;
|
||||
import org.jetbrains.jet.codegen.JetTypeMapper;
|
||||
import org.jetbrains.jet.codegen.StackValue;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
public class UnaryPlus implements IntrinsicMethod {
|
||||
@Override
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, @Nullable PsiElement element, @Nullable List<JetExpression> arguments, StackValue receiver) {
|
||||
boolean nullable = expectedType.getSort() == Type.OBJECT;
|
||||
if(nullable) {
|
||||
expectedType = JetTypeMapper.unboxType(expectedType);
|
||||
}
|
||||
receiver.put(expectedType, v);
|
||||
return StackValue.onStack(expectedType);
|
||||
}
|
||||
}
|
||||
@@ -356,7 +356,7 @@ public class CompileEnvironment {
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeToOutputDirectory(ClassFileFactory factory, final String outputDir) {
|
||||
public static void writeToOutputDirectory(ClassFileFactory factory, final String outputDir) {
|
||||
List<String> files = factory.files();
|
||||
for (String file : files) {
|
||||
if(!skipFile(file)) {
|
||||
|
||||
+57
-5
@@ -267,7 +267,7 @@ public class JavaDescriptorResolver {
|
||||
return javaFacade.findClass(qualifiedName, javaSearchScope);
|
||||
}
|
||||
|
||||
private PsiPackage findPackage(String qualifiedName) {
|
||||
/*package*/ PsiPackage findPackage(String qualifiedName) {
|
||||
return javaFacade.findPackage(qualifiedName);
|
||||
}
|
||||
|
||||
@@ -332,7 +332,6 @@ public class JavaDescriptorResolver {
|
||||
}
|
||||
|
||||
private ValueParameterDescriptor resolveParameterDescriptor(DeclarationDescriptor containingDeclaration, int i, PsiParameter parameter) {
|
||||
String name = parameter.getName();
|
||||
PsiType psiType = parameter.getType();
|
||||
|
||||
JetType varargElementType;
|
||||
@@ -343,14 +342,43 @@ public class JavaDescriptorResolver {
|
||||
else {
|
||||
varargElementType = null;
|
||||
}
|
||||
|
||||
boolean changeNullable = false;
|
||||
boolean nullable = true;
|
||||
|
||||
// TODO: must be very slow, make it lazy?
|
||||
String name = parameter.getName() != null ? parameter.getName() : "p" + i;
|
||||
for (PsiAnnotation annotation : parameter.getModifierList().getAnnotations()) {
|
||||
// TODO: softcode annotation name
|
||||
|
||||
PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes();
|
||||
attributes.toString();
|
||||
|
||||
if (annotation.getQualifiedName().equals("jet.typeinfo.JetParameter")) {
|
||||
PsiLiteralExpression nameExpression = (PsiLiteralExpression) annotation.findAttributeValue("name");
|
||||
if (nameExpression != null) {
|
||||
name = (String) nameExpression.getValue();
|
||||
}
|
||||
|
||||
PsiLiteralExpression nullableExpression = (PsiLiteralExpression) annotation.findAttributeValue("nullable");
|
||||
if (nullableExpression != null) {
|
||||
nullable = (Boolean) nullableExpression.getValue();
|
||||
} else {
|
||||
// default value of parameter
|
||||
nullable = false;
|
||||
changeNullable = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JetType outType = semanticServices.getTypeTransformer().transformToType(psiType);
|
||||
return new ValueParameterDescriptorImpl(
|
||||
containingDeclaration,
|
||||
i,
|
||||
Collections.<AnnotationDescriptor>emptyList(), // TODO
|
||||
name == null ? "p" + i : name,
|
||||
name,
|
||||
null, // TODO : review
|
||||
outType,
|
||||
changeNullable ? TypeUtils.makeNullableAsSpecified(outType, nullable) : outType,
|
||||
false,
|
||||
varargElementType
|
||||
);
|
||||
@@ -451,7 +479,7 @@ public class JavaDescriptorResolver {
|
||||
DescriptorUtils.getExpectedThisObjectIfNeeded(classDescriptor),
|
||||
typeParameters,
|
||||
semanticServices.getDescriptorResolver().resolveParameterDescriptors(functionDescriptorImpl, parameters),
|
||||
semanticServices.getTypeTransformer().transformToType(returnType),
|
||||
semanticServices.getDescriptorResolver().makeReturnType(returnType, method),
|
||||
Modality.convertFromFlags(method.hasModifierProperty(PsiModifier.ABSTRACT), !method.hasModifierProperty(PsiModifier.FINAL)),
|
||||
resolveVisibilityFromPsiModifiers(method)
|
||||
);
|
||||
@@ -463,6 +491,30 @@ public class JavaDescriptorResolver {
|
||||
return substitutedFunctionDescriptor;
|
||||
}
|
||||
|
||||
private JetType makeReturnType(PsiType returnType, PsiMethod method) {
|
||||
boolean changeNullable = false;
|
||||
boolean nullable = true;
|
||||
|
||||
for (PsiAnnotation annotation : method.getModifierList().getAnnotations()) {
|
||||
if (annotation.getQualifiedName().equals("jet.typeinfo.JetMethod")) {
|
||||
PsiLiteralExpression nullableExpression = (PsiLiteralExpression) annotation.findAttributeValue("nullableReturnType");
|
||||
if (nullableExpression != null) {
|
||||
nullable = (Boolean) nullableExpression.getValue();
|
||||
} else {
|
||||
// default value of parameter
|
||||
nullable = false;
|
||||
changeNullable = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
JetType transformedType = semanticServices.getTypeTransformer().transformToType(returnType);
|
||||
if (changeNullable) {
|
||||
return TypeUtils.makeNullableAsSpecified(transformedType, nullable);
|
||||
} else {
|
||||
return transformedType;
|
||||
}
|
||||
}
|
||||
|
||||
private static Visibility resolveVisibilityFromPsiModifiers(PsiModifierListOwner modifierListOwner) {
|
||||
//TODO report error
|
||||
return modifierListOwner.hasModifierProperty(PsiModifier.PUBLIC) ? Visibility.PUBLIC :
|
||||
|
||||
+54
-6
@@ -1,9 +1,17 @@
|
||||
package org.jetbrains.jet.lang.resolve.java;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiModifier;
|
||||
import com.intellij.psi.PsiPackage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScopeImpl;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -13,11 +21,13 @@ import java.util.Set;
|
||||
public class JavaPackageScope extends JetScopeImpl {
|
||||
private final JavaSemanticServices semanticServices;
|
||||
private final DeclarationDescriptor containingDescriptor;
|
||||
private final String packagePrefix;
|
||||
private final String packageFQN;
|
||||
|
||||
private Collection<DeclarationDescriptor> allDescriptors;
|
||||
|
||||
public JavaPackageScope(@NotNull String packageFQN, DeclarationDescriptor containingDescriptor, JavaSemanticServices semanticServices) {
|
||||
this.semanticServices = semanticServices;
|
||||
this.packagePrefix = packageFQN.isEmpty() ? "" : packageFQN + ".";
|
||||
this.packageFQN = packageFQN;
|
||||
this.containingDescriptor = containingDescriptor;
|
||||
}
|
||||
|
||||
@@ -34,7 +44,17 @@ public class JavaPackageScope extends JetScopeImpl {
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<FunctionDescriptor> getFunctions(@NotNull String name) {
|
||||
return Collections.emptySet();
|
||||
// TODO: what is GlobalSearchScope
|
||||
PsiClass psiClass = semanticServices.getDescriptorResolver().javaFacade.findClass(getQualifiedName("namespace"));
|
||||
if (psiClass == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
if (containingDescriptor == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
return semanticServices.getDescriptorResolver().resolveFunctionGroup(containingDescriptor, psiClass, null, name, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -43,7 +63,35 @@ public class JavaPackageScope extends JetScopeImpl {
|
||||
return containingDescriptor;
|
||||
}
|
||||
|
||||
private String getQualifiedName(String name) {
|
||||
return packagePrefix + name;
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<DeclarationDescriptor> getAllDescriptors() {
|
||||
if (allDescriptors == null) {
|
||||
allDescriptors = Sets.newHashSet();
|
||||
|
||||
final PsiPackage javaPackage = semanticServices.getDescriptorResolver().findPackage(packageFQN);
|
||||
|
||||
if (javaPackage != null) {
|
||||
final JavaDescriptorResolver descriptorResolver = semanticServices.getDescriptorResolver();
|
||||
|
||||
for (PsiPackage psiSubPackage : javaPackage.getSubPackages()) {
|
||||
allDescriptors.add(descriptorResolver.resolveNamespace(psiSubPackage.getQualifiedName()));
|
||||
}
|
||||
|
||||
for (PsiClass psiClass : javaPackage.getClasses()) {
|
||||
if (psiClass.hasModifierProperty(PsiModifier.PUBLIC)) {
|
||||
allDescriptors.add(descriptorResolver.resolveClass(psiClass));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return allDescriptors;
|
||||
}
|
||||
|
||||
private String getQualifiedName(String name) {
|
||||
return (packageFQN.isEmpty() ? "" : packageFQN + ".") + name;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.jet;
|
||||
|
||||
import com.intellij.core.JavaCoreEnvironment;
|
||||
import com.intellij.lang.java.JavaParserDefinition;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import org.jetbrains.jet.lang.parsing.JetParserDefinition;
|
||||
import org.jetbrains.jet.plugin.JetFileType;
|
||||
@@ -15,6 +16,7 @@ public class JetCoreEnvironment extends JavaCoreEnvironment {
|
||||
registerFileType(JetFileType.INSTANCE, "kts");
|
||||
registerFileType(JetFileType.INSTANCE, "ktm");
|
||||
registerFileType(JetFileType.INSTANCE, "jet");
|
||||
registerParserDefinition(new JavaParserDefinition());
|
||||
registerParserDefinition(new JetParserDefinition());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -820,6 +820,9 @@ public class JetControlFlowProcessor {
|
||||
}
|
||||
|
||||
private void visitClassOrObject(JetClassOrObject classOrObject) {
|
||||
for (JetDelegationSpecifier specifier : classOrObject.getDelegationSpecifiers()) {
|
||||
value(specifier, inCondition);
|
||||
}
|
||||
List<JetDeclaration> declarations = classOrObject.getDeclarations();
|
||||
List<JetProperty> properties = Lists.newArrayList();
|
||||
for (JetDeclaration declaration : declarations) {
|
||||
@@ -838,6 +841,14 @@ public class JetControlFlowProcessor {
|
||||
visitClassOrObject(klass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call) {
|
||||
List<? extends ValueArgument> valueArguments = call.getValueArguments();
|
||||
for (ValueArgument valueArgument : valueArguments) {
|
||||
value(valueArgument.getArgumentExpression(), inCondition);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJetElement(JetElement element) {
|
||||
builder.unsupported(element);
|
||||
|
||||
@@ -6,11 +6,11 @@ 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.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||
import org.jetbrains.jet.lang.diagnostics.Errors;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
@@ -223,22 +223,24 @@ public class JetFlowInformationProvider {
|
||||
@Override
|
||||
public void execute(Instruction instruction, @Nullable Map<VariableDescriptor, VariableInitializers> enterData, @Nullable Map<VariableDescriptor, VariableInitializers> exitData) {
|
||||
assert enterData != null && exitData != null;
|
||||
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, true);
|
||||
if (variableDescriptor == null) return;
|
||||
if (instruction instanceof ReadValueInstruction) {
|
||||
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, false);
|
||||
if (variableDescriptor != null && declaredVariables.contains(variableDescriptor)) {
|
||||
checkIsInitialized(variableDescriptor, ((ReadValueInstruction) instruction).getElement(), exitData.get(variableDescriptor), varWithUninitializedErrorGenerated);
|
||||
JetElement element = ((ReadValueInstruction) instruction).getElement();
|
||||
boolean error = checkBackingField(variableDescriptor, element);
|
||||
if (!error && declaredVariables.contains(variableDescriptor)) {
|
||||
checkIsInitialized(variableDescriptor, element, exitData.get(variableDescriptor), varWithUninitializedErrorGenerated);
|
||||
}
|
||||
}
|
||||
else if (instruction instanceof WriteValueInstruction) {
|
||||
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, true);
|
||||
JetElement element = ((WriteValueInstruction) instruction).getlValue();
|
||||
if (variableDescriptor != null && element instanceof JetExpression) {
|
||||
if (!processLocalDeclaration) { // error has been generated before while processing outer function of this local declaration
|
||||
checkValReassignment(variableDescriptor, (JetExpression) element, enterData.get(variableDescriptor), varWithValReassignErrorGenerated);
|
||||
}
|
||||
if (processClassOrObject) {
|
||||
checkInitializationUsingBackingField(variableDescriptor, (JetExpression) element, enterData.get(variableDescriptor), exitData.get(variableDescriptor));
|
||||
}
|
||||
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) {
|
||||
checkInitializationUsingBackingField(variableDescriptor, (JetExpression) element, enterData.get(variableDescriptor), exitData.get(variableDescriptor));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -263,7 +265,7 @@ public class JetFlowInformationProvider {
|
||||
}
|
||||
}
|
||||
|
||||
private void checkValReassignment(@NotNull VariableDescriptor variableDescriptor, @NotNull JetExpression expression, @NotNull VariableInitializers enterInitializers, @NotNull Collection<VariableDescriptor> varWithValReassignErrorGenerated) {
|
||||
private boolean checkValReassignment(@NotNull VariableDescriptor variableDescriptor, @NotNull JetExpression expression, @NotNull VariableInitializers enterInitializers, @NotNull Collection<VariableDescriptor> varWithValReassignErrorGenerated) {
|
||||
boolean isInitializedNotHere = enterInitializers.isInitialized();
|
||||
Set<JetElement> possibleLocalInitializers = enterInitializers.getPossibleLocalInitializers();
|
||||
if (possibleLocalInitializers.size() == 1) {
|
||||
@@ -298,12 +300,19 @@ public class JetFlowInformationProvider {
|
||||
}
|
||||
if (!hasReassignMethodReturningUnit) {
|
||||
trace.report(Errors.VAL_REASSIGNMENT.on(expression, variableDescriptor));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void checkInitializationUsingBackingField(@NotNull VariableDescriptor variableDescriptor, @NotNull JetExpression expression, @NotNull VariableInitializers enterInitializers, @NotNull VariableInitializers exitInitializers) {
|
||||
if (variableDescriptor instanceof PropertyDescriptor && !enterInitializers.isInitialized() && exitInitializers.isInitialized()) {
|
||||
if (!variableDescriptor.isVar()) return;
|
||||
if (!trace.get(BindingContext.BACKING_FIELD_REQUIRED, (PropertyDescriptor) variableDescriptor)) return;
|
||||
PsiElement property = trace.get(BindingContext.DESCRIPTOR_TO_DECLARATION, variableDescriptor);
|
||||
assert property instanceof JetProperty;
|
||||
if (((PropertyDescriptor) variableDescriptor).getModality() == Modality.FINAL && ((JetProperty) property).getSetter() == null) return;
|
||||
JetExpression variable = expression;
|
||||
if (expression instanceof JetDotQualifiedExpression) {
|
||||
if (((JetDotQualifiedExpression) expression).getReceiverExpression() instanceof JetThisExpression) {
|
||||
@@ -313,12 +322,63 @@ public class JetFlowInformationProvider {
|
||||
if (variable instanceof JetSimpleNameExpression) {
|
||||
JetSimpleNameExpression simpleNameExpression = (JetSimpleNameExpression) variable;
|
||||
if (simpleNameExpression.getReferencedNameElementType() != JetTokens.FIELD_IDENTIFIER) {
|
||||
trace.report(Errors.INITIALIZATION_USING_BACKING_FIELD.on(simpleNameExpression, expression, variableDescriptor));
|
||||
if (((PropertyDescriptor) variableDescriptor).getModality() != Modality.FINAL) {
|
||||
trace.report(Errors.INITIALIZATION_USING_BACKING_FIELD_OPEN_SETTER.on(simpleNameExpression, expression, variableDescriptor));
|
||||
}
|
||||
else {
|
||||
trace.report(Errors.INITIALIZATION_USING_BACKING_FIELD_CUSTOM_SETTER.on(simpleNameExpression, expression, variableDescriptor));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkBackingField(@NotNull VariableDescriptor variableDescriptor, @NotNull JetElement element) {
|
||||
boolean[] error = new boolean[1];
|
||||
if (isBackingFieldReference((JetElement) element.getParent(), error, false)) return false; // this expression has been already checked
|
||||
if (!isBackingFieldReference(element, error, true)) return false;
|
||||
if (error[0]) return true;
|
||||
if (!(variableDescriptor instanceof PropertyDescriptor)) {
|
||||
trace.report(Errors.NOT_PROPERTY_BACKING_FIELD.on(element));
|
||||
return true;
|
||||
}
|
||||
PsiElement property = trace.get(BindingContext.DESCRIPTOR_TO_DECLARATION, variableDescriptor);
|
||||
if (!trace.get(BindingContext.BACKING_FIELD_REQUIRED, (PropertyDescriptor) variableDescriptor) &&
|
||||
!PsiTreeUtil.isAncestor(property, element, false)) { // 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));
|
||||
}
|
||||
else {
|
||||
trace.report(NO_BACKING_FIELD_CUSTOM_ACCESSORS.on(element));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
JetClassOrObject propertyClassOrObject = PsiTreeUtil.getParentOfType(property, JetClassOrObject.class);
|
||||
if (propertyClassOrObject == null || !PsiTreeUtil.isAncestor(propertyClassOrObject, element, false)) {
|
||||
trace.report(Errors.INACCESSIBLE_BACKING_FIELD.on(element));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isBackingFieldReference(@Nullable JetElement element, boolean[] error, boolean reportError) {
|
||||
error[0] = false;
|
||||
if (element instanceof JetSimpleNameExpression && ((JetSimpleNameExpression) element).getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
|
||||
return true;
|
||||
}
|
||||
if (element instanceof JetDotQualifiedExpression && isBackingFieldReference(((JetDotQualifiedExpression) element).getSelectorExpression(), error, false)) {
|
||||
if (((JetDotQualifiedExpression) element).getReceiverExpression() instanceof JetThisExpression) {
|
||||
return true;
|
||||
}
|
||||
error[0] = true;
|
||||
if (reportError) {
|
||||
trace.report(Errors.INACCESSIBLE_BACKING_FIELD.on(element));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void recordInitializedVariables(Collection<VariableDescriptor> declaredVariables, Map<VariableDescriptor, VariableInitializers> resultInfo) {
|
||||
for (Map.Entry<VariableDescriptor, VariableInitializers> entry : resultInfo.entrySet()) {
|
||||
VariableDescriptor variable = entry.getKey();
|
||||
@@ -456,58 +516,55 @@ public class JetFlowInformationProvider {
|
||||
public void execute(Instruction instruction, @Nullable Map<VariableDescriptor, VariableStatus> enterData, @Nullable Map<VariableDescriptor, VariableStatus> exitData) {
|
||||
assert enterData != null && exitData != null;
|
||||
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, false);
|
||||
if (variableDescriptor != null && declaredVariables.contains(variableDescriptor)) {
|
||||
PsiElement variableDeclarationElement = trace.get(BindingContext.DESCRIPTOR_TO_DECLARATION, variableDescriptor);
|
||||
assert variableDeclarationElement instanceof JetDeclaration;
|
||||
boolean isLocal = JetPsiUtil.isLocal((JetDeclaration) variableDeclarationElement);
|
||||
if (isLocal) {
|
||||
if (instruction instanceof WriteValueInstruction) {
|
||||
JetElement element = ((WriteValueInstruction) instruction).getElement();
|
||||
if (enterData.get(variableDescriptor) == VariableStatus.WRITTEN || enterData.get(variableDescriptor) == VariableStatus.UNUSED) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
else if (element instanceof JetPostfixExpression) {
|
||||
IElementType operationToken = ((JetPostfixExpression) element).getOperationReference().getReferencedNameElementType();
|
||||
if (operationToken == JetTokens.PLUSPLUS || operationToken == JetTokens.MINUSMINUS) {
|
||||
trace.report(Errors.UNUSED_CHANGED_VALUE.on(element, element));
|
||||
}
|
||||
}
|
||||
if (variableDescriptor == null || !declaredVariables.contains(variableDescriptor)) return;
|
||||
PsiElement variableDeclarationElement = trace.get(BindingContext.DESCRIPTOR_TO_DECLARATION, variableDescriptor);
|
||||
assert variableDeclarationElement instanceof JetDeclaration;
|
||||
if (!JetPsiUtil.isLocal((JetDeclaration) variableDeclarationElement)) return;
|
||||
if (instruction instanceof WriteValueInstruction) {
|
||||
JetElement element = ((WriteValueInstruction) instruction).getElement();
|
||||
if (enterData.get(variableDescriptor) == VariableStatus.WRITTEN || enterData.get(variableDescriptor) == VariableStatus.UNUSED) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
else if (instruction instanceof VariableDeclarationInstruction) {
|
||||
JetDeclaration element = ((VariableDeclarationInstruction) instruction).getVariableDeclarationElement();
|
||||
if (element instanceof JetNamedDeclaration) {
|
||||
PsiElement nameIdentifier = ((JetNamedDeclaration) element).getNameIdentifier();
|
||||
PsiElement elementToMark = nameIdentifier != null ? nameIdentifier : element;
|
||||
if (enterData.get(variableDescriptor) == VariableStatus.UNUSED) {
|
||||
if (element instanceof JetProperty) {
|
||||
trace.report(Errors.UNUSED_VARIABLE.on((JetProperty) element, elementToMark, variableDescriptor));
|
||||
}
|
||||
else if (element instanceof JetParameter) {
|
||||
PsiElement psiElement = element.getParent().getParent();
|
||||
if (psiElement instanceof JetFunction) {
|
||||
boolean isMain = (psiElement instanceof JetNamedFunction) && JetMainDetector.isMain((JetNamedFunction) psiElement);
|
||||
DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, psiElement);
|
||||
assert descriptor instanceof FunctionDescriptor;
|
||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
|
||||
if (!isMain && !functionDescriptor.getModality().isOverridable() && functionDescriptor.getOverriddenDescriptors().isEmpty()) {
|
||||
trace.report(Errors.UNUSED_PARAMETER.on((JetParameter) element, elementToMark, variableDescriptor));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (enterData.get(variableDescriptor) == VariableStatus.WRITTEN && element instanceof JetProperty) {
|
||||
trace.report(Errors.ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE.on((JetNamedDeclaration) element, elementToMark, variableDescriptor));
|
||||
}
|
||||
}
|
||||
else if (element instanceof JetPostfixExpression) {
|
||||
IElementType operationToken = ((JetPostfixExpression) element).getOperationReference().getReferencedNameElementType();
|
||||
if (operationToken == JetTokens.PLUSPLUS || operationToken == JetTokens.MINUSMINUS) {
|
||||
trace.report(Errors.UNUSED_CHANGED_VALUE.on(element, element));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (instruction instanceof VariableDeclarationInstruction) {
|
||||
JetDeclaration element = ((VariableDeclarationInstruction) instruction).getVariableDeclarationElement();
|
||||
if (element instanceof JetNamedDeclaration) {
|
||||
PsiElement nameIdentifier = ((JetNamedDeclaration) element).getNameIdentifier();
|
||||
PsiElement elementToMark = nameIdentifier != null ? nameIdentifier : element;
|
||||
if (enterData.get(variableDescriptor) == VariableStatus.UNUSED) {
|
||||
if (element instanceof JetProperty) {
|
||||
trace.report(Errors.UNUSED_VARIABLE.on((JetProperty) element, elementToMark, variableDescriptor));
|
||||
}
|
||||
else if (element instanceof JetParameter) {
|
||||
PsiElement psiElement = element.getParent().getParent();
|
||||
if (psiElement instanceof JetFunction) {
|
||||
boolean isMain = (psiElement instanceof JetNamedFunction) && JetMainDetector.isMain((JetNamedFunction) psiElement);
|
||||
DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, psiElement);
|
||||
assert descriptor instanceof FunctionDescriptor;
|
||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
|
||||
if (!isMain && !functionDescriptor.getModality().isOverridable() && functionDescriptor.getOverriddenDescriptors().isEmpty()) {
|
||||
trace.report(Errors.UNUSED_PARAMETER.on((JetParameter) element, elementToMark, variableDescriptor));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (enterData.get(variableDescriptor) == VariableStatus.WRITTEN && element instanceof JetProperty) {
|
||||
trace.report(Errors.ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE.on((JetNamedDeclaration) element, elementToMark, variableDescriptor));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+1
-2
@@ -62,7 +62,7 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
|
||||
this.scopeForMemberLookup = new WritableScopeImpl(JetScope.EMPTY, this, redeclarationHandler).setDebugName("MemberLookup").changeLockLevel(WritableScope.LockLevel.BOTH);
|
||||
this.scopeForSupertypeResolution = new WritableScopeImpl(outerScope, this, redeclarationHandler).setDebugName("SupertypeResolution").changeLockLevel(WritableScope.LockLevel.BOTH);
|
||||
this.scopeForMemberResolution = new WritableScopeImpl(scopeForSupertypeResolution, this, redeclarationHandler).setDebugName("MemberResolution").changeLockLevel(WritableScope.LockLevel.BOTH);
|
||||
this.scopeForInitializers = new WritableScopeImpl(scopeForMemberResolution, this, redeclarationHandler).setDebugName("PropertyInitializers").changeLockLevel(WritableScope.LockLevel.BOTH);
|
||||
this.scopeForInitializers = new WritableScopeImpl(scopeForMemberResolution, this, redeclarationHandler).setDebugName("Initializers").changeLockLevel(WritableScope.LockLevel.BOTH);
|
||||
this.kind = kind;
|
||||
}
|
||||
|
||||
@@ -147,7 +147,6 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
|
||||
callableMembers.add(propertyDescriptor);
|
||||
scopeForMemberLookup.addVariableDescriptor(propertyDescriptor);
|
||||
scopeForMemberResolution.addVariableDescriptor(propertyDescriptor);
|
||||
scopeForInitializers.addPropertyDescriptorByFieldName("$" + propertyDescriptor.getName(), propertyDescriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -84,7 +84,11 @@ public interface Errors {
|
||||
|
||||
SimpleDiagnosticFactory CANNOT_INFER_PARAMETER_TYPE = SimpleDiagnosticFactory.create(ERROR, "Cannot infer a type for this parameter. To specify it explicitly use the {(p : Type) => ...} notation");
|
||||
|
||||
SimpleDiagnosticFactory NO_BACKING_FIELD = SimpleDiagnosticFactory.create(ERROR, "This property does not have a backing field");
|
||||
SimpleDiagnosticFactory NO_BACKING_FIELD_ABSTRACT_PROPERTY = SimpleDiagnosticFactory.create(ERROR, "This property doesn't have a backing field, because it's abstract");
|
||||
SimpleDiagnosticFactory NO_BACKING_FIELD_CUSTOM_ACCESSORS = SimpleDiagnosticFactory.create(ERROR, "This property doesn't have a backing field, because it has custom accessors without reference to the backing field");
|
||||
SimpleDiagnosticFactory INACCESSIBLE_BACKING_FIELD = SimpleDiagnosticFactory.create(ERROR, "The backing field is not accessible here");
|
||||
SimpleDiagnosticFactory NOT_PROPERTY_BACKING_FIELD = SimpleDiagnosticFactory.create(ERROR, "The referenced variable is not a property and doesn't have backing field");
|
||||
|
||||
SimpleDiagnosticFactory MIXING_NAMED_AND_POSITIONED_ARGUMENTS = SimpleDiagnosticFactory.create(ERROR, "Mixing named and positioned arguments in not allowed");
|
||||
SimpleDiagnosticFactory ARGUMENT_PASSED_TWICE = SimpleDiagnosticFactory.create(ERROR, "An argument is already passed for this parameter");
|
||||
UnresolvedReferenceDiagnosticFactory NAMED_PARAMETER_NOT_FOUND = new UnresolvedReferenceDiagnosticFactory("Cannot find a parameter with this name");//SimpleDiagnosticFactory.create(ERROR, "Cannot find a parameter with this name");
|
||||
@@ -166,7 +170,8 @@ public interface Errors {
|
||||
PsiElementOnlyDiagnosticFactory1<JetExpression, DeclarationDescriptor> VAL_REASSIGNMENT = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Val can not be reassigned", NAME);
|
||||
SimplePsiElementOnlyDiagnosticFactory<JetExpression> VARIABLE_EXPECTED = new SimplePsiElementOnlyDiagnosticFactory<JetExpression>(ERROR, "Variable expected");
|
||||
|
||||
PsiElementOnlyDiagnosticFactory1<JetSimpleNameExpression, DeclarationDescriptor> INITIALIZATION_USING_BACKING_FIELD = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Initialization using backing field required", NAME);
|
||||
PsiElementOnlyDiagnosticFactory1<JetSimpleNameExpression, DeclarationDescriptor> INITIALIZATION_USING_BACKING_FIELD_CUSTOM_SETTER = PsiElementOnlyDiagnosticFactory1.create(ERROR, "This property has a custom setter, so initialization using backing field required", NAME);
|
||||
PsiElementOnlyDiagnosticFactory1<JetSimpleNameExpression, DeclarationDescriptor> INITIALIZATION_USING_BACKING_FIELD_OPEN_SETTER = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Setter of this property can be overridden, so initialization using backing field required", NAME);
|
||||
|
||||
PsiElementOnlyDiagnosticFactory1<JetSimpleNameExpression, DeclarationDescriptor> FUNCTION_PARAMETERS_OF_INLINE_FUNCTION = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Function parameters of inline function can only be invoked", NAME);
|
||||
|
||||
|
||||
@@ -104,9 +104,9 @@ public class JetPsiUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isLocal(@NotNull JetDeclaration declaration) {
|
||||
JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(declaration, JetClassOrObject.class);
|
||||
JetDeclarationWithBody function = PsiTreeUtil.getParentOfType(declaration, JetDeclarationWithBody.class);
|
||||
public static boolean isLocal(@NotNull JetElement element) {
|
||||
JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(element, JetClassOrObject.class);
|
||||
JetDeclarationWithBody function = PsiTreeUtil.getParentOfType(element, JetDeclarationWithBody.class);
|
||||
if (function != null && PsiTreeUtil.isAncestor(classOrObject, function, false)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -34,41 +34,11 @@ import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
|
||||
public class BodyResolver {
|
||||
private final TopDownAnalysisContext context;
|
||||
|
||||
private final ObservableBindingTrace traceForConstructors;
|
||||
private final ObservableBindingTrace traceForMembers;
|
||||
private final ObservableBindingTrace trace;
|
||||
|
||||
public BodyResolver(TopDownAnalysisContext context) {
|
||||
this.context = context;
|
||||
|
||||
// This allows access to backing fields
|
||||
this.traceForConstructors = new ObservableBindingTrace(context.getTrace()).addHandler(BindingContext.REFERENCE_TARGET, new ObservableBindingTrace.RecordHandler<JetReferenceExpression, DeclarationDescriptor>() {
|
||||
@Override
|
||||
public void handleRecord(WritableSlice<JetReferenceExpression, DeclarationDescriptor> slice, JetReferenceExpression expression, DeclarationDescriptor descriptor) {
|
||||
if (expression instanceof JetSimpleNameExpression) {
|
||||
JetSimpleNameExpression simpleNameExpression = (JetSimpleNameExpression) expression;
|
||||
if (simpleNameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
|
||||
if (!BodyResolver.this.context.getTrace().getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, (PropertyDescriptor) descriptor)) {
|
||||
BodyResolver.this.context.getTrace().report(NO_BACKING_FIELD.on(expression));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// This tracks access to properties in order to register primary constructor parameters that yield real fields (JET-9)
|
||||
// NOTE!!! This code is not used, because we do not allow constructor parameter access in member bodies
|
||||
this.traceForMembers = new ObservableBindingTrace(context.getTrace()).addHandler(BindingContext.REFERENCE_TARGET, new ObservableBindingTrace.RecordHandler<JetReferenceExpression, DeclarationDescriptor>() {
|
||||
@Override
|
||||
public void handleRecord(WritableSlice<JetReferenceExpression, DeclarationDescriptor> slice, JetReferenceExpression expression, DeclarationDescriptor descriptor) {
|
||||
if (descriptor instanceof PropertyDescriptor) {
|
||||
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
||||
if (BodyResolver.this.context.getPrimaryConstructorParameterProperties().contains(propertyDescriptor)) {
|
||||
traceForMembers.record(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.trace = context.getTrace();
|
||||
}
|
||||
|
||||
public void resolveBehaviorDeclarationBodies() {
|
||||
@@ -100,8 +70,8 @@ public class BodyResolver {
|
||||
final ConstructorDescriptor primaryConstructor = descriptor.getUnsubstitutedPrimaryConstructor();
|
||||
final JetScope scopeForConstructor = primaryConstructor == null
|
||||
? null
|
||||
: FunctionDescriptorUtil.getFunctionInnerScope(descriptor.getScopeForSupertypeResolution(), primaryConstructor, traceForConstructors);
|
||||
final ExpressionTypingServices typeInferrer = context.getSemanticServices().getTypeInferrerServices(traceForConstructors); // TODO : flow
|
||||
: FunctionDescriptorUtil.getFunctionInnerScope(descriptor.getScopeForSupertypeResolution(), primaryConstructor, trace);
|
||||
final ExpressionTypingServices typeInferrer = context.getSemanticServices().getTypeInferrerServices(trace); // TODO : flow
|
||||
|
||||
final Map<JetTypeReference, JetType> supertypes = Maps.newLinkedHashMap();
|
||||
JetVisitorVoid visitor = new JetVisitorVoid() {
|
||||
@@ -268,7 +238,7 @@ public class BodyResolver {
|
||||
ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
|
||||
assert primaryConstructor != null;
|
||||
final JetScope scopeForInitializers = classDescriptor.getScopeForInitializers();
|
||||
ExpressionTypingServices typeInferrer = context.getSemanticServices().getTypeInferrerServices(traceForConstructors);
|
||||
ExpressionTypingServices typeInferrer = context.getSemanticServices().getTypeInferrerServices(trace);
|
||||
for (JetClassInitializer anonymousInitializer : anonymousInitializers) {
|
||||
typeInferrer.getType(scopeForInitializers, anonymousInitializer.getBody(), NO_EXPECTED_TYPE);
|
||||
}
|
||||
@@ -294,9 +264,9 @@ public class BodyResolver {
|
||||
private void resolveSecondaryConstructorBody(JetSecondaryConstructor declaration, final ConstructorDescriptor descriptor) {
|
||||
if (!context.completeAnalysisNeeded(declaration)) return;
|
||||
MutableClassDescriptor classDescriptor = (MutableClassDescriptor) descriptor.getContainingDeclaration();
|
||||
final JetScope scopeForSupertypeInitializers = FunctionDescriptorUtil.getFunctionInnerScope(classDescriptor.getScopeForSupertypeResolution(), descriptor, traceForConstructors);
|
||||
final JetScope scopeForSupertypeInitializers = FunctionDescriptorUtil.getFunctionInnerScope(classDescriptor.getScopeForSupertypeResolution(), descriptor, trace);
|
||||
//contains only constructor parameters
|
||||
final JetScope scopeForConstructorBody = FunctionDescriptorUtil.getFunctionInnerScope(classDescriptor.getScopeForInitializers(), descriptor, traceForConstructors);
|
||||
final JetScope scopeForConstructorBody = FunctionDescriptorUtil.getFunctionInnerScope(classDescriptor.getScopeForInitializers(), descriptor, trace);
|
||||
//contains members & backing fields
|
||||
|
||||
final CallResolver callResolver = new CallResolver(context.getSemanticServices(), DataFlowInfo.EMPTY); // TODO: dataFlowInfo
|
||||
@@ -360,7 +330,7 @@ public class BodyResolver {
|
||||
}
|
||||
JetExpression bodyExpression = declaration.getBodyExpression();
|
||||
if (bodyExpression != null) {
|
||||
ExpressionTypingServices typeInferrer = context.getSemanticServices().getTypeInferrerServices(traceForConstructors);
|
||||
ExpressionTypingServices typeInferrer = context.getSemanticServices().getTypeInferrerServices(trace);
|
||||
|
||||
typeInferrer.checkFunctionReturnType(scopeForConstructorBody, declaration, JetStandardClasses.getUnitType());
|
||||
}
|
||||
@@ -417,7 +387,6 @@ public class BodyResolver {
|
||||
JetScope propertyDeclarationInnerScope = context.getDescriptorResolver().getPropertyDeclarationInnerScope(
|
||||
declaringScope, propertyDescriptor, propertyDescriptor.getTypeParameters(), propertyDescriptor.getReceiverParameter());
|
||||
WritableScope accessorScope = new WritableScopeImpl(propertyDeclarationInnerScope, declaringScope.getContainingDeclaration(), new TraceBasedRedeclarationHandler(context.getTrace())).setDebugName("Accessor scope");
|
||||
accessorScope.addPropertyDescriptorByFieldName("$" + propertyDescriptor.getName(), propertyDescriptor);
|
||||
accessorScope.changeLockLevel(WritableScope.LockLevel.READING);
|
||||
|
||||
return accessorScope;
|
||||
@@ -442,7 +411,7 @@ public class BodyResolver {
|
||||
}
|
||||
|
||||
private ObservableBindingTrace createFieldTrackingTrace(final PropertyDescriptor propertyDescriptor) {
|
||||
return new ObservableBindingTrace(traceForMembers).addHandler(BindingContext.REFERENCE_TARGET, new ObservableBindingTrace.RecordHandler<JetReferenceExpression, DeclarationDescriptor>() {
|
||||
return new ObservableBindingTrace(trace).addHandler(BindingContext.REFERENCE_TARGET, new ObservableBindingTrace.RecordHandler<JetReferenceExpression, DeclarationDescriptor>() {
|
||||
@Override
|
||||
public void handleRecord(WritableSlice<JetReferenceExpression, DeclarationDescriptor> slice, JetReferenceExpression expression, DeclarationDescriptor descriptor) {
|
||||
if (expression instanceof JetSimpleNameExpression) {
|
||||
@@ -450,7 +419,7 @@ public class BodyResolver {
|
||||
if (simpleNameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
|
||||
// This check may be considered redundant as long as $x is only accessible from accessors to $x
|
||||
if (descriptor == propertyDescriptor) { // TODO : original?
|
||||
traceForMembers.record(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor); // TODO: this context.getTrace()?
|
||||
trace.record(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor); // TODO: this context.getTrace()?
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -460,7 +429,7 @@ public class BodyResolver {
|
||||
|
||||
private void resolvePropertyInitializer(JetProperty property, PropertyDescriptor propertyDescriptor, JetExpression initializer, JetScope scope) {
|
||||
//JetFlowInformationProvider flowInformationProvider = context.getDescriptorResolver().computeFlowData(property, initializer); // TODO : flow JET-15
|
||||
ExpressionTypingServices typeInferrer = context.getSemanticServices().getTypeInferrerServices(traceForConstructors);
|
||||
ExpressionTypingServices typeInferrer = context.getSemanticServices().getTypeInferrerServices(trace);
|
||||
JetType expectedTypeForInitializer = property.getPropertyTypeRef() != null ? propertyDescriptor.getOutType() : NO_EXPECTED_TYPE;
|
||||
JetType type = typeInferrer.getType(context.getDescriptorResolver().getPropertyDeclarationInnerScope(scope, propertyDescriptor, propertyDescriptor.getTypeParameters(), propertyDescriptor.getReceiverParameter()), initializer, expectedTypeForInitializer);
|
||||
//
|
||||
@@ -494,7 +463,7 @@ public class BodyResolver {
|
||||
JetScope declaringScope = this.context.getDeclaringScopes().get(declaration);
|
||||
assert declaringScope != null;
|
||||
|
||||
resolveFunctionBody(traceForMembers, declaration, descriptor, declaringScope);
|
||||
resolveFunctionBody(trace, declaration, descriptor, declaringScope);
|
||||
|
||||
assert descriptor.getReturnType() != null;
|
||||
}
|
||||
|
||||
@@ -181,7 +181,8 @@ public class DeclarationsChecker {
|
||||
if (!(classDescriptor.getModality() == Modality.ABSTRACT) && classDescriptor.getKind() != ClassKind.ENUM_CLASS) {
|
||||
PsiElement classElement = context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, classDescriptor);
|
||||
assert classElement instanceof JetClass;
|
||||
context.getTrace().report(ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS.on(property, abstractNode, property.getName(), classDescriptor, (JetClass) classElement));
|
||||
String name = property.getName();
|
||||
context.getTrace().report(ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS.on(property, abstractNode, name != null ? name : "", classDescriptor, (JetClass) classElement));
|
||||
return;
|
||||
}
|
||||
if (classDescriptor.getKind() == ClassKind.TRAIT) {
|
||||
|
||||
@@ -64,7 +64,15 @@ public class CallResolver {
|
||||
if (referencedName == null) {
|
||||
return null;
|
||||
}
|
||||
List<ResolutionTask<VariableDescriptor>> prioritizedTasks = TaskPrioritizers.PROPERTY_TASK_PRIORITIZER.computePrioritizedTasks(scope, call, referencedName, trace.getBindingContext(), dataFlowInfo);
|
||||
TaskPrioritizer<VariableDescriptor> task_prioritizer;
|
||||
if (nameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
|
||||
referencedName = referencedName.substring(1);
|
||||
task_prioritizer = TaskPrioritizers.PROPERTY_TASK_PRIORITIZER;
|
||||
}
|
||||
else {
|
||||
task_prioritizer = TaskPrioritizers.VARIABLE_TASK_PRIORITIZER;
|
||||
}
|
||||
List<ResolutionTask<VariableDescriptor>> prioritizedTasks = task_prioritizer.computePrioritizedTasks(scope, call, referencedName, trace.getBindingContext(), dataFlowInfo);
|
||||
return resolveCallToDescriptor(trace, scope, call, expectedType, prioritizedTasks, nameExpression);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.jetbrains.jet.lang.resolve.calls;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
@@ -8,10 +9,7 @@ import org.jetbrains.jet.lang.types.ErrorUtils;
|
||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -83,7 +81,7 @@ public class TaskPrioritizers {
|
||||
}
|
||||
};
|
||||
|
||||
/*package*/ static TaskPrioritizer<VariableDescriptor> PROPERTY_TASK_PRIORITIZER = new TaskPrioritizer<VariableDescriptor>() {
|
||||
/*package*/ static TaskPrioritizer<VariableDescriptor> VARIABLE_TASK_PRIORITIZER = new TaskPrioritizer<VariableDescriptor>() {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
@@ -115,4 +113,34 @@ public class TaskPrioritizers {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
};
|
||||
|
||||
/*package*/ static TaskPrioritizer<VariableDescriptor> PROPERTY_TASK_PRIORITIZER = new TaskPrioritizer<VariableDescriptor>() {
|
||||
private Collection<VariableDescriptor> filterProperties(Collection<VariableDescriptor> variableDescriptors) {
|
||||
ArrayList<VariableDescriptor> properties = Lists.newArrayList();
|
||||
for (VariableDescriptor descriptor : variableDescriptors) {
|
||||
if (descriptor instanceof PropertyDescriptor) {
|
||||
properties.add(descriptor);
|
||||
}
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Collection<VariableDescriptor> getNonExtensionsByName(JetScope scope, String name) {
|
||||
return filterProperties(VARIABLE_TASK_PRIORITIZER.getNonExtensionsByName(scope, name));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Collection<VariableDescriptor> getMembersByName(@NotNull JetType receiver, String name) {
|
||||
return filterProperties(VARIABLE_TASK_PRIORITIZER.getMembersByName(receiver, name));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Collection<VariableDescriptor> getExtensionsByName(JetScope scope, String name) {
|
||||
return filterProperties(VARIABLE_TASK_PRIORITIZER.getExtensionsByName(scope, name));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -36,8 +36,6 @@ public interface WritableScope extends JetScope {
|
||||
@Nullable
|
||||
NamespaceDescriptor getDeclaredNamespace(@NotNull String name);
|
||||
|
||||
void addPropertyDescriptorByFieldName(@NotNull String fieldName, @NotNull PropertyDescriptor propertyDescriptor);
|
||||
|
||||
void importScope(@NotNull JetScope imported);
|
||||
|
||||
void setImplicitReceiver(@NotNull ReceiverDescriptor implicitReceiver);
|
||||
|
||||
@@ -338,17 +338,6 @@ public class WritableScopeImpl extends WritableScopeWithImports {
|
||||
return propertyDescriptorsByFieldNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPropertyDescriptorByFieldName(@NotNull String fieldName, @NotNull PropertyDescriptor propertyDescriptor) {
|
||||
checkMayWrite();
|
||||
|
||||
if (!fieldName.startsWith("$")) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
getPropertyDescriptorsByFieldNames().put(fieldName, propertyDescriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyDescriptor getPropertyByFieldReference(@NotNull String fieldName) {
|
||||
checkMayRead();
|
||||
|
||||
@@ -176,13 +176,6 @@ public class WriteThroughScope extends WritableScopeWithImports {
|
||||
return writableWorker.getDeclaredNamespace(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPropertyDescriptorByFieldName(@NotNull String fieldName, @NotNull PropertyDescriptor propertyDescriptor) {
|
||||
checkMayWrite();
|
||||
|
||||
writableWorker.addPropertyDescriptorByFieldName(fieldName, propertyDescriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void importScope(@NotNull JetScope imported) {
|
||||
checkMayWrite();
|
||||
@@ -206,6 +199,10 @@ public class WriteThroughScope extends WritableScopeWithImports {
|
||||
allDescriptors = Lists.newArrayList();
|
||||
allDescriptors.addAll(writableWorker.getAllDescriptors());
|
||||
allDescriptors.addAll(getWorkerScope().getAllDescriptors());
|
||||
|
||||
for (JetScope imported : getImports()) {
|
||||
allDescriptors.addAll(imported.getAllDescriptors());
|
||||
}
|
||||
}
|
||||
return allDescriptors;
|
||||
}
|
||||
|
||||
+1
-16
@@ -47,22 +47,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
public JetType visitSimpleNameExpression(JetSimpleNameExpression expression, ExpressionTypingContext context) {
|
||||
// TODO : other members
|
||||
// TODO : type substitutions???
|
||||
String referencedName = expression.getReferencedName();
|
||||
if (expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER
|
||||
&& referencedName != null) {
|
||||
PropertyDescriptor property = context.scope.getPropertyByFieldReference(referencedName);
|
||||
if (property == null) {
|
||||
context.trace.report(UNRESOLVED_REFERENCE.on(expression));
|
||||
}
|
||||
else {
|
||||
context.trace.record(REFERENCE_TARGET, expression, property);
|
||||
return DataFlowUtils.checkType(property.getOutType(), expression, context);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return DataFlowUtils.checkType(getSelectorReturnType(NO_RECEIVER, null, expression, context), expression, context); // TODO : Extensions to this
|
||||
}
|
||||
return null;
|
||||
return DataFlowUtils.checkType(getSelectorReturnType(NO_RECEIVER, null, expression, context), expression, context); // TODO : Extensions to this
|
||||
}
|
||||
|
||||
private JetType lookupNamespaceOrClassObject(JetSimpleNameExpression expression, String referencedName, ExpressionTypingContext context) {
|
||||
|
||||
+1
-10
@@ -213,16 +213,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
||||
basic.checkLValue(context.trace, expression.getLeft());
|
||||
}
|
||||
if (left instanceof JetSimpleNameExpression) {
|
||||
JetSimpleNameExpression simpleName = (JetSimpleNameExpression) left;
|
||||
String referencedName = simpleName.getReferencedName();
|
||||
if (simpleName.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER
|
||||
&& referencedName != null) {
|
||||
PropertyDescriptor property = context.scope.getPropertyByFieldReference(referencedName);
|
||||
if (property != null) {
|
||||
context.trace.record(BindingContext.VARIABLE_ASSIGNMENT, simpleName, property);
|
||||
}
|
||||
}
|
||||
ExpressionTypingUtils.checkWrappingInRef(simpleName, context);
|
||||
ExpressionTypingUtils.checkWrappingInRef(left, context);
|
||||
}
|
||||
return checkExpectedType(expression, contextWithExpectedType);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
class A() {
|
||||
class B(val i: Int) {
|
||||
}
|
||||
|
||||
fun test() = Array<B> (10, { B(it) })
|
||||
}
|
||||
|
||||
fun box() = if(A().test()[5].i == 5) "OK" else "fail"
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace org2
|
||||
|
||||
enum class Test {
|
||||
A
|
||||
B
|
||||
C
|
||||
}
|
||||
|
||||
fun box() = Test.A.toString()
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace demo_range
|
||||
|
||||
fun Int?.plus() : Int = this.sure().plus()
|
||||
fun Int?.dec() : Int = this.sure().dec()
|
||||
fun Int?.inc() : Int = this.sure().inc()
|
||||
fun Int?.minus() : Int = this.sure().minus()
|
||||
|
||||
fun box() : String {
|
||||
val x : Int? = 10
|
||||
System.out?.println(x?.inv())// * x?.plus() * x?.dec() * x?.minus() as Number)
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace demo_long
|
||||
|
||||
fun Long?.inv() : Long = this.sure().inv()
|
||||
|
||||
fun box() : String {
|
||||
val x : Long? = 10
|
||||
System.out?.println(x.inv())
|
||||
return if(x.inv() == -11.lng) "OK" else "fail"
|
||||
}
|
||||
@@ -24,7 +24,7 @@ class WithC() {
|
||||
{
|
||||
val z = <!UNRESOLVED_REFERENCE!>b<!>
|
||||
val zz = x
|
||||
val zzz = <!NO_BACKING_FIELD!>$a<!>
|
||||
val zzz = <!NO_BACKING_FIELD_CUSTOM_ACCESSORS!>$a<!>
|
||||
}
|
||||
|
||||
this(a : Int) : this() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var x : Int = 1 + x
|
||||
var x : Int = 1 + x
|
||||
get() : Int = 1
|
||||
set(<!REF_SETTER_PARAMETER!>ref<!> value : <!WRONG_SETTER_PARAMETER_TYPE!>Long<!>) {
|
||||
$x = value.int
|
||||
@@ -14,16 +14,16 @@
|
||||
|
||||
class Test() {
|
||||
var a : Int = 111
|
||||
var b : Int get() = <!UNRESOLVED_REFERENCE!>$a<!>; set(x) {a = x; <!UNRESOLVED_REFERENCE!>$a<!> = x}
|
||||
var b : Int get() = $a; set(x) {a = x; $a = x}
|
||||
|
||||
this(i : Int) : this() {
|
||||
<!NO_BACKING_FIELD!>$b<!> = $a
|
||||
$a = <!NO_BACKING_FIELD!>$b<!>
|
||||
a = <!NO_BACKING_FIELD!>$b<!>
|
||||
<!NO_BACKING_FIELD_CUSTOM_ACCESSORS!>$b<!> = $a
|
||||
$a = <!NO_BACKING_FIELD_CUSTOM_ACCESSORS!>$b<!>
|
||||
a = <!NO_BACKING_FIELD_CUSTOM_ACCESSORS!>$b<!>
|
||||
}
|
||||
fun f() {
|
||||
<!UNRESOLVED_REFERENCE!>$b<!> = <!UNRESOLVED_REFERENCE!>$a<!>
|
||||
a = <!UNRESOLVED_REFERENCE!>$b<!>
|
||||
<!NO_BACKING_FIELD_CUSTOM_ACCESSORS!>$b<!> = $a
|
||||
a = <!NO_BACKING_FIELD_CUSTOM_ACCESSORS!>$b<!>
|
||||
}
|
||||
public val <!PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE!>i<!> = 1
|
||||
}
|
||||
@@ -137,14 +137,14 @@ class AnonymousInitializers(var a: String, val b: String) {
|
||||
|
||||
{
|
||||
<!VAL_REASSIGNMENT!>$i<!> = 13
|
||||
<!NO_BACKING_FIELD, VAL_REASSIGNMENT!>$j<!> = 30
|
||||
j = 34
|
||||
<!NO_BACKING_FIELD_CUSTOM_ACCESSORS!>$j<!> = 30
|
||||
<!VAL_REASSIGNMENT!>j<!> = 34
|
||||
}
|
||||
|
||||
val k: String
|
||||
{
|
||||
if (1 < 3) {
|
||||
<!INITIALIZATION_USING_BACKING_FIELD!>k<!> = "a"
|
||||
k = "a"
|
||||
}
|
||||
else {
|
||||
$k = "b"
|
||||
@@ -288,7 +288,7 @@ class TestObjectExpression() {
|
||||
val <!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>y<!> : Int
|
||||
{
|
||||
if (true)
|
||||
<!INITIALIZATION_USING_BACKING_FIELD!>x<!> = 12
|
||||
x = 12
|
||||
else
|
||||
$x = 1
|
||||
}
|
||||
@@ -349,4 +349,4 @@ fun test(m : M) {
|
||||
fun test1(m : M) {
|
||||
<!VAL_REASSIGNMENT!>m.x<!>++
|
||||
m.y--
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
class ReadByAnotherPropertyInitializer() {
|
||||
val a = 1
|
||||
fun ff() = <!UNRESOLVED_REFERENCE!>$a<!>
|
||||
fun ff() = $a
|
||||
}
|
||||
|
||||
+2
-2
@@ -2,6 +2,6 @@ abstract class ReadNonexistent() {
|
||||
abstract val aa: Int
|
||||
|
||||
{
|
||||
val x = <!NO_BACKING_FIELD!>$aa<!>
|
||||
val x = <!NO_BACKING_FIELD_ABSTRACT_PROPERTY!>$aa<!>
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
abstract class ReadNonexistent {
|
||||
abstract val aa: Int
|
||||
|
||||
fun ff() = <!UNRESOLVED_REFERENCE!>$aa<!>
|
||||
}
|
||||
fun ff() = <!NO_BACKING_FIELD_ABSTRACT_PROPERTY!>$aa<!>
|
||||
}
|
||||
+2
-2
@@ -3,6 +3,6 @@ class ReadNonexistent() {
|
||||
get() = 1
|
||||
|
||||
{
|
||||
val x = <!NO_BACKING_FIELD!>$a<!>
|
||||
val x = <!NO_BACKING_FIELD_CUSTOM_ACCESSORS!>$a<!>
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -2,5 +2,5 @@ class CustomValNoBackingField() {
|
||||
val a: Int
|
||||
get() = 1
|
||||
|
||||
val b = <!NO_BACKING_FIELD!>$a<!>
|
||||
}
|
||||
val b = <!NO_BACKING_FIELD_CUSTOM_ACCESSORS!>$a<!>
|
||||
}
|
||||
+6
-7
@@ -1,7 +1,6 @@
|
||||
val y = 1
|
||||
|
||||
class A() {
|
||||
{
|
||||
val x = <!UNRESOLVED_REFERENCE!>$y<!>
|
||||
}
|
||||
}
|
||||
class CustomValNoBackingField() {
|
||||
val a: Int
|
||||
get() = 1
|
||||
|
||||
val b = <!NO_BACKING_FIELD_CUSTOM_ACCESSORS!>$a<!>
|
||||
}
|
||||
+2
-2
@@ -2,6 +2,6 @@ val y = 1
|
||||
|
||||
class A() {
|
||||
{
|
||||
<!UNRESOLVED_REFERENCE!>$y<!> = 1
|
||||
<!INACCESSIBLE_BACKING_FIELD!>$y<!> = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
//KT-462 Consider allowing initializing properties via property names when it is safe
|
||||
//KT-598 Allow to use backing fields after this expression
|
||||
|
||||
namespace kt462
|
||||
|
||||
abstract class TestInitializationWithoutBackingField() {
|
||||
val valWithBackingField : Int
|
||||
{
|
||||
valWithBackingField = 2
|
||||
}
|
||||
|
||||
val valWithoutBackingField : Int
|
||||
get() = 42
|
||||
{
|
||||
<!VAL_REASSIGNMENT!>valWithoutBackingField<!> = 45
|
||||
}
|
||||
|
||||
var finalDefaultVar : Int
|
||||
{
|
||||
finalDefaultVar = 3
|
||||
}
|
||||
|
||||
open var openVar : Int
|
||||
{
|
||||
<!INITIALIZATION_USING_BACKING_FIELD_OPEN_SETTER!>openVar<!> = 4
|
||||
}
|
||||
|
||||
var varWithCustomSetter : Int
|
||||
set(v: Int) {
|
||||
$varWithCustomSetter = v
|
||||
}
|
||||
{
|
||||
<!INITIALIZATION_USING_BACKING_FIELD_CUSTOM_SETTER!>varWithCustomSetter<!> = 3
|
||||
}
|
||||
|
||||
var varWithoutBackingField : Int
|
||||
get() = 3
|
||||
set(v: Int) {}
|
||||
{
|
||||
varWithoutBackingField = 4
|
||||
}
|
||||
|
||||
abstract var abstractVar : Int
|
||||
{
|
||||
abstractVar = 34
|
||||
}
|
||||
}
|
||||
|
||||
abstract class TestInitializationThroughBackingField() {
|
||||
val valWithBackingField : Int
|
||||
{
|
||||
$valWithBackingField = 2
|
||||
}
|
||||
|
||||
val valWithoutBackingField : Int
|
||||
get() = 42
|
||||
{
|
||||
<!NO_BACKING_FIELD_CUSTOM_ACCESSORS!>$valWithoutBackingField<!> = 45
|
||||
}
|
||||
|
||||
var finalDefaultVar : Int
|
||||
{
|
||||
$finalDefaultVar = 3
|
||||
}
|
||||
|
||||
open var openVar : Int
|
||||
{
|
||||
$openVar = 4
|
||||
}
|
||||
|
||||
var varWithCustomSetter : Int
|
||||
set(v: Int) {
|
||||
$varWithCustomSetter = v
|
||||
}
|
||||
{
|
||||
$varWithCustomSetter = 3
|
||||
}
|
||||
|
||||
var varWithoutBackingField : Int
|
||||
get() = 3
|
||||
set(v: Int) {}
|
||||
{
|
||||
<!NO_BACKING_FIELD_CUSTOM_ACCESSORS!>$varWithoutBackingField<!> = 4
|
||||
}
|
||||
|
||||
abstract var abstractVar : Int
|
||||
{
|
||||
<!NO_BACKING_FIELD_ABSTRACT_PROPERTY!>$abstractVar<!> = 34
|
||||
}
|
||||
}
|
||||
|
||||
class TestBackingFieldsVisibility() {
|
||||
var a : Int = 712
|
||||
{
|
||||
$a = 37
|
||||
this.$a = 357
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
$a = 334
|
||||
this.$a = 347
|
||||
}
|
||||
|
||||
fun foo(a: TestBackingFieldsVisibility) {
|
||||
val <!UNUSED_VARIABLE!>b<!> : Int = 3
|
||||
<!UNRESOLVED_REFERENCE!>$b<!> = 342
|
||||
<!INACCESSIBLE_BACKING_FIELD!>a.$a<!> = 3
|
||||
}
|
||||
|
||||
val x = <!INACCESSIBLE_BACKING_FIELD!>$namespaceLevelVar<!>
|
||||
|
||||
class Inner() {
|
||||
val z = this@TestBackingFieldsVisibility.$x
|
||||
}
|
||||
|
||||
<!ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS!>abstract<!> val w = 11
|
||||
get() = $w //test there is no second error here
|
||||
}
|
||||
|
||||
val namespaceLevelVar = 11
|
||||
|
||||
class T() {
|
||||
val z : Int get() = 42
|
||||
|
||||
{
|
||||
<!NO_BACKING_FIELD_CUSTOM_ACCESSORS!>this.$z<!> = 34
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
<!NO_BACKING_FIELD_CUSTOM_ACCESSORS!>this.$z<!> = 343
|
||||
}
|
||||
|
||||
val a = object {
|
||||
val x = <!NO_BACKING_FIELD_CUSTOM_ACCESSORS, NO_BACKING_FIELD_CUSTOM_ACCESSORS!>$z<!>
|
||||
{
|
||||
<!NO_BACKING_FIELD_CUSTOM_ACCESSORS, NO_BACKING_FIELD_CUSTOM_ACCESSORS!>$z<!> = 23
|
||||
}
|
||||
}
|
||||
|
||||
var x: Int = 2
|
||||
get() {
|
||||
val <!UNUSED_VARIABLE!>o<!> = object {
|
||||
{
|
||||
$x = 34
|
||||
}
|
||||
fun foo() {
|
||||
$x = 23
|
||||
}
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
var r: Int = $x
|
||||
set(v: Int) {
|
||||
if (true) {
|
||||
$r = 33
|
||||
}
|
||||
else {
|
||||
$r = 35
|
||||
}
|
||||
}
|
||||
|
||||
fun bar() {
|
||||
$x = 34
|
||||
val <!UNUSED_VARIABLE!>o<!> = object {
|
||||
val y = $x
|
||||
{
|
||||
$x = 422
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ namespace kt510
|
||||
public open class Identifier1() {
|
||||
var field : Boolean
|
||||
{
|
||||
<!INITIALIZATION_USING_BACKING_FIELD!>field<!> = false; // error
|
||||
field = false; // error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,6 @@ public open class Identifier1() {
|
||||
public open class Identifier2() {
|
||||
var field : Boolean
|
||||
{
|
||||
<!INITIALIZATION_USING_BACKING_FIELD!>this.field<!> = false;
|
||||
this.field = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace test
|
||||
|
||||
class Ramification
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace test
|
||||
|
||||
class River {
|
||||
fun song() = 1
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace test
|
||||
|
||||
fun fff(a: String) = 1
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace test
|
||||
|
||||
fun fff(a: String?) = 1
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace test
|
||||
|
||||
fun f() = 1
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace test
|
||||
|
||||
fun ff(): String = ""
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace test
|
||||
|
||||
fun ff(): String? = ""
|
||||
@@ -0,0 +1,246 @@
|
||||
package org.jetbrains.jet;
|
||||
|
||||
import com.intellij.lang.ASTFactory;
|
||||
import com.intellij.lang.LanguageASTFactory;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.psi.PsiFileFactory;
|
||||
import com.intellij.psi.impl.PsiFileFactoryImpl;
|
||||
import com.intellij.psi.impl.source.tree.JavaASTFactory;
|
||||
import com.intellij.testFramework.LightVirtualFile;
|
||||
import com.intellij.testFramework.UsefulTestCase;
|
||||
import junit.framework.Test;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.codegen.ClassBuilderFactory;
|
||||
import org.jetbrains.jet.codegen.ClassFileFactory;
|
||||
import org.jetbrains.jet.codegen.GenerationState;
|
||||
import org.jetbrains.jet.compiler.CompileEnvironment;
|
||||
import org.jetbrains.jet.lang.JetSemanticServices;
|
||||
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.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
|
||||
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices;
|
||||
import org.jetbrains.jet.plugin.JetLanguage;
|
||||
import org.junit.Assert;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Stepan Koltsov
|
||||
*/
|
||||
public class ReadClassDataTest extends UsefulTestCase {
|
||||
|
||||
protected final Disposable myTestRootDisposable = new Disposable() {
|
||||
@Override
|
||||
public void dispose() {
|
||||
}
|
||||
};
|
||||
|
||||
private JetCoreEnvironment jetCoreEnvironment;
|
||||
private File tmpdir;
|
||||
|
||||
private final File testFile;
|
||||
|
||||
public ReadClassDataTest(@NotNull File testFile) {
|
||||
this.testFile = testFile;
|
||||
setName(testFile.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
tmpdir = new File("tmp/" + this.getClass().getSimpleName() + "." + this.getName());
|
||||
rmrf(tmpdir);
|
||||
mkdirs(tmpdir);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tearDown() throws Exception {
|
||||
Disposer.dispose(myTestRootDisposable);
|
||||
}
|
||||
|
||||
private void mkdirs(File file) throws IOException {
|
||||
if (file.isDirectory()) {
|
||||
return;
|
||||
}
|
||||
if (!file.mkdirs()) {
|
||||
throw new IOException();
|
||||
}
|
||||
}
|
||||
|
||||
private void rmrf(File file) {
|
||||
if (file != null) {
|
||||
File[] children = file.listFiles();
|
||||
if (children != null) {
|
||||
for (File child : children) {
|
||||
rmrf(child);
|
||||
}
|
||||
}
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
private void createMockCoreEnvironment() {
|
||||
jetCoreEnvironment = new JetCoreEnvironment(myTestRootDisposable);
|
||||
|
||||
final File rtJar = new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/rt.jar");
|
||||
jetCoreEnvironment.addToClasspath(rtJar);
|
||||
jetCoreEnvironment.addToClasspath(new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/annotations.jar"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runTest() throws Exception {
|
||||
createMockCoreEnvironment();
|
||||
|
||||
LanguageASTFactory.INSTANCE.addExplicitExtension(JavaLanguage.INSTANCE, new JavaASTFactory());
|
||||
|
||||
|
||||
String text = FileUtil.loadFile(testFile);
|
||||
|
||||
LightVirtualFile virtualFile = new LightVirtualFile("Hello.kt", JetLanguage.INSTANCE, text);
|
||||
virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET);
|
||||
JetFile psiFile = (JetFile) ((PsiFileFactoryImpl) PsiFileFactory.getInstance(jetCoreEnvironment.getProject())).trySetupPsiForFile(virtualFile, JetLanguage.INSTANCE, true, false);
|
||||
|
||||
GenerationState state = new GenerationState(jetCoreEnvironment.getProject(), ClassBuilderFactory.BINARIES);
|
||||
AnalyzingUtils.checkForSyntacticErrors(psiFile);
|
||||
BindingContext bindingContext = state.compile(psiFile);
|
||||
|
||||
ClassFileFactory classFileFactory = state.getFactory();
|
||||
|
||||
CompileEnvironment.writeToOutputDirectory(classFileFactory, tmpdir.getPath());
|
||||
|
||||
NamespaceDescriptor namespaceFromSource = (NamespaceDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, psiFile.getRootNamespace());
|
||||
|
||||
Assert.assertEquals("test", namespaceFromSource.getName());
|
||||
|
||||
Disposer.dispose(myTestRootDisposable);
|
||||
|
||||
|
||||
|
||||
createMockCoreEnvironment();
|
||||
|
||||
jetCoreEnvironment.addToClasspath(tmpdir);
|
||||
|
||||
JetSemanticServices jetSemanticServices = JetSemanticServices.createSemanticServices(jetCoreEnvironment.getProject());
|
||||
JavaSemanticServices semanticServices = new JavaSemanticServices(jetCoreEnvironment.getProject(), jetSemanticServices, new BindingTraceContext());
|
||||
|
||||
JavaDescriptorResolver javaDescriptorResolver = semanticServices.getDescriptorResolver();
|
||||
NamespaceDescriptor namespaceFromClass = javaDescriptorResolver.resolveNamespace("test");
|
||||
|
||||
compareNamespaces(namespaceFromSource, namespaceFromClass);
|
||||
}
|
||||
|
||||
private void compareNamespaces(@NotNull NamespaceDescriptor nsa, @NotNull NamespaceDescriptor nsb) {
|
||||
Assert.assertEquals(nsa.getName(), nsb.getName());
|
||||
System.out.println("namespace " + nsa.getName());
|
||||
for (DeclarationDescriptor ad : nsa.getMemberScope().getAllDescriptors()) {
|
||||
if (ad instanceof ClassifierDescriptor) {
|
||||
ClassifierDescriptor bd = nsb.getMemberScope().getClassifier(ad.getName());
|
||||
compareClassifiers((ClassifierDescriptor) ad, bd);
|
||||
} else if (ad instanceof FunctionDescriptor) {
|
||||
Set<FunctionDescriptor> functions = nsb.getMemberScope().getFunctions(ad.getName());
|
||||
Assert.assertTrue(functions.size() >= 1);
|
||||
Assert.assertTrue("not implemented", functions.size() == 1);
|
||||
FunctionDescriptor bd = functions.iterator().next();
|
||||
compareFunctions((FunctionDescriptor) ad, bd);
|
||||
} else {
|
||||
throw new AssertionError("Unknown member: " + ad);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void compareClassifiers(@NotNull ClassifierDescriptor a, @NotNull ClassifierDescriptor b) {
|
||||
Assert.assertEquals(a.getName(), b.getName());
|
||||
System.out.println("classifier " + a.getName());
|
||||
if (a instanceof ClassDescriptor || b instanceof ClassDescriptor) {
|
||||
compareClasses((ClassDescriptor) a, (ClassDescriptor) b);
|
||||
}
|
||||
}
|
||||
|
||||
private void compareClasses(@NotNull ClassDescriptor a, @NotNull ClassDescriptor b) {
|
||||
System.out.println("... is class");
|
||||
}
|
||||
|
||||
private void compareFunctions(@NotNull FunctionDescriptor a, @NotNull FunctionDescriptor b) {
|
||||
Assert.assertEquals(a.getName(), b.getName());
|
||||
Assert.assertEquals(a.getValueParameters().size(), b.getValueParameters().size());
|
||||
for (int i = 0; i < a.getValueParameters().size(); ++i) {
|
||||
compareAnything(ValueParameterDescriptor.class, a.getValueParameters().get(i), b.getValueParameters().get(i));
|
||||
}
|
||||
Assert.assertEquals(a.getReturnType(), b.getReturnType());
|
||||
System.out.println("fun " + a.getName() + "(...): " + a.getReturnType());
|
||||
}
|
||||
|
||||
private <T> void compareAnything(Class<T> clazz, T a, T b) {
|
||||
System.out.println("Comparing " + clazz);
|
||||
Assert.assertNotNull(a);
|
||||
Assert.assertNotNull(b);
|
||||
|
||||
for (Method method : clazz.getMethods()) {
|
||||
if (!isGetter(method)) {
|
||||
continue;
|
||||
}
|
||||
if (method.getName().equals("getContainingDeclaration")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (clazz.equals(ValueParameterDescriptor.class)) {
|
||||
if (method.getName().equals("isRef") || method.getName().equals("getOriginal")) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println(method.getName());
|
||||
Object ap = invoke(method, a);
|
||||
Object bp = invoke(method, b);
|
||||
Assert.assertEquals(ap, bp);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isGetter(Method method) {
|
||||
if (method.getParameterTypes().length > 0) {
|
||||
return false;
|
||||
}
|
||||
if (method.getName().matches("is.+")) {
|
||||
return method.getReturnType().equals(boolean.class);
|
||||
} else if (method.getName().matches("get.+")) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static Object invoke(Method method, Object thiz, Object... args) {
|
||||
try {
|
||||
return method.invoke(thiz, args);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("failed to invoke " + method + ": " + e);
|
||||
}
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
return JetTestCaseBuilder.suiteForDirectory(JetTestCaseBuilder.getTestDataPathBase(), "/readClass", true, new JetTestCaseBuilder.NamedTestFactory() {
|
||||
@NotNull
|
||||
@Override
|
||||
public Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) {
|
||||
return new ReadClassDataTest(file);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -286,4 +286,9 @@ public class ArrayGenTest extends CodegenTestCase {
|
||||
// System.out.println(generateToText());
|
||||
blackBox();
|
||||
}
|
||||
|
||||
public void testNonNullArray() throws Exception {
|
||||
blackBoxFile("classes/nonnullarray.jet");
|
||||
System.out.println(generateToText());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import org.jetbrains.jet.lang.psi.JetNamespace;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
@@ -216,6 +218,10 @@ public class ClassGenTest extends CodegenTestCase {
|
||||
blackBoxFile("regressions/kt500.jet");
|
||||
}
|
||||
|
||||
public void testKt694 () throws Exception {
|
||||
// blackBoxFile("regressions/kt694.jet");
|
||||
}
|
||||
|
||||
public void testKt285 () throws Exception {
|
||||
// blackBoxFile("regressions/kt285.jet");
|
||||
}
|
||||
|
||||
@@ -287,37 +287,31 @@ public class PrimitiveTypesTest extends CodegenTestCase {
|
||||
|
||||
public void testKt711 () throws Exception {
|
||||
loadText("fun box() = if ((1 ?: 0) == 1) \"OK\" else \"fail\"");
|
||||
// System.out.println(generateToText());
|
||||
blackBox();
|
||||
}
|
||||
|
||||
public void testSureNonnull () throws Exception {
|
||||
loadText("fun box() = 10.sure().toString()");
|
||||
// System.out.println(generateToText());
|
||||
assertFalse(generateToText().contains("IFNONNULL"));
|
||||
}
|
||||
|
||||
public void testSureNullable () throws Exception {
|
||||
loadText("val a : Int? = 10; fun box() = a.sure().toString()");
|
||||
// System.out.println(generateToText());
|
||||
assertTrue(generateToText().contains("IFNONNULL"));
|
||||
}
|
||||
|
||||
public void testSafeNonnull () throws Exception {
|
||||
loadText("fun box() = 10?.toString()");
|
||||
// System.out.println(generateToText());
|
||||
assertFalse(generateToText().contains("IFNULL"));
|
||||
}
|
||||
|
||||
public void testSafeNullable () throws Exception {
|
||||
loadText("val a : Int? = 10; fun box() = a?.toString()");
|
||||
// System.out.println(generateToText());
|
||||
assertTrue(generateToText().contains("IFNULL"));
|
||||
}
|
||||
|
||||
public void testKt737() throws Exception {
|
||||
loadText("fun box() = if(3.compareTo(2) != 1) \"fail\" else if(5.byt.compareTo(10.lng) >= 0) \"fail\" else \"OK\"");
|
||||
// System.out.println(generateToText());
|
||||
assertEquals("OK", blackBox());
|
||||
}
|
||||
|
||||
@@ -334,22 +328,27 @@ public class PrimitiveTypesTest extends CodegenTestCase {
|
||||
" System.out?.println(f(six))\n" +
|
||||
" return \"OK\"" +
|
||||
"}");
|
||||
// System.out.println(generateToText());
|
||||
blackBox();
|
||||
}
|
||||
|
||||
public void testKt752 () {
|
||||
blackBoxFile("regressions/kt752.jet");
|
||||
// System.out.println(generateToText());
|
||||
}
|
||||
|
||||
public void testKt753 () {
|
||||
blackBoxFile("regressions/kt753.jet");
|
||||
// System.out.println(generateToText());
|
||||
}
|
||||
|
||||
public void testKt684 () {
|
||||
blackBoxFile("regressions/kt684.jet");
|
||||
// System.out.println(generateToText());
|
||||
}
|
||||
|
||||
public void testKt756 () {
|
||||
blackBoxFile("regressions/kt756.jet");
|
||||
System.out.println(generateToText());
|
||||
}
|
||||
|
||||
public void testKt757 () {
|
||||
blackBoxFile("regressions/kt757.jet");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
* The Computer Language Benchmarks Game
|
||||
* http://shootout.alioth.debian.org/
|
||||
*
|
||||
* contributed by Fabien Le Floc'h
|
||||
*
|
||||
* Java implementation of thread-ring benchmark. Best performance is achieved with
|
||||
* MAX_THREAD=1 as the thread-ring test is bested with only 1 os thread.
|
||||
* This implementation shows using a simple thread pool solves the thread context
|
||||
* switch issue.
|
||||
*/
|
||||
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public class ThreadRing {
|
||||
private static final int MAX_NODES = 503;
|
||||
private static final int MAX_THREADS = 503;
|
||||
|
||||
private ExecutorService executor;
|
||||
private final int N;
|
||||
|
||||
static final CountDownLatch cdl = new CountDownLatch(1);
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
long start = System.currentTimeMillis();
|
||||
int n = 5000000;
|
||||
try {
|
||||
n = Integer.parseInt(args[0]);
|
||||
} catch (Exception e) {}
|
||||
ThreadRing ring = new ThreadRing(n);
|
||||
Node node = ring.start(MAX_NODES);
|
||||
node.sendMessage(new TokenMessage(1,0));
|
||||
cdl.await();
|
||||
|
||||
long total = System.currentTimeMillis() - start;
|
||||
System.out.println("[ThreadRing-" + System.getProperty("project.name")+ " Benchmark Result: " + total + "]");
|
||||
}
|
||||
|
||||
public ThreadRing(int n) {
|
||||
N = n;
|
||||
}
|
||||
|
||||
public Node start(int n) {
|
||||
Node[] nodes = spawnNodes(n);
|
||||
connectNodes(n, nodes);
|
||||
return nodes[0];
|
||||
}
|
||||
|
||||
private Node[] spawnNodes(int n) {
|
||||
executor = Executors.newFixedThreadPool(MAX_THREADS);
|
||||
Node[] nodes = new Node[n+1];
|
||||
for (int i = 0; i < n ; i++) {
|
||||
nodes[i] = new Node(i+1, null);
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
public void connectNodes(int n, Node[] nodes) {
|
||||
nodes[n] = nodes[0];
|
||||
for (int i=0; i<n; i++) {
|
||||
nodes[i].connect(nodes[i+1]);
|
||||
}
|
||||
}
|
||||
|
||||
private static class TokenMessage {
|
||||
private int nodeId;
|
||||
private volatile int value;
|
||||
private boolean isStop;
|
||||
|
||||
public TokenMessage(int nodeId, int value) {
|
||||
this.nodeId = nodeId;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public TokenMessage(int nodeId, int value, boolean isStop) {
|
||||
this.nodeId = nodeId;
|
||||
this.value = value;
|
||||
this.isStop = isStop;
|
||||
}
|
||||
}
|
||||
|
||||
private class Node implements Runnable {
|
||||
private int nodeId;
|
||||
private Node nextNode;
|
||||
private BlockingQueue<TokenMessage> queue = new LinkedBlockingQueue<TokenMessage>();
|
||||
private boolean isActive = false;
|
||||
private int counter;
|
||||
|
||||
public Node(int id, Node nextNode) {
|
||||
this.nodeId = id;
|
||||
this.nextNode = nextNode;
|
||||
this.counter = 0;
|
||||
}
|
||||
|
||||
public void connect(Node node) {
|
||||
this.nextNode = node;
|
||||
isActive = true;
|
||||
}
|
||||
|
||||
public void sendMessage(TokenMessage m) {
|
||||
queue.add(m);
|
||||
executor.execute(this);
|
||||
}
|
||||
|
||||
|
||||
public void run() {
|
||||
if (isActive) {
|
||||
try {
|
||||
TokenMessage m = queue.take();
|
||||
if (m.isStop) {
|
||||
int nextValue = m.value+1;
|
||||
if (nextValue == MAX_NODES) {
|
||||
// System.out.println("last one");
|
||||
executor.shutdown();
|
||||
cdl.countDown();
|
||||
} else {
|
||||
m.value = nextValue;
|
||||
nextNode.sendMessage(m);
|
||||
}
|
||||
isActive = false;
|
||||
// System.out.println("ending node "+nodeId);
|
||||
} else {
|
||||
if (m.value == N) {
|
||||
System.out.println(nodeId);
|
||||
nextNode.sendMessage(new TokenMessage(nodeId, 0, true));
|
||||
} else {
|
||||
m.value = m.value + 1;
|
||||
nextNode.sendMessage(m);
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException ie) {
|
||||
ie.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
namespace threadring
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.*;
|
||||
|
||||
val MAX_NODES = 503
|
||||
val MAX_THREADS = 503
|
||||
|
||||
val cdl = CountDownLatch(1)
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val start = System.currentTimeMillis()
|
||||
var n = 5000000;
|
||||
try {
|
||||
n = Integer.parseInt(args[0]);
|
||||
} catch (e: Throwable) {
|
||||
}
|
||||
|
||||
val ring = ThreadRing(n)
|
||||
ring.sendMessage(TokenMessage(1,0,false))
|
||||
cdl.await();
|
||||
|
||||
val total = System.currentTimeMillis() - start
|
||||
System.out?.println("[ThreadRing-" + System.getProperty("project.name")+ " Benchmark Result: " + total + "]")
|
||||
}
|
||||
|
||||
class TokenMessage(val nodeId : Int, value: Int, val isStop: Boolean) : AtomicInteger(value){
|
||||
}
|
||||
|
||||
class ThreadRing(val N: Int) {
|
||||
val executor = Executors.newFixedThreadPool(MAX_THREADS).sure()
|
||||
|
||||
val nodes : Array<Node> = Array<Node>(MAX_NODES+1, { Node(it+1) })
|
||||
|
||||
{
|
||||
connectNodes()
|
||||
}
|
||||
|
||||
fun connectNodes() {
|
||||
nodes[nodes.size-1] = nodes[0]
|
||||
for (i in 0..nodes.size-2) {
|
||||
nodes[i].connect(nodes[i+1]);
|
||||
}
|
||||
}
|
||||
|
||||
fun sendMessage(m : TokenMessage) {
|
||||
nodes[0].sendMessage(m)
|
||||
}
|
||||
class Node(val nodeId : Int) : Runnable {
|
||||
val queue = LinkedBlockingQueue<TokenMessage>()
|
||||
var isActive = false
|
||||
var nextNode : Node? = null
|
||||
|
||||
fun sendMessage(m: TokenMessage) {
|
||||
queue.add(m)
|
||||
executor.execute(this)
|
||||
}
|
||||
|
||||
fun connect(next: Node) {
|
||||
nextNode = next
|
||||
isActive = true
|
||||
}
|
||||
|
||||
override fun run() {
|
||||
if(isActive) {
|
||||
try {
|
||||
val m = queue.take()
|
||||
if(m.isStop) {
|
||||
val nextValue = m.get()+1
|
||||
if (nextValue == MAX_NODES) {
|
||||
executor.shutdown()
|
||||
cdl.countDown()
|
||||
} else {
|
||||
m.set(nextValue)
|
||||
nextNode.sure().sendMessage(m)
|
||||
}
|
||||
isActive = false
|
||||
}
|
||||
else {
|
||||
if (m.get() == N) {
|
||||
System.out?.println(nodeId);
|
||||
nextNode.sure().sendMessage(TokenMessage(nodeId, 0, true));
|
||||
} else {
|
||||
m.incrementAndGet()
|
||||
nextNode.sure().sendMessage(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(e: InterruptedException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,7 +59,9 @@
|
||||
<codeInsight.overrideMethod language="jet" implementationClass="org.jetbrains.jet.plugin.codeInsight.OverrideMethodsHandler"/>
|
||||
|
||||
|
||||
<!--
|
||||
<java.elementFinder implementation="org.jetbrains.jet.plugin.java.JavaElementFinder"/>
|
||||
-->
|
||||
<toolWindow id="CodeWindow"
|
||||
factoryClass="org.jetbrains.jet.plugin.internal.codewindow.BytecodeToolwindow$Factory"
|
||||
anchor="right"/>
|
||||
|
||||
@@ -4,7 +4,7 @@ import com.intellij.ide.IconProvider;
|
||||
import com.intellij.openapi.util.Iconable;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.Icons;
|
||||
import com.intellij.util.PlatformIcons;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
@@ -15,21 +15,21 @@ import javax.swing.*;
|
||||
* @author yole
|
||||
*/
|
||||
public class JetIconProvider extends IconProvider {
|
||||
public static final Icon ICON_FOR_OBJECT = Icons.ANONYMOUS_CLASS_ICON;
|
||||
public static final Icon ICON_FOR_OBJECT = PlatformIcons.ANONYMOUS_CLASS_ICON;
|
||||
|
||||
@Override
|
||||
public Icon getIcon(@NotNull PsiElement psiElement, int flags) {
|
||||
if (psiElement instanceof JetNamespace) {
|
||||
return (flags & Iconable.ICON_FLAG_OPEN) != 0 ? Icons.PACKAGE_OPEN_ICON : Icons.PACKAGE_ICON;
|
||||
return (flags & Iconable.ICON_FLAG_OPEN) != 0 ? PlatformIcons.PACKAGE_OPEN_ICON : PlatformIcons.PACKAGE_ICON;
|
||||
}
|
||||
if (psiElement instanceof JetNamedFunction) {
|
||||
return PsiTreeUtil.getParentOfType(psiElement, JetNamedDeclaration.class) instanceof JetClass
|
||||
? Icons.METHOD_ICON
|
||||
: Icons.FUNCTION_ICON;
|
||||
? PlatformIcons.METHOD_ICON
|
||||
: PlatformIcons.FUNCTION_ICON;
|
||||
}
|
||||
if (psiElement instanceof JetClass) {
|
||||
JetClass jetClass = (JetClass) psiElement;
|
||||
Icon icon = jetClass.hasModifier(JetTokens.ENUM_KEYWORD) ? Icons.ENUM_ICON : Icons.CLASS_ICON;
|
||||
Icon icon = jetClass.hasModifier(JetTokens.ENUM_KEYWORD) ? PlatformIcons.ENUM_ICON : PlatformIcons.CLASS_ICON;
|
||||
if (jetClass instanceof JetEnumEntry) {
|
||||
JetEnumEntry enumEntry = (JetEnumEntry) jetClass;
|
||||
if (enumEntry.getPrimaryConstructorParameterList() == null) {
|
||||
@@ -42,13 +42,13 @@ public class JetIconProvider extends IconProvider {
|
||||
if (((JetParameter) psiElement).getValOrVarNode() != null) {
|
||||
JetParameterList parameterList = PsiTreeUtil.getParentOfType(psiElement, JetParameterList.class);
|
||||
if (parameterList != null && parameterList.getParent() instanceof JetClass) {
|
||||
return Icons.PROPERTY_ICON;
|
||||
return PlatformIcons.PROPERTY_ICON;
|
||||
}
|
||||
}
|
||||
return Icons.PARAMETER_ICON;
|
||||
return PlatformIcons.PARAMETER_ICON;
|
||||
}
|
||||
if (psiElement instanceof JetProperty) {
|
||||
return Icons.PROPERTY_ICON;
|
||||
return PlatformIcons.PROPERTY_ICON;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -24,13 +24,23 @@ import java.util.Set;
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class WholeProjectAnalyzerFacade {
|
||||
public static final Function<JetFile, Collection<JetDeclaration>> WHOLE_PROJECT_DECLARATION_PROVIDER = new Function<JetFile, Collection<JetDeclaration>>() {
|
||||
public final class WholeProjectAnalyzerFacade {
|
||||
|
||||
/** Forbid creating */
|
||||
private WholeProjectAnalyzerFacade() {}
|
||||
|
||||
/**
|
||||
* Will collect all root-namespaces in all kotlin files in the project.
|
||||
*/
|
||||
public static final Function<JetFile, Collection<JetDeclaration>> WHOLE_PROJECT_DECLARATION_PROVIDER =
|
||||
new Function<JetFile, Collection<JetDeclaration>>() {
|
||||
|
||||
@Override
|
||||
public Collection<JetDeclaration> fun(final JetFile rootFile) {
|
||||
final Project project = rootFile.getProject();
|
||||
final Set<JetDeclaration> namespaces = Sets.newLinkedHashSet();
|
||||
ProjectRootManager rootManager = ProjectRootManager.getInstance(project);
|
||||
final ProjectRootManager rootManager = ProjectRootManager.getInstance(project);
|
||||
|
||||
if (rootManager != null && !ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
VirtualFile[] contentRoots = rootManager.getContentRoots();
|
||||
|
||||
@@ -55,9 +65,9 @@ public class WholeProjectAnalyzerFacade {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@NotNull
|
||||
public static BindingContext analyzeProjectWithCacheOnAFile(@NotNull JetFile file) {
|
||||
return AnalyzerFacade.analyzeFileWithCache(file, WHOLE_PROJECT_DECLARATION_PROVIDER);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ public class AddModifierFix extends JetIntentionAction<JetModifierListOwner> {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
/*package*/ static String getElementName(JetModifierListOwner modifierListOwner) {
|
||||
/*package*/ static String getElementName(@NotNull JetModifierListOwner modifierListOwner) {
|
||||
String name = null;
|
||||
if (modifierListOwner instanceof PsiNameIdentifierOwner) {
|
||||
PsiElement nameIdentifier = ((PsiNameIdentifierOwner) modifierListOwner).getNameIdentifier();
|
||||
|
||||
@@ -36,12 +36,7 @@ public class ChangeToBackingFieldFix extends JetIntentionAction<JetSimpleNameExp
|
||||
@Override
|
||||
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
|
||||
JetSimpleNameExpression backingField = (JetSimpleNameExpression) JetPsiFactory.createExpression(project, "$" + element.getText());
|
||||
if (element.getParent() instanceof JetDotQualifiedExpression && ((JetDotQualifiedExpression) element.getParent()).getReceiverExpression() instanceof JetThisExpression) {
|
||||
element.getParent().replace(backingField);
|
||||
}
|
||||
else {
|
||||
element.replace(backingField);
|
||||
}
|
||||
element.replace(backingField);
|
||||
}
|
||||
|
||||
public static JetIntentionActionFactory<JetSimpleNameExpression> createFactory() {
|
||||
|
||||
@@ -78,8 +78,9 @@ public class ChangeVariableMutabilityFix implements IntentionAction {
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
|
||||
JetProperty element = getCorrespondingProperty(editor, (JetFile)file);
|
||||
JetProperty newElement = (JetProperty) element.copy();
|
||||
JetProperty property = getCorrespondingProperty(editor, (JetFile)file);
|
||||
assert property != null && !property.isVar();
|
||||
JetProperty newElement = (JetProperty) property.copy();
|
||||
if (newElement.isVar()) {
|
||||
PsiElement varElement = newElement.getNode().findChildByType(JetTokens.VAR_KEYWORD).getPsi();
|
||||
|
||||
@@ -94,7 +95,7 @@ public class ChangeVariableMutabilityFix implements IntentionAction {
|
||||
PsiElement varElement = varProperty.getNode().findChildByType(JetTokens.VAR_KEYWORD).getPsi();
|
||||
CodeEditUtil.replaceChild(newElement.getNode(), valElement.getNode(), varElement.getNode());
|
||||
}
|
||||
element.replace(newElement);
|
||||
property.replace(newElement);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -111,8 +111,10 @@ public class QuickFixes {
|
||||
add(Errors.ILLEGAL_MODIFIER, removeModifierFactory);
|
||||
|
||||
add(Errors.PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE, AddReturnTypeFix.createFactory());
|
||||
|
||||
add(Errors.INITIALIZATION_USING_BACKING_FIELD, ChangeToBackingFieldFix.createFactory());
|
||||
|
||||
JetIntentionActionFactory<JetSimpleNameExpression> changeToBackingFieldFactory = ChangeToBackingFieldFix.createFactory();
|
||||
add(Errors.INITIALIZATION_USING_BACKING_FIELD_CUSTOM_SETTER, changeToBackingFieldFactory);
|
||||
add(Errors.INITIALIZATION_USING_BACKING_FIELD_OPEN_SETTER, changeToBackingFieldFactory);
|
||||
|
||||
ImplementMethodsHandler implementMethodsHandler = new ImplementMethodsHandler();
|
||||
actionMap.put(Errors.ABSTRACT_MEMBER_NOT_IMPLEMENTED, implementMethodsHandler);
|
||||
|
||||
@@ -35,7 +35,7 @@ public class RemoveModifierFix {
|
||||
if (isRedundant) {
|
||||
return JetBundle.message("remove.redundant.modifier", modifier.getValue());
|
||||
}
|
||||
if (element != null && modifier == JetTokens.ABSTRACT_KEYWORD || modifier == JetTokens.OPEN_KEYWORD) {
|
||||
if (element != null && (modifier == JetTokens.ABSTRACT_KEYWORD || modifier == JetTokens.OPEN_KEYWORD)) {
|
||||
return JetBundle.message("make.element.not.modifier", AddModifierFix.getElementName(element), modifier.getValue());
|
||||
}
|
||||
return JetBundle.message("remove.modifier", modifier.getValue());
|
||||
|
||||
@@ -24,17 +24,3 @@ namespace boundsWithSubstitutors {
|
||||
abstract val x : fun (B<<error>Char</error>>) : B<<error>Any</error>>
|
||||
}
|
||||
|
||||
|
||||
fun test() {
|
||||
foo<<error>Int?</error>>()
|
||||
foo<Int>()
|
||||
bar<Int?>()
|
||||
bar<Int>()
|
||||
bar<<error>Double?</error>>()
|
||||
bar<<error>Double</error>>()
|
||||
1.buzz<<error>Double</error>>()
|
||||
}
|
||||
|
||||
fun foo<T : Any>() {}
|
||||
fun bar<T : Int?>() {}
|
||||
fun <T : <warning>Int</warning>> Int.buzz() : Unit {}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
fun test() {
|
||||
foo<<error>Int?</error>>()
|
||||
foo<Int>()
|
||||
bar<Int?>()
|
||||
bar<Int>()
|
||||
bar<<error>Double?</error>>()
|
||||
bar<<error>Double</error>>()
|
||||
1.buzz<<error>Double</error>>()
|
||||
}
|
||||
|
||||
fun foo<T : Any>() {}
|
||||
fun bar<T : Int?>() {}
|
||||
fun <T : <warning>Int</warning>> Int.buzz() : Unit {}
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
class Test() {
|
||||
var a : Int = 111
|
||||
var b : Int get() = <error>$a</error>; set(x) {a = x; <error>$a</error> = x}
|
||||
var b : Int get() = $a; set(x) {a = x; $a = x}
|
||||
|
||||
this(i : Int) : this() {
|
||||
<error>$b</error> = $a
|
||||
@@ -22,7 +22,7 @@ class Test() {
|
||||
a = <error>$b</error>
|
||||
}
|
||||
fun f() {
|
||||
<error>$b</error> = <error>$a</error>
|
||||
<error>$b</error> = $a
|
||||
a = <error>$b</error>
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Tests
|
||||
|
||||
import java.util.*
|
||||
|
||||
fun hello() {
|
||||
val a = So<caret>
|
||||
}
|
||||
|
||||
// EXIST: SortedSet, SortedMap
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Tests
|
||||
|
||||
class A : java.<caret>
|
||||
|
||||
// EXIST: lang, util, io
|
||||
// ABSENT: fun, val, var, namespace
|
||||
@@ -1,10 +1,10 @@
|
||||
open class MyClass() {
|
||||
}
|
||||
|
||||
class A() : My<caret> {
|
||||
class A() {
|
||||
public fun test() {
|
||||
val a : MyC<caret>
|
||||
}
|
||||
}
|
||||
|
||||
// EXIST: MyClass
|
||||
// EXIST: MyClass
|
||||
|
||||
@@ -3,4 +3,4 @@ fun foo() {
|
||||
}
|
||||
|
||||
// TODO: Move all keywords to absent
|
||||
// EXPECT: fun, val, var, namespace
|
||||
// EXIST: fun, val, var, namespace
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<caret>
|
||||
|
||||
// EXPECT: namespace, as, type, class, this, super, val, var, fun, for, null, true
|
||||
// EXPECT: false, is, in, throw, return, break, continue, object, if, try, else, while
|
||||
// EXPECT: do, when, trait, This
|
||||
// EXPECT: import, where, by, get, set, abstract, enum, open, annotation, override, private
|
||||
// EXPECT: public, internal, protected, catch, out, vararg, inline, finally, final, ref
|
||||
// EXIST: namespace, as, type, class, this, super, val, var, fun, for, null, true
|
||||
// EXIST: false, is, in, throw, return, break, continue, object, if, try, else, while
|
||||
// EXIST: do, when, trait, This
|
||||
// EXIST: import, where, by, get, set, abstract, enum, open, annotation, override, private
|
||||
// EXIST: public, internal, protected, catch, out, vararg, inline, finally, final, ref
|
||||
// ABSENT: ?in, new, extends, implements
|
||||
@@ -1,6 +1,7 @@
|
||||
// "Change reference to backing field" "true"
|
||||
class A() {
|
||||
val a : Int
|
||||
var a : Int
|
||||
set(v) {}
|
||||
{
|
||||
<caret>$a = 1
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// "Change reference to backing field" "true"
|
||||
public open class Identifier() {
|
||||
var field : Boolean
|
||||
set(v) {}
|
||||
{
|
||||
<caret>$field = false;
|
||||
<caret>this.$field = false;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
// "Change reference to backing field" "true"
|
||||
class A() {
|
||||
val a : Int
|
||||
var a : Int
|
||||
set(v) {}
|
||||
{
|
||||
<caret>a = 1
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// "Change reference to backing field" "true"
|
||||
public open class Identifier() {
|
||||
var field : Boolean
|
||||
set(v) {}
|
||||
{
|
||||
<caret>this.field = false;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ public class JetBasicCompletionTest extends JetCompletionTestBase {
|
||||
setName("testCompletionExecute");
|
||||
}
|
||||
|
||||
public void testCompletionExecute() {
|
||||
public void testCompletionExecute() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
|
||||
@@ -2,70 +2,64 @@ package org.jetbrains.jet.completion;
|
||||
|
||||
import com.intellij.codeInsight.completion.CodeCompletionHandlerBase;
|
||||
import com.intellij.codeInsight.completion.CompletionType;
|
||||
import com.intellij.codeInsight.completion.LightCompletionTestCase;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupEx;
|
||||
import com.intellij.codeInsight.lookup.LookupManager;
|
||||
import com.intellij.testFramework.LightCodeInsightTestCase;
|
||||
import com.intellij.codeInsight.lookup.impl.LookupImpl;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.plugin.PluginTestCaseBase;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Nikolay.Krasko
|
||||
*/
|
||||
public abstract class JetCompletionTestBase extends LightCodeInsightTestCase {
|
||||
public abstract class JetCompletionTestBase extends LightCompletionTestCase {
|
||||
|
||||
protected void doTest() {
|
||||
private CompletionType type;
|
||||
|
||||
protected void doTest() throws Exception {
|
||||
final String testName = getTestName(false);
|
||||
|
||||
type = (testName.startsWith("Smart")) ? CompletionType.SMART : CompletionType.BASIC;
|
||||
|
||||
configureByFile(testName + ".kt");
|
||||
|
||||
CompletionType completionType = (testName.startsWith("Smart")) ? CompletionType.SMART : CompletionType.BASIC;
|
||||
new CodeCompletionHandlerBase(completionType, false, false, true).invokeCompletion(getProject(), getEditor());
|
||||
|
||||
LookupEx lookup = LookupManager.getActiveLookup(getEditor());
|
||||
assert lookup != null;
|
||||
|
||||
HashSet<String> items = new HashSet<String>(resolveLookups(lookup.getItems()));
|
||||
|
||||
List<String> shouldExist = itemsShouldExist(getFile().getText());
|
||||
for (String shouldExistItem : shouldExist) {
|
||||
assertTrue(String.format("Should contain proposal '%s'.", shouldExistItem),
|
||||
items.contains(shouldExistItem));
|
||||
}
|
||||
|
||||
List<String> shouldAbsent = itemsShouldAbsent(getFile().getText());
|
||||
for (String shouldAbsentItem : shouldAbsent) {
|
||||
assertTrue(String.format("Shouldn't contain proposal '%s'.", shouldAbsentItem),
|
||||
!items.contains(shouldAbsentItem));
|
||||
}
|
||||
assertContainsItems(itemsShouldExist(getFile().getText()));
|
||||
assertNotContainItems(itemsShouldAbsent(getFile().getText()));
|
||||
}
|
||||
|
||||
private static List<String> resolveLookups(List<LookupElement> items) {
|
||||
ArrayList<String> result = new ArrayList<String>(items.size());
|
||||
for (LookupElement item : items) {
|
||||
result.add(item.getLookupString());
|
||||
}
|
||||
|
||||
return result;
|
||||
@Override
|
||||
protected Sdk getProjectJDK() {
|
||||
return PluginTestCaseBase.jdkFromIdeaHome();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void complete(final int time) {
|
||||
new CodeCompletionHandlerBase(type, false, false, true).invokeCompletion(getProject(), getEditor(), time, false);
|
||||
|
||||
LookupImpl lookup = (LookupImpl) LookupManager.getActiveLookup(myEditor);
|
||||
myItems = lookup == null ? null : lookup.getItems().toArray(LookupElement.EMPTY_ARRAY);
|
||||
myPrefix = lookup == null ? null : lookup.itemPattern(lookup.getItems().get(0));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<String> itemsShouldExist(String fileText) {
|
||||
private static String[] itemsShouldExist(String fileText) {
|
||||
return findListWithPrefix("// EXIST:", fileText);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<String> itemsShouldAbsent(String fileText) {
|
||||
private static String[] itemsShouldAbsent(String fileText) {
|
||||
return findListWithPrefix("// ABSENT:", fileText);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<String> findListWithPrefix(String prefix, String fileText) {
|
||||
private static String[] findListWithPrefix(String prefix, String fileText) {
|
||||
ArrayList<String> result = new ArrayList<String>();
|
||||
|
||||
for (String line : findLinesWithPrefixRemoved(prefix, fileText)) {
|
||||
@@ -76,7 +70,7 @@ public abstract class JetCompletionTestBase extends LightCodeInsightTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return result.toArray(new String[result.size()]);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.jetbrains.jet.completion;
|
||||
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestSuite;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.JetTestCaseBuilder;
|
||||
@@ -25,7 +26,7 @@ public class KeywordsCompletionTest extends JetCompletionTestBase {
|
||||
setName("testCompletionExecute");
|
||||
}
|
||||
|
||||
public void testCompletionExecute() {
|
||||
public void testCompletionExecute() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
@@ -49,13 +50,14 @@ public class KeywordsCompletionTest extends JetCompletionTestBase {
|
||||
PluginTestCaseBase.getTestDataPathBase(), "/completion/keywords/", false,
|
||||
JetTestCaseBuilder.emptyFilter, new JetTestCaseBuilder.NamedTestFactory() {
|
||||
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public junit.framework.Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) {
|
||||
public Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) {
|
||||
return new KeywordsCompletionTest(dataPath, name);
|
||||
}
|
||||
}, suite);
|
||||
|
||||
return suite;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user