diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index aead6e36f70..88346225fc3 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -10,12 +10,8 @@ import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.types.JetStandardClasses; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeProjection; -import org.jetbrains.jet.lang.types.Variance; import org.jetbrains.jet.lexer.JetTokens; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; +import org.objectweb.asm.*; import org.objectweb.asm.commons.InstructionAdapter; import org.objectweb.asm.commons.Method; @@ -101,6 +97,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { interfaces.toArray(new String[interfaces.size()]) ); v.visitSource(myClass.getContainingFile().getName(), null); + + if(myClass instanceof JetClass) { + AnnotationVisitor annotationVisitor = v.visitAnnotation("Ljet/typeinfo/JetSignature;", true); + annotationVisitor.visit("value", SignatureUtil.classToSignature((JetClass)myClass, state.getBindingContext(), state.getTypeMapper())); + annotationVisitor.visitEnd(); + } } private String jvmName() { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/SignatureUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/SignatureUtil.java new file mode 100644 index 00000000000..0bddcbbb7ec --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/SignatureUtil.java @@ -0,0 +1,77 @@ +package org.jetbrains.jet.codegen; + +import jet.typeinfo.TypeInfoVariance; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; +import org.jetbrains.jet.lang.psi.JetClass; +import org.jetbrains.jet.lang.psi.JetDelegationSpecifier; +import org.jetbrains.jet.lang.psi.JetTypeParameter; +import org.jetbrains.jet.lang.psi.JetTypeReference; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.java.JavaClassDescriptor; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.TypeProjection; +import org.jetbrains.jet.lang.types.Variance; +import org.objectweb.asm.Type; + +import java.util.List; + +/** + * @author alex.tkachman + */ +public class SignatureUtil { + public static String classToSignature(JetClass type, BindingContext bindingContext, JetTypeMapper typeMapper) { + StringBuilder sb = new StringBuilder(); + genTypeParams(type, sb); + List delegationSpecifiers = type.getDelegationSpecifiers(); + for (JetDelegationSpecifier specifier : delegationSpecifiers) { + JetTypeReference typeReference = specifier.getTypeReference(); + JetType jetType = bindingContext.get(BindingContext.TYPE, typeReference); + genJetType(sb, jetType, typeMapper); + } + return sb.toString(); + } + + private static void genJetType(StringBuilder sb, JetType jetType, JetTypeMapper typeMapper) { + DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor(); + if(descriptor instanceof ClassDescriptor) { + JetType defaultType = ((ClassDescriptor) descriptor).getDefaultType(); + org.objectweb.asm.Type type = typeMapper.mapType(defaultType, OwnerKind.IMPLEMENTATION); + if(JetTypeMapper.isPrimitive(type)) { + type = JetTypeMapper.boxType(type); + } + sb.append(type.getDescriptor()); + } + else { + sb.append("T").append(descriptor.getName()).append(";"); + } + if(!jetType.getArguments().isEmpty()) { + sb.append("<"); + for (TypeProjection typeProjection : jetType.getArguments()) { + if(typeProjection.getProjectionKind() == Variance.IN_VARIANCE) + sb.append("in "); + if(typeProjection.getProjectionKind() == Variance.OUT_VARIANCE) + sb.append("out "); + genJetType(sb, typeProjection.getType(), typeMapper); + } + sb.append(">"); + } + if(jetType.isNullable()) + sb.append("?"); + } + + private static void genTypeParams(JetClass type, StringBuilder sb) { + List parameters = type.getTypeParameterList().getParameters(); + for(JetTypeParameter param : parameters) { + sb.append("T"); + Variance variance = param.getVariance(); + if(variance == Variance.IN_VARIANCE) + sb.append("in "); + else if(variance == Variance.OUT_VARIANCE) + sb.append("out "); + sb.append(param.getName()); + sb.append(";"); + } + } +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java index 402a6db487b..c1817e67cc1 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java @@ -7,7 +7,7 @@ import com.intellij.psi.PsiClass; import com.intellij.psi.PsiMethod; import com.intellij.psi.search.ProjectScope; import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.resolve.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.types.JetStandardClasses; import org.jetbrains.jet.lang.types.JetStandardLibrary; import org.jetbrains.jet.lang.types.TypeProjection; diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassDescriptor.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassDescriptor.java index 4d0ae312517..680d984b1e7 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassDescriptor.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassDescriptor.java @@ -3,8 +3,8 @@ package org.jetbrains.jet.lang.resolve.java; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.resolve.JetScope; -import org.jetbrains.jet.lang.resolve.SubstitutingScope; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope; import org.jetbrains.jet.lang.types.*; import java.util.Collections; diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java index 4fb1ef331d1..23fbbacaa7b 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java @@ -5,11 +5,12 @@ import com.google.common.collect.Sets; import com.intellij.psi.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.resolve.JetScope; -import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.types.TypeSubstitutor; import java.util.Collection; +import java.util.List; import java.util.Map; /** @@ -64,6 +65,7 @@ public class JavaClassMembersScope implements JetScope { return classifierDescriptor; } + @NotNull @Override public Collection getAllDescriptors() { if (allDescriptors == null) { @@ -123,7 +125,7 @@ public class JavaClassMembersScope implements JetScope { return null; } - return semanticServices.getDescriptorResolver().resolveFieldToVariableDescriptor((ClassDescriptor) containingDeclaration, field); + return semanticServices.getDescriptorResolver().resolveFieldToVariableDescriptor(containingDeclaration, field); } @NotNull @@ -149,7 +151,12 @@ public class JavaClassMembersScope implements JetScope { @NotNull @Override - public JetType getThisType() { - return null; + public ReceiverDescriptor getImplicitReceiver() { + throw new UnsupportedOperationException(); // Should never occur, we don't sit in a Java class... + } + + @Override + public void getImplicitReceiversHierarchy(@NotNull List result) { + throw new UnsupportedOperationException(); // Should never occur, we don't sit in a Java class... } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDefaultImports.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDefaultImports.java index 47544d6f20b..f6d6f2f001d 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDefaultImports.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDefaultImports.java @@ -4,7 +4,7 @@ import com.intellij.openapi.project.Project; import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.ImportingStrategy; -import org.jetbrains.jet.lang.resolve.WritableScope; +import org.jetbrains.jet.lang.resolve.scopes.WritableScope; /** * @author abreslav diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaNamespaceDescriptor.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaNamespaceDescriptor.java index 7868f2a9127..3443ebf0f79 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaNamespaceDescriptor.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaNamespaceDescriptor.java @@ -4,7 +4,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.AbstractNamespaceDescriptorImpl; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; -import org.jetbrains.jet.lang.resolve.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; import java.util.List; diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java index ab56eb57e81..7c43e8a8bba 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java @@ -2,7 +2,7 @@ package org.jetbrains.jet.lang.resolve.java; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.resolve.JetScopeImpl; +import org.jetbrains.jet.lang.resolve.scopes.JetScopeImpl; /** * @author abreslav diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptor.java index 7f5008c9376..efb8efb0995 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptor.java @@ -2,7 +2,7 @@ package org.jetbrains.jet.lang.descriptors; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.resolve.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeProjection; import org.jetbrains.jet.lang.types.TypeSubstitutor; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptorImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptorImpl.java index 2e3c73ce671..484382ba987 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptorImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/ClassDescriptorImpl.java @@ -3,8 +3,8 @@ package org.jetbrains.jet.lang.descriptors; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.resolve.JetScope; -import org.jetbrains.jet.lang.resolve.SubstitutingScope; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope; import org.jetbrains.jet.lang.types.*; import java.util.Collection; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorUtil.java index 5b2281ea730..00dc4d2f7a3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/FunctionDescriptorUtil.java @@ -5,16 +5,15 @@ import com.google.common.collect.HashBiMap; import com.google.common.collect.Maps; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.resolve.BindingTrace; -import org.jetbrains.jet.lang.resolve.JetScope; -import org.jetbrains.jet.lang.resolve.WritableScope; -import org.jetbrains.jet.lang.resolve.WritableScopeImpl; +import org.jetbrains.jet.lang.resolve.*; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.WritableScope; +import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionCallableReceiver; import org.jetbrains.jet.lang.types.*; import java.util.*; -import static org.jetbrains.jet.lang.types.TypeSubstitutor.TypeSubstitution; - /** * @author abreslav */ @@ -97,10 +96,10 @@ public class FunctionDescriptorUtil { @NotNull public static JetScope getFunctionInnerScope(@NotNull JetScope outerScope, @NotNull FunctionDescriptor descriptor, @NotNull BindingTrace trace) { - WritableScope parameterScope = new WritableScopeImpl(outerScope, descriptor, trace).setDebugName("Function inner scope"); + WritableScope parameterScope = new WritableScopeImpl(outerScope, descriptor, new TraceBasedRedeclarationHandler(trace)).setDebugName("Function inner scope"); JetType receiverType = descriptor.getReceiverType(); if (receiverType != null) { - parameterScope.setThisType(receiverType); + parameterScope.setImplicitReceiver(new ExtensionCallableReceiver(descriptor)); } for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) { parameterScope.addTypeParameterDescriptor(typeParameter); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java index 7db18637f16..86b70a0dcf5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/LazySubstitutingClassDescriptor.java @@ -3,8 +3,8 @@ package org.jetbrains.jet.lang.descriptors; import com.google.common.collect.Lists; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.resolve.JetScope; -import org.jetbrains.jet.lang.resolve.SubstitutingScope; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope; import org.jetbrains.jet.lang.types.*; import java.util.Collection; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java index dd6ef1366fb..5768910bd25 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/MutableClassDescriptor.java @@ -6,6 +6,11 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.resolve.*; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope; +import org.jetbrains.jet.lang.resolve.scopes.WritableScope; +import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.resolve.DescriptorRenderer; @@ -40,9 +45,10 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme public MutableClassDescriptor(@NotNull BindingTrace trace, @NotNull DeclarationDescriptor containingDeclaration, @NotNull JetScope outerScope, ClassKind kind) { super(containingDeclaration); - this.scopeForMemberLookup = new WritableScopeImpl(JetScope.EMPTY, this, trace).setDebugName("MemberLookup"); - this.scopeForSupertypeResolution = new WritableScopeImpl(outerScope, this, trace).setDebugName("SupertypeResolution"); - this.scopeForMemberResolution = new WritableScopeImpl(scopeForSupertypeResolution, this, trace).setDebugName("MemberResolution"); + TraceBasedRedeclarationHandler redeclarationHandler = new TraceBasedRedeclarationHandler(trace); + this.scopeForMemberLookup = new WritableScopeImpl(JetScope.EMPTY, this, redeclarationHandler).setDebugName("MemberLookup"); + this.scopeForSupertypeResolution = new WritableScopeImpl(outerScope, this, redeclarationHandler).setDebugName("SupertypeResolution"); + this.scopeForMemberResolution = new WritableScopeImpl(scopeForSupertypeResolution, this, redeclarationHandler).setDebugName("MemberResolution"); this.kind = kind; } @@ -159,7 +165,7 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme getName(), typeParameters, supertypes); - scopeForMemberResolution.setThisType(getDefaultType()); + scopeForMemberResolution.setImplicitReceiver(new ClassReceiver(this)); for (FunctionDescriptor functionDescriptor : constructors.getFunctionDescriptors()) { ((ConstructorDescriptorImpl) functionDescriptor).setReturnType(getDefaultType()); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/NamespaceDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/NamespaceDescriptor.java index f3d8c867e00..e28ddec1d21 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/NamespaceDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/NamespaceDescriptor.java @@ -2,7 +2,7 @@ package org.jetbrains.jet.lang.descriptors; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.annotations.Annotated; -import org.jetbrains.jet.lang.resolve.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.types.NamespaceType; /** diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/NamespaceDescriptorImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/NamespaceDescriptorImpl.java index 3c63b6c15e5..16016715a4d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/NamespaceDescriptorImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/NamespaceDescriptorImpl.java @@ -3,7 +3,7 @@ package org.jetbrains.jet.lang.descriptors; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.resolve.WritableScope; +import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import java.util.List; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java index 8c88bad746e..d441e8a3756 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/TypeParameterDescriptor.java @@ -3,8 +3,8 @@ package org.jetbrains.jet.lang.descriptors; import com.google.common.collect.Sets; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.resolve.JetScope; -import org.jetbrains.jet.lang.resolve.LazyScopeAdapter; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.LazyScopeAdapter; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.resolve.DescriptorRenderer; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement1.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement1.java index efc03f41cdf..8d10286885c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement1.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement1.java @@ -1,9 +1,7 @@ package org.jetbrains.jet.lang.diagnostics; import com.intellij.lang.ASTNode; -import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; /** @@ -29,11 +27,11 @@ public abstract class DiagnosticFactoryWithPsiElement1 @NotNull public Diagnostic on(@NotNull T element, @NotNull ASTNode node, @NotNull A argument) { - return new DiagnosticWithPsiElement(this, severity, makeMessage(argument), element, node.getTextRange()); + return new DiagnosticWithPsiElementImpl(this, severity, makeMessage(argument), element, node.getTextRange()); } @NotNull public Diagnostic on(@NotNull T element, @NotNull PsiElement psiElement, @NotNull A argument) { - return new DiagnosticWithPsiElement(this, severity, makeMessage(argument), element, psiElement.getTextRange()); + return new DiagnosticWithPsiElementImpl(this, severity, makeMessage(argument), element, psiElement.getTextRange()); } } \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement2.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement2.java index 669090b4a50..dc4ea2218f2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement2.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement2.java @@ -33,6 +33,6 @@ public abstract class DiagnosticFactoryWithPsiElement2(this, severity, makeMessage(a, b), element, node.getTextRange()); + return new DiagnosticWithPsiElementImpl(this, severity, makeMessage(a, b), element, node.getTextRange()); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticUtils.java index 07e72ee6000..ea3d2d57700 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticUtils.java @@ -4,7 +4,6 @@ import com.intellij.lang.ASTNode; import com.intellij.openapi.editor.Document; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; @@ -42,8 +41,14 @@ public class DiagnosticUtils { return closestPsiElement.getContainingFile(); } + @NotNull public static String atLocation(@NotNull PsiFile file, @NotNull TextRange textRange) { - Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file); + Document document = file.getViewProvider().getDocument();//PsiDocumentManager.getInstance(file.getProject()).getDocument(file); + return atLocation(file, textRange, document); + } + + @NotNull + public static String atLocation(PsiFile file, TextRange textRange, Document document) { int offset = textRange.getStartOffset(); VirtualFile virtualFile = file.getVirtualFile(); String pathSuffix = virtualFile == null ? "" : " in " + virtualFile.getPath(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithPsiElement.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithPsiElement.java index 034ef8de822..30b4aac5aff 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithPsiElement.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithPsiElement.java @@ -1,27 +1,12 @@ package org.jetbrains.jet.lang.diagnostics; -import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; /** - * @author svtk + * @author abreslav */ -public class DiagnosticWithPsiElement extends GenericDiagnostic { - private final T psiElement; - - public DiagnosticWithPsiElement(DiagnosticFactory factory, Severity severity, String message, T psiElement) { - this(factory, severity, message, psiElement, psiElement.getTextRange()); - } - - public DiagnosticWithPsiElement(DiagnosticFactory factory, Severity severity, String message, T psiElement, @NotNull TextRange textRange) { - super(factory, severity, message, psiElement.getContainingFile(), textRange); - this.psiElement = psiElement; - } - +public interface DiagnosticWithPsiElement extends DiagnosticWithTextRange { @NotNull - public T getPsiElement() { - return psiElement; - } + T getPsiElement(); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithPsiElementImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithPsiElementImpl.java new file mode 100644 index 00000000000..4c9914d4967 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithPsiElementImpl.java @@ -0,0 +1,27 @@ +package org.jetbrains.jet.lang.diagnostics; + +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; + +/** + * @author svtk + */ +public class DiagnosticWithPsiElementImpl extends GenericDiagnostic implements DiagnosticWithPsiElement { + private final T psiElement; + + public DiagnosticWithPsiElementImpl(DiagnosticFactory factory, Severity severity, String message, T psiElement) { + this(factory, severity, message, psiElement, psiElement.getTextRange()); + } + + public DiagnosticWithPsiElementImpl(DiagnosticFactory factory, Severity severity, String message, T psiElement, @NotNull TextRange textRange) { + super(factory, severity, message, psiElement.getContainingFile(), textRange); + this.psiElement = psiElement; + } + + @Override + @NotNull + public T getPsiElement() { + return psiElement; + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory3.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory3.java index dd80fb14dc5..fafff17af01 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory3.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory3.java @@ -46,6 +46,6 @@ public class ParameterizedDiagnosticFactory3 extends DiagnosticFactoryW @NotNull public Diagnostic on(@NotNull PsiElement element, @NotNull A a, @NotNull B b, @NotNull C c) { - return new DiagnosticWithPsiElement(this, severity, makeMessage(a, b, c), element); + return new DiagnosticWithPsiElementImpl(this, severity, makeMessage(a, b, c), element); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/RedeclarationDiagnostic.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/RedeclarationDiagnostic.java index 9fbb737d3b1..eafe8595cab 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/RedeclarationDiagnostic.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/RedeclarationDiagnostic.java @@ -1,46 +1,79 @@ package org.jetbrains.jet.lang.diagnostics; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.resolve.BindingContext; import static org.jetbrains.jet.lang.diagnostics.Severity.ERROR; /** -* @author abreslav -*/ -public class RedeclarationDiagnostic implements Diagnostic { + * @author abreslav + */ +public interface RedeclarationDiagnostic extends DiagnosticWithPsiElement { + public class SimpleRedeclarationDiagnostic extends DiagnosticWithPsiElementImpl implements RedeclarationDiagnostic { - private final DeclarationDescriptor a; - private final DeclarationDescriptor b; - - public RedeclarationDiagnostic(DeclarationDescriptor a, DeclarationDescriptor b) { - this.a = a; - this.b = b; + public SimpleRedeclarationDiagnostic(@NotNull PsiElement psiElement) { + super(RedeclarationDiagnosticFactory.INSTANCE, ERROR, "Redeclaration", psiElement); + } } - public DeclarationDescriptor getA() { - return a; + public class RedeclarationDiagnosticWithDeferredResolution implements RedeclarationDiagnostic { + + private final DeclarationDescriptor duplicatingDescriptor; + private final BindingContext contextToResolveToDeclaration; + private PsiElement element; + + public RedeclarationDiagnosticWithDeferredResolution(@NotNull DeclarationDescriptor duplicatingDescriptor, @NotNull BindingContext contextToResolveToDeclaration) { + this.duplicatingDescriptor = duplicatingDescriptor; + this.contextToResolveToDeclaration = contextToResolveToDeclaration; + } + + private PsiElement resolve() { + if (element == null) { + element = contextToResolveToDeclaration.get(BindingContext.DESCRIPTOR_TO_DECLARATION, duplicatingDescriptor); + assert element != null : "No element for descriptor: " + duplicatingDescriptor; + } + return element; + } + + @NotNull + @Override + public PsiElement getPsiElement() { + return resolve(); + } + + @NotNull + @Override + public TextRange getTextRange() { + return resolve().getTextRange(); + } + + @NotNull + @Override + public PsiFile getPsiFile() { + return resolve().getContainingFile(); + } + + @NotNull + @Override + public DiagnosticFactory getFactory() { + return Errors.REDECLARATION; + } + + @NotNull + @Override + public String getMessage() { + return "Redeclaration"; + } + + @NotNull + @Override + public Severity getSeverity() { + return ERROR; + } } - public DeclarationDescriptor getB() { - return b; - } - - @NotNull - @Override - public DiagnosticFactory getFactory() { - return RedeclarationDiagnosticFactory.INSTANCE; - } - - @NotNull - @Override - public String getMessage() { - return "Redeclaration"; - } - - @NotNull - @Override - public Severity getSeverity() { - return ERROR; - } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/RedeclarationDiagnosticFactory.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/RedeclarationDiagnosticFactory.java index 5ebd2be9fb5..c9303288d18 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/RedeclarationDiagnosticFactory.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/RedeclarationDiagnosticFactory.java @@ -1,33 +1,40 @@ package org.jetbrains.jet.lang.diagnostics; import com.intellij.openapi.util.TextRange; -import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.psi.JetNamedDeclaration; +import org.jetbrains.jet.lang.resolve.BindingContext; /** * @author abreslav */ -public class RedeclarationDiagnosticFactory implements DiagnosticFactory { +public class RedeclarationDiagnosticFactory extends AbstractDiagnosticFactory { public static final RedeclarationDiagnosticFactory INSTANCE = new RedeclarationDiagnosticFactory(); public RedeclarationDiagnosticFactory() {} - public RedeclarationDiagnostic on(DeclarationDescriptor a, DeclarationDescriptor b) { - return new RedeclarationDiagnostic(a, b); + public RedeclarationDiagnostic on(@NotNull PsiElement duplicatingElement) { + return new RedeclarationDiagnostic.SimpleRedeclarationDiagnostic(duplicatingElement); + } + + public Diagnostic on(DeclarationDescriptor duplicatingDescriptor, BindingContext contextToResolveToDeclaration) { + return new RedeclarationDiagnostic.RedeclarationDiagnosticWithDeferredResolution(duplicatingDescriptor, contextToResolveToDeclaration); } @NotNull @Override public TextRange getTextRange(@NotNull Diagnostic diagnostic) { - throw new UnsupportedOperationException(); // TODO - } - - @NotNull - @Override - public PsiFile getPsiFile(@NotNull Diagnostic diagnostic) { - throw new UnsupportedOperationException(); // TODO + PsiElement redeclaration = ((RedeclarationDiagnostic) diagnostic).getPsiElement(); + if (redeclaration instanceof JetNamedDeclaration) { + PsiElement nameIdentifier = ((JetNamedDeclaration) redeclaration).getNameIdentifier(); + if (nameIdentifier != null) { + return nameIdentifier.getTextRange(); + } + } + return redeclaration.getTextRange(); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/SimpleDiagnosticFactoryWithPsiElement.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/SimpleDiagnosticFactoryWithPsiElement.java index 4d8a7d4b7ee..89c1929ca7a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/SimpleDiagnosticFactoryWithPsiElement.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/SimpleDiagnosticFactoryWithPsiElement.java @@ -18,7 +18,7 @@ public abstract class SimpleDiagnosticFactoryWithPsiElement(this, severity, message, element, node.getTextRange()); + return new DiagnosticWithPsiElementImpl(this, severity, message, element, node.getTextRange()); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/UnresolvedReferenceDiagnostic.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/UnresolvedReferenceDiagnostic.java index ebe70e62ed3..3e41219d46a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/UnresolvedReferenceDiagnostic.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/UnresolvedReferenceDiagnostic.java @@ -8,7 +8,7 @@ import static org.jetbrains.jet.lang.diagnostics.Severity.ERROR; /** * @author abreslav */ -public class UnresolvedReferenceDiagnostic extends DiagnosticWithPsiElement { +public class UnresolvedReferenceDiagnostic extends DiagnosticWithPsiElementImpl { public UnresolvedReferenceDiagnostic(JetReferenceExpression referenceExpression) { super(Errors.UNRESOLVED_REFERENCE, ERROR, "Unresolved reference", referenceExpression); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java index 2da63a0e2d6..3a99064cff3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java @@ -106,7 +106,9 @@ public class JetExpressionParsing extends AbstractJetParsing { COLON_AS(COLON, AS_KEYWORD, AS_SAFE) { @Override public JetNodeType parseRightHandSide(IElementType operation, JetExpressionParsing parser) { + parser.myBuilder.disableJoiningComplexTokens(); parser.myJetParsing.parseTypeRef(); + parser.myBuilder.enableJoiningComplexTokens(); return BINARY_WITH_TYPE; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunctionLiteral.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunctionLiteral.java index 976b8d04d62..6f20e9a1478 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunctionLiteral.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunctionLiteral.java @@ -3,6 +3,7 @@ package org.jetbrains.jet.lang.psi; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lexer.JetTokens; /** @@ -36,4 +37,20 @@ public class JetFunctionLiteral extends JetFunction { public JetBlockExpression getBodyExpression() { return (JetBlockExpression) super.getBodyExpression(); } + + @NotNull + public ASTNode getOpenBraceNode() { + return getNode().findChildByType(JetTokens.LBRACE); + } + + @Nullable + @IfNotParsed + public ASTNode getClosingBraceNode() { + return getNode().findChildByType(JetTokens.RBRACE); + } + + @Nullable + public ASTNode getArrowNode() { + return getNode().findChildByType(JetTokens.DOUBLE_ARROW); + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunctionLiteralExpression.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunctionLiteralExpression.java index a91fbac044e..070bf524ff3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunctionLiteralExpression.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunctionLiteralExpression.java @@ -2,7 +2,9 @@ package org.jetbrains.jet.lang.psi; import com.intellij.lang.ASTNode; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.JetNodeTypes; +import org.jetbrains.jet.lexer.JetTokens; /** * @author max @@ -47,4 +49,5 @@ public class JetFunctionLiteralExpression extends JetExpression implements JetDe public JetElement asElement() { return this; } + } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AbstractScopeAdapter.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AbstractScopeAdapter.java index a75b1ed3be4..f9624422740 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AbstractScopeAdapter.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AbstractScopeAdapter.java @@ -2,9 +2,11 @@ package org.jetbrains.jet.lang.resolve; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; import java.util.Collection; +import java.util.List; /** * @author abreslav @@ -15,8 +17,13 @@ public abstract class AbstractScopeAdapter implements JetScope { @NotNull @Override - public JetType getThisType() { - return getWorkerScope().getThisType(); + public ReceiverDescriptor getImplicitReceiver() { + return getWorkerScope().getImplicitReceiver(); + } + + @Override + public void getImplicitReceiversHierarchy(@NotNull List result) { + getWorkerScope().getImplicitReceiversHierarchy(result); } @NotNull @@ -62,6 +69,7 @@ public abstract class AbstractScopeAdapter implements JetScope { return getWorkerScope().getDeclarationDescriptorForUnqualifiedThis(); } + @NotNull @Override public Collection getAllDescriptors() { return getWorkerScope().getAllDescriptors(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java index 3ca2ef052c1..94e330a7756 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java @@ -18,6 +18,9 @@ import org.jetbrains.jet.lang.diagnostics.*; import org.jetbrains.jet.lang.psi.JetDeclaration; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetNamespace; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.WritableScope; +import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; import java.util.Collections; @@ -69,7 +72,7 @@ public class AnalyzingUtils { JetScope libraryScope = semanticServices.getStandardLibrary().getLibraryScope(); ModuleDescriptor owner = new ModuleDescriptor(""); - final WritableScope scope = new WritableScopeImpl(libraryScope, owner, bindingTraceContext).setDebugName("Root scope in analyzeNamespace"); + final WritableScope scope = new WritableScopeImpl(libraryScope, owner, new TraceBasedRedeclarationHandler(bindingTraceContext)).setDebugName("Root scope in analyzeNamespace"); importingStrategy.addImports(project, semanticServices, bindingTraceContext, scope); TopDownAnalyzer.process(semanticServices, bindingTraceContext, scope, new NamespaceLike.Adapter(owner) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java index 20506d72c01..ba70a94aee1 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnnotationResolver.java @@ -10,6 +10,7 @@ import org.jetbrains.jet.lang.psi.JetAnnotationEntry; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetModifierList; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetTypeInferrer; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java index f0f64418c2b..b9f7086b750 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContext.java @@ -7,6 +7,7 @@ import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.util.slicedmap.*; @@ -32,7 +33,8 @@ public interface BindingContext { WritableSlice RESOLUTION_SCOPE = Slices.createSimpleSlice("RESOLUTION_SCOPE"); WritableSlice VARIABLE_REASSIGNMENT = Slices.createSimpleSetSlice("VARIABLE_REASSIGNMENT"); - WritableSlice VARIABLE_ASSIGNMENT = Slices.createSimpleSlice("VARIABLE_ASSIGNMENT"); + WritableSlice AUTO_CREATED_IT = Slices.createSimpleSetSlice("AUTO_CREATED_IT"); + WritableSlice VARIABLE_ASSIGNMENT = Slices.createSimpleSlice("VARIABLE_ASSIGNMENT"); WritableSlice PROCESSED = Slices.createSimpleSetSlice("PROCESSED"); WritableSlice STATEMENT = Slices.createRemovableSetSlice("STATEMENT"); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java index 2da0eb2866b..64ceb724c88 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java @@ -10,6 +10,11 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.WritableScope; +import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionCallableReceiver; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.util.slicedmap.WritableSlice; @@ -500,12 +505,12 @@ public class BodyResolver { @NotNull private JetScope getInnerScopeForConstructor(@NotNull ConstructorDescriptor descriptor, @NotNull JetScope declaringScope, boolean primary) { - WritableScope constructorScope = new WritableScopeImpl(declaringScope, declaringScope.getContainingDeclaration(), context.getTrace()).setDebugName("Inner scope for constructor"); + WritableScope constructorScope = new WritableScopeImpl(declaringScope, declaringScope.getContainingDeclaration(), new TraceBasedRedeclarationHandler(context.getTrace())).setDebugName("Inner scope for constructor"); for (PropertyDescriptor propertyDescriptor : ((MutableClassDescriptor) descriptor.getContainingDeclaration()).getProperties()) { constructorScope.addPropertyDescriptorByFieldName("$" + propertyDescriptor.getName(), propertyDescriptor); } - constructorScope.setThisType(descriptor.getContainingDeclaration().getDefaultType()); +// constructorScope.setImplicitReceiver(new ClassReceiver(descriptor.getContainingDeclaration())); for (ValueParameterDescriptor valueParameterDescriptor : descriptor.getValueParameters()) { JetParameter parameter = (JetParameter) context.getTrace().getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, valueParameterDescriptor); @@ -567,13 +572,13 @@ public class BodyResolver { } private JetScope getPropertyDeclarationInnerScope(@NotNull JetScope outerScope, @NotNull PropertyDescriptor propertyDescriptor) { - WritableScopeImpl result = new WritableScopeImpl(outerScope, propertyDescriptor, context.getTrace()).setDebugName("Property declaration inner scope"); + WritableScopeImpl result = new WritableScopeImpl(outerScope, propertyDescriptor, new TraceBasedRedeclarationHandler(context.getTrace())).setDebugName("Property declaration inner scope"); for (TypeParameterDescriptor typeParameterDescriptor : propertyDescriptor.getTypeParameters()) { result.addTypeParameterDescriptor(typeParameterDescriptor); } JetType receiverType = propertyDescriptor.getReceiverType(); if (receiverType != null) { - result.setThisType(receiverType); + result.setImplicitReceiver(new ExtensionCallableReceiver(propertyDescriptor)); } return result; } @@ -581,7 +586,7 @@ public class BodyResolver { private void resolvePropertyAccessors(JetProperty property, PropertyDescriptor propertyDescriptor, JetScope declaringScope) { BindingTraceAdapter fieldAccessTrackingTrace = createFieldTrackingTrace(propertyDescriptor); - WritableScope accessorScope = new WritableScopeImpl(getPropertyDeclarationInnerScope(declaringScope, propertyDescriptor), declaringScope.getContainingDeclaration(), context.getTrace()).setDebugName("Accessor scope"); + WritableScope accessorScope = new WritableScopeImpl(getPropertyDeclarationInnerScope(declaringScope, propertyDescriptor), declaringScope.getContainingDeclaration(), new TraceBasedRedeclarationHandler(context.getTrace())).setDebugName("Accessor scope"); accessorScope.addPropertyDescriptorByFieldName("$" + propertyDescriptor.getName(), propertyDescriptor); JetPropertyAccessor getter = property.getGetter(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java index 122108346c5..d46c0706303 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java @@ -17,6 +17,9 @@ import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.diagnostics.Errors; import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.WritableScope; +import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lexer.JetTokens; @@ -142,7 +145,7 @@ public class ClassDescriptorResolver { annotationResolver.resolveAnnotations(scope, function.getModifierList()), JetPsiUtil.safeName(function.getName()) ); - WritableScope innerScope = new WritableScopeImpl(scope, functionDescriptor, trace).setDebugName("Function descriptor header scope"); + WritableScope innerScope = new WritableScopeImpl(scope, functionDescriptor, new TraceBasedRedeclarationHandler(trace)).setDebugName("Function descriptor header scope"); innerScope.addLabeledDeclaration(functionDescriptor); List typeParameterDescriptors = resolveTypeParameters(functionDescriptor, innerScope, function.getTypeParameters()); @@ -451,7 +454,7 @@ public class ClassDescriptorResolver { typeParameterDescriptors = Collections.emptyList(); } else { - WritableScope writableScope = new WritableScopeImpl(scope, containingDeclaration, trace).setDebugName("Scope with type parameters of a property"); + WritableScope writableScope = new WritableScopeImpl(scope, containingDeclaration, new TraceBasedRedeclarationHandler(trace)).setDebugName("Scope with type parameters of a property"); typeParameterDescriptors = resolveTypeParameters(containingDeclaration, writableScope, typeParameters); resolveGenericBounds(property, writableScope, typeParameterDescriptors); scopeWithTypeParameters = writableScope; @@ -659,7 +662,7 @@ public class ClassDescriptorResolver { typeParameters, resolveValueParameters( constructorDescriptor, - new WritableScopeImpl(scope, classDescriptor, trace).setDebugName("Scope with value parameters of a constructor"), + new WritableScopeImpl(scope, classDescriptor, new TraceBasedRedeclarationHandler(trace)).setDebugName("Scope with value parameters of a constructor"), valueParameters), Modality.FINAL); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationResolver.java index 6aca3fe1866..3048ec1503a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationResolver.java @@ -4,6 +4,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import java.util.List; import java.util.Map; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportingStrategy.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportingStrategy.java index 546545cc36a..1671b51fa74 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportingStrategy.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportingStrategy.java @@ -2,6 +2,7 @@ package org.jetbrains.jet.lang.resolve; import com.intellij.openapi.project.Project; import org.jetbrains.jet.lang.JetSemanticServices; +import org.jetbrains.jet.lang.resolve.scopes.WritableScope; /** * @author abreslav diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/JetModuleUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/JetModuleUtil.java index 83b7b08e240..a23a151f168 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/JetModuleUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/JetModuleUtil.java @@ -1,6 +1,7 @@ package org.jetbrains.jet.lang.resolve; import org.jetbrains.jet.lang.psi.JetElement; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.types.NamespaceType; /** diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisContext.java index 7fc9a95c460..225a7069436 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisContext.java @@ -5,6 +5,8 @@ import com.google.common.collect.Sets; import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import java.util.Map; import java.util.Set; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index 47d569b259b..ac6a81e01ce 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -5,6 +5,8 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import java.util.Collections; import java.util.List; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TraceBasedRedeclarationHandler.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TraceBasedRedeclarationHandler.java new file mode 100644 index 00000000000..299b6f63455 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TraceBasedRedeclarationHandler.java @@ -0,0 +1,35 @@ +package org.jetbrains.jet.lang.resolve; + +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.resolve.scopes.RedeclarationHandler; + +import static org.jetbrains.jet.lang.diagnostics.Errors.REDECLARATION; + +/** + * @author abreslav + */ +public class TraceBasedRedeclarationHandler implements RedeclarationHandler { + private final BindingTrace trace; + + public TraceBasedRedeclarationHandler(@NotNull BindingTrace trace) { + this.trace = trace; + } + + @Override + public void handleRedeclaration(@NotNull DeclarationDescriptor first, @NotNull DeclarationDescriptor second) { + report(first); + report(second); + } + + private void report(DeclarationDescriptor first) { + PsiElement firstElement = trace.get(BindingContext.DESCRIPTOR_TO_DECLARATION, first); + if (firstElement != null) { + trace.report(REDECLARATION.on(firstElement)); + } + else { + trace.report(REDECLARATION.on(first, trace.getBindingContext())); + } + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java index 48e6a50b829..3bab1a2d111 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java @@ -11,6 +11,9 @@ import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; +import org.jetbrains.jet.lang.resolve.scopes.WriteThroughScope; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lexer.JetTokens; @@ -71,13 +74,13 @@ public class TypeHierarchyResolver { Collections.emptyList(), // TODO: annotations name ); - namespaceDescriptor.initialize(new WritableScopeImpl(JetScope.EMPTY, namespaceDescriptor, context.getTrace()).setDebugName("Namespace member scope")); + namespaceDescriptor.initialize(new WritableScopeImpl(JetScope.EMPTY, namespaceDescriptor, new TraceBasedRedeclarationHandler(context.getTrace())).setDebugName("Namespace member scope")); owner.addNamespace(namespaceDescriptor); context.getTrace().record(BindingContext.NAMESPACE, namespace, namespaceDescriptor); } context.getNamespaceDescriptors().put(namespace, namespaceDescriptor); - WriteThroughScope namespaceScope = new WriteThroughScope(outerScope, namespaceDescriptor.getMemberScope(), context.getTrace()); + WriteThroughScope namespaceScope = new WriteThroughScope(outerScope, namespaceDescriptor.getMemberScope(), new TraceBasedRedeclarationHandler(context.getTrace())); context.getNamespaceScopes().put(namespace, namespaceScope); processImports(namespace, namespaceScope, outerScope); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java index ec7da04365a..0b023d82c01 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeResolver.java @@ -9,6 +9,8 @@ import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.LazyScopeAdapter; import org.jetbrains.jet.lang.types.*; import java.util.ArrayList; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java index b03aad99a9e..5a8af24287b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java @@ -12,9 +12,9 @@ import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.*; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.inference.ConstraintSystem; -import org.jetbrains.jet.resolve.DescriptorRenderer; import java.util.*; @@ -355,6 +355,7 @@ public class CallResolver { if (error) { failedCandidates.add(candidate); + checkTypesWithNoCallee(temporaryTrace, scope, task.getTypeArguments(), task.getValueArguments(), task.getFunctionLiteralArguments()); continue; } @@ -490,7 +491,7 @@ public class CallResolver { } } - private Function createMapFunction(Descriptor substitutedFunctionDescriptor) { + private Function createMapFunction(D substitutedFunctionDescriptor) { assert substitutedFunctionDescriptor != null; final Map parameterMap = Maps.newHashMap(); for (ValueParameterDescriptor valueParameterDescriptor : substitutedFunctionDescriptor.getValueParameters()) { @@ -505,7 +506,7 @@ public class CallResolver { }; } - private boolean checkReceiver(ResolutionTask task, TracingStrategy tracing, Descriptor candidate, TemporaryBindingTrace temporaryTrace) { + private boolean checkReceiver(ResolutionTask task, TracingStrategy tracing, D candidate, TemporaryBindingTrace temporaryTrace) { if (!checkReceiverAbsence(task, tracing, candidate, temporaryTrace)) return false; JetType receiverType = task.getReceiverType(); JetType candidateReceiverType = candidate.getReceiverType(); @@ -518,7 +519,7 @@ public class CallResolver { return true; } - private boolean checkReceiverAbsence(ResolutionTask task, TracingStrategy tracing, Descriptor candidate, TemporaryBindingTrace temporaryTrace) { + private boolean checkReceiverAbsence(ResolutionTask task, TracingStrategy tracing, D candidate, TemporaryBindingTrace temporaryTrace) { JetType receiverType = task.getReceiverType(); JetType candidateReceiverType = candidate.getReceiverType(); if (receiverType != null) { @@ -535,26 +536,26 @@ public class CallResolver { } @NotNull - private OverloadResolutionResult computeResultAndReportErrors(BindingTrace trace, TracingStrategy tracing, Map successfulCandidates, Set failedCandidates, Set dirtyCandidates, Map traces) { + private OverloadResolutionResult computeResultAndReportErrors(BindingTrace trace, TracingStrategy tracing, Map successfulCandidates, Set failedCandidates, Set dirtyCandidates, Map traces) { // TODO : maybe it's better to filter overrides out first, and only then look for the maximally specific if (successfulCandidates.size() > 0) { if (successfulCandidates.size() != 1) { - Map cleanCandidates = Maps.newLinkedHashMap(successfulCandidates); + Map cleanCandidates = Maps.newLinkedHashMap(successfulCandidates); cleanCandidates.keySet().removeAll(dirtyCandidates); if (cleanCandidates.isEmpty()) { cleanCandidates = successfulCandidates; } - Descriptor maximallySpecific = overloadingConflictResolver.findMaximallySpecific(cleanCandidates, traces, false); + D maximallySpecific = overloadingConflictResolver.findMaximallySpecific(cleanCandidates, traces, false); if (maximallySpecific != null) { return OverloadResolutionResult.success(maximallySpecific); } - Descriptor maximallySpecificGenericsDiscriminated = overloadingConflictResolver.findMaximallySpecific(cleanCandidates, traces, true); + D maximallySpecificGenericsDiscriminated = overloadingConflictResolver.findMaximallySpecific(cleanCandidates, traces, true); if (maximallySpecificGenericsDiscriminated != null) { return OverloadResolutionResult.success(maximallySpecificGenericsDiscriminated); } - Set noOverrides = filterOverrides(successfulCandidates.keySet()); + Set noOverrides = filterOverrides(successfulCandidates.keySet()); if (dirtyCandidates.isEmpty()) { // tracing.reportOverallResolutionError(trace, "Overload resolution ambiguity: " // + makeErrorMessageForMultipleDescriptors(noOverrides)); @@ -566,9 +567,9 @@ public class CallResolver { return OverloadResolutionResult.ambiguity(noOverrides); } else { - Map.Entry entry = successfulCandidates.entrySet().iterator().next(); - Descriptor functionDescriptor = entry.getKey(); - Descriptor result = entry.getValue(); + Map.Entry entry = successfulCandidates.entrySet().iterator().next(); + D functionDescriptor = entry.getKey(); + D result = entry.getValue(); TemporaryBindingTrace temporaryTrace = traces.get(functionDescriptor); temporaryTrace.commit(); @@ -577,7 +578,7 @@ public class CallResolver { } else if (!failedCandidates.isEmpty()) { if (failedCandidates.size() != 1) { - Set noOverrides = filterOverrides(failedCandidates); + Set noOverrides = filterOverrides(failedCandidates); if (noOverrides.size() != 1) { // tracing.reportOverallResolutionError(trace, "None of the following functions can be called with the arguments supplied: " // + makeErrorMessageForMultipleDescriptors(noOverrides)); @@ -587,7 +588,7 @@ public class CallResolver { } failedCandidates = noOverrides; } - Descriptor functionDescriptor = failedCandidates.iterator().next(); + D functionDescriptor = failedCandidates.iterator().next(); TemporaryBindingTrace temporaryTrace = traces.get(functionDescriptor); temporaryTrace.commit(); return OverloadResolutionResult.singleFailedCandidate(failedCandidates.iterator().next()); @@ -598,19 +599,11 @@ public class CallResolver { } } - private StringBuilder makeErrorMessageForMultipleDescriptors(Set candidates) { - StringBuilder stringBuilder = new StringBuilder("\n"); - for (Descriptor functionDescriptor : candidates) { - stringBuilder.append(DescriptorRenderer.TEXT.render(functionDescriptor)).append("\n"); - } - return stringBuilder; - } - - private Set filterOverrides(Set candidateSet) { - Set candidates = Sets.newLinkedHashSet(); + private Set filterOverrides(Set candidateSet) { + Set candidates = Sets.newLinkedHashSet(); outerLoop: - for (Descriptor me : candidateSet) { - for (Descriptor other : candidateSet) { + for (D me : candidateSet) { + for (D other : candidateSet) { if (OverloadingConflictResolver.overrides(other, me)) { continue outerLoop; } @@ -718,18 +711,6 @@ public class CallResolver { return found; } - private OverloadResolutionResult listToOverloadResolutionResult(List result) { - if (result.isEmpty()) { - return OverloadResolutionResult.nameNotFound(); - } - else if (result.size() == 1) { - return OverloadResolutionResult.success(result.get(0)); - } - else { - return OverloadResolutionResult.ambiguity(result); - } - } - private boolean findExtensionFunctions(Collection candidates, JetType receiverType, List parameterTypes, List result) { boolean found = false; for (FunctionDescriptor functionDescriptor : candidates) { @@ -755,7 +736,6 @@ public class CallResolver { return true; } - private static TaskPrioritizer FUNCTION_TASK_PRIORITIZER = new TaskPrioritizer() { @NotNull @@ -825,7 +805,6 @@ public class CallResolver { } }; - private static TaskPrioritizer PROPERTY_TASK_PRIORITIZER = new TaskPrioritizer() { @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizer.java index 9d1d56592c7..96a668739de 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/TaskPrioritizer.java @@ -6,8 +6,10 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.psi.Call; -import org.jetbrains.jet.lang.resolve.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.types.JetType; import java.util.Collection; @@ -44,6 +46,9 @@ import java.util.List; * local extension prevail over members (and members prevail over all non-local extensions) */ public static boolean isLocal(DeclarationDescriptor containerOfTheCurrentLocality, DeclarationDescriptor candidate) { + if (candidate instanceof ValueParameterDescriptor) { + return true; + } DeclarationDescriptor parent = candidate.getContainingDeclaration(); if (!(parent instanceof FunctionDescriptor)) { return false; @@ -59,11 +64,17 @@ import java.util.List; return false; } - public List> computePrioritizedTasks(JetScope scope, JetType receiverType, Call call, String name) { + public List> computePrioritizedTasks(@NotNull JetScope scope, @Nullable JetType receiverType, @NotNull Call call, @NotNull String name) { List> result = Lists.newArrayList(); + doComputeTasks(scope, receiverType, call, name, result); + return result; + } + + private void doComputeTasks(JetScope scope, JetType receiverType, Call call, String name, List> result) { + List receivers = Lists.newArrayList(); + scope.getImplicitReceiversHierarchy(receivers); if (receiverType != null) { Collection extensionFunctions = getExtensionsByName(scope, name); - List nonlocals = Lists.newArrayList(); List locals = Lists.newArrayList(); //noinspection unchecked,RedundantTypeArguments @@ -73,6 +84,12 @@ import java.util.List; addTask(result, receiverType, call, locals); addTask(result, null, call, members); + + for (ReceiverDescriptor receiver : receivers) { + Collection memberExtensions = getExtensionsByName(receiver.getReceiverType().getMemberScope(), name); + addTask(result, receiverType, call, memberExtensions); + } + addTask(result, receiverType, call, nonlocals); } else { @@ -85,9 +102,12 @@ import java.util.List; addTask(result, receiverType, call, locals); + for (ReceiverDescriptor receiver : receivers) { + doComputeTasks(scope, receiver.getReceiverType(), call, name, result); + } + addTask(result, receiverType, call, nonlocals); } - return result; } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ChainedScope.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/ChainedScope.java similarity index 88% rename from compiler/frontend/src/org/jetbrains/jet/lang/resolve/ChainedScope.java rename to compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/ChainedScope.java index d1edc538c0d..5b61003165e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ChainedScope.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/ChainedScope.java @@ -1,12 +1,14 @@ -package org.jetbrains.jet.lang.resolve; +package org.jetbrains.jet.lang.resolve.scopes; import com.google.common.collect.Sets; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import java.util.Collection; import java.util.Collections; +import java.util.List; /** * @author abreslav @@ -69,10 +71,17 @@ public class ChainedScope implements JetScope { @NotNull @Override - public JetType getThisType() { + public ReceiverDescriptor getImplicitReceiver() { throw new UnsupportedOperationException(); // TODO } + @Override + public void getImplicitReceiversHierarchy(@NotNull List result) { + for (JetScope jetScope : scopeChain) { + jetScope.getImplicitReceiversHierarchy(result); + } + } + @NotNull @Override public DeclarationDescriptor getContainingDeclaration() { @@ -115,6 +124,7 @@ public class ChainedScope implements JetScope { return null; } + @NotNull @Override public Collection getAllDescriptors() { if (allDescriptors == null) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/JetScope.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScope.java similarity index 68% rename from compiler/frontend/src/org/jetbrains/jet/lang/resolve/JetScope.java rename to compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScope.java index 93dcfa946eb..eb5bfb96890 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/JetScope.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScope.java @@ -1,11 +1,12 @@ -package org.jetbrains.jet.lang.resolve; +package org.jetbrains.jet.lang.resolve.scopes; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import java.util.Collection; +import java.util.List; /** * @author abreslav @@ -15,7 +16,7 @@ public interface JetScope { @NotNull @Override public DeclarationDescriptor getContainingDeclaration() { - throw new UnsupportedOperationException(); // TODO + throw new UnsupportedOperationException(); } @Override @@ -36,9 +37,6 @@ public interface JetScope { @NotNull FunctionGroup getFunctionGroup(@NotNull String name); - @NotNull - JetType getThisType(); - @NotNull DeclarationDescriptor getContainingDeclaration(); @@ -55,5 +53,18 @@ public interface JetScope { @Nullable DeclarationDescriptor getDeclarationDescriptorForUnqualifiedThis(); + @NotNull Collection getAllDescriptors(); + + /** + * @return EFFECTIVE implicit receiver at this point (may be corresponding to an outer scope) + */ + @NotNull + ReceiverDescriptor getImplicitReceiver(); + + /** + * Adds receivers to the list in order of locality, so that the closest (the most local) receiver goes first + * @param result + */ + void getImplicitReceiversHierarchy(@NotNull List result); } \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/JetScopeAdapter.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScopeAdapter.java similarity index 77% rename from compiler/frontend/src/org/jetbrains/jet/lang/resolve/JetScopeAdapter.java rename to compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScopeAdapter.java index a3b531bd831..248f00bee77 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/JetScopeAdapter.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScopeAdapter.java @@ -1,6 +1,7 @@ -package org.jetbrains.jet.lang.resolve; +package org.jetbrains.jet.lang.resolve.scopes; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.resolve.AbstractScopeAdapter; /** * @author abreslav diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/JetScopeImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScopeImpl.java similarity index 77% rename from compiler/frontend/src/org/jetbrains/jet/lang/resolve/JetScopeImpl.java rename to compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScopeImpl.java index fbbe8cf99e8..8eeec10a018 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/JetScopeImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/JetScopeImpl.java @@ -1,11 +1,12 @@ -package org.jetbrains.jet.lang.resolve; +package org.jetbrains.jet.lang.resolve.scopes; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.types.*; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import java.util.Collection; import java.util.Collections; +import java.util.List; /** * @author abreslav @@ -28,8 +29,8 @@ public abstract class JetScopeImpl implements JetScope { @NotNull @Override - public JetType getThisType() { - return JetStandardClasses.getNothingType(); + public ReceiverDescriptor getImplicitReceiver() { + return ReceiverDescriptor.NO_RECEIVER; } @NotNull @@ -54,8 +55,13 @@ public abstract class JetScopeImpl implements JetScope { return null; } + @NotNull @Override public Collection getAllDescriptors() { return Collections.emptyList(); } + + @Override + public void getImplicitReceiversHierarchy(@NotNull List result) { + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/LazyScopeAdapter.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/LazyScopeAdapter.java similarity index 79% rename from compiler/frontend/src/org/jetbrains/jet/lang/resolve/LazyScopeAdapter.java rename to compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/LazyScopeAdapter.java index 40a39ff5ca7..4cd937f0e76 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/LazyScopeAdapter.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/LazyScopeAdapter.java @@ -1,6 +1,7 @@ -package org.jetbrains.jet.lang.resolve; +package org.jetbrains.jet.lang.resolve.scopes; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.resolve.AbstractScopeAdapter; import org.jetbrains.jet.lang.types.LazyValue; /** diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/RedeclarationHandler.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/RedeclarationHandler.java new file mode 100644 index 00000000000..c123871fa46 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/RedeclarationHandler.java @@ -0,0 +1,23 @@ +package org.jetbrains.jet.lang.resolve.scopes; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; + +/** + * @author abreslav + */ +public interface RedeclarationHandler { + RedeclarationHandler DO_NOTHING = new RedeclarationHandler() { + @Override + public void handleRedeclaration(@NotNull DeclarationDescriptor first, @NotNull DeclarationDescriptor second) { + } + }; + RedeclarationHandler THROW_EXCEPTION = new RedeclarationHandler() { + @Override + public void handleRedeclaration(@NotNull DeclarationDescriptor first, @NotNull DeclarationDescriptor second) { + throw new IllegalStateException("Redeclaration: " + first + " and " + second + "(no line info available)"); + } + }; + + void handleRedeclaration(@NotNull DeclarationDescriptor first, @NotNull DeclarationDescriptor second); +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/SubstitutingScope.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/SubstitutingScope.java similarity index 90% rename from compiler/frontend/src/org/jetbrains/jet/lang/resolve/SubstitutingScope.java rename to compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/SubstitutingScope.java index 8d4392eee57..fb7497551f0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/SubstitutingScope.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/SubstitutingScope.java @@ -1,14 +1,15 @@ -package org.jetbrains.jet.lang.resolve; +package org.jetbrains.jet.lang.resolve.scopes; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.TypeSubstitutor; import java.util.Collection; +import java.util.List; import java.util.Map; /** @@ -56,7 +57,12 @@ public class SubstitutingScope implements JetScope { @NotNull @Override - public JetType getThisType() { + public ReceiverDescriptor getImplicitReceiver() { + throw new UnsupportedOperationException(); // TODO + } + + @Override + public void getImplicitReceiversHierarchy(@NotNull List result) { throw new UnsupportedOperationException(); // TODO } @@ -109,6 +115,7 @@ public class SubstitutingScope implements JetScope { return workerScope.getDeclarationDescriptorForUnqualifiedThis(); } + @NotNull @Override public Collection getAllDescriptors() { if (allDescriptors == null) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/WritableScope.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScope.java similarity index 83% rename from compiler/frontend/src/org/jetbrains/jet/lang/resolve/WritableScope.java rename to compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScope.java index 0e7485b4d2f..c052fb4a23e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/WritableScope.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScope.java @@ -1,9 +1,9 @@ -package org.jetbrains.jet.lang.resolve; +package org.jetbrains.jet.lang.resolve.scopes; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.types.*; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ImplicitReceiverDescriptor; /** * @author abreslav @@ -30,5 +30,5 @@ public interface WritableScope extends JetScope { void importScope(@NotNull JetScope imported); - void setThisType(@NotNull JetType thisType); + void setImplicitReceiver(@NotNull ImplicitReceiverDescriptor implicitReceiver); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/WritableScopeImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeImpl.java similarity index 86% rename from compiler/frontend/src/org/jetbrains/jet/lang/resolve/WritableScopeImpl.java rename to compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeImpl.java index 6d6065cc7c0..dbb5f057c23 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/WritableScopeImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeImpl.java @@ -1,4 +1,4 @@ -package org.jetbrains.jet.lang.resolve; +package org.jetbrains.jet.lang.resolve.scopes; import com.google.common.collect.Lists; import com.google.common.collect.Maps; @@ -6,13 +6,12 @@ import com.google.common.collect.Sets; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.diagnostics.DiagnosticHolder; -import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ImplicitReceiverDescriptor; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import java.util.*; -import static org.jetbrains.jet.lang.diagnostics.Errors.REDECLARATION; - /** * @author abreslav */ @@ -35,13 +34,12 @@ public class WritableScopeImpl extends WritableScopeWithImports { @Nullable private Map> labelsToDescriptors; + @Nullable - private JetType thisType; + private ImplicitReceiverDescriptor implicitReceiver; - private List variableDescriptors; - - public WritableScopeImpl(@NotNull JetScope scope, @NotNull DeclarationDescriptor owner, @NotNull DiagnosticHolder diagnosticHolder) { - super(scope, diagnosticHolder); + public WritableScopeImpl(@NotNull JetScope scope, @NotNull DeclarationDescriptor owner, @NotNull RedeclarationHandler redeclarationHandler) { + super(scope, redeclarationHandler); this.ownerDeclarationDescriptor = owner; } @@ -70,6 +68,7 @@ public class WritableScopeImpl extends WritableScopeWithImports { super.importClassifierAlias(importedClassifierName, classifierDescriptor); } + @NotNull @Override public Collection getAllDescriptors() { if (!allDescriptorsDone) { @@ -126,26 +125,16 @@ public class WritableScopeImpl extends WritableScopeWithImports { return variableClassOrNamespaceDescriptors; } - @NotNull - private List getVariableDescriptors() { - if (variableDescriptors == null) { - variableDescriptors = Lists.newArrayList(); - } - return variableDescriptors; - } - @Override public void addVariableDescriptor(@NotNull VariableDescriptor variableDescriptor) { Map variableClassOrNamespaceDescriptors = getVariableClassOrNamespaceDescriptors(); DeclarationDescriptor existingDescriptor = variableClassOrNamespaceDescriptors.get(variableDescriptor.getName()); if (existingDescriptor != null) { - diagnosticHolder.report(REDECLARATION.on(existingDescriptor, variableDescriptor)); + redeclarationHandler.handleRedeclaration(existingDescriptor, variableDescriptor); } // TODO : Should this always happen? variableClassOrNamespaceDescriptors.put(variableDescriptor.getName(), variableDescriptor); allDescriptors.add(variableDescriptor); - - getVariableDescriptors().add(variableDescriptor); } @Override @@ -156,12 +145,12 @@ public class WritableScopeImpl extends WritableScopeWithImports { return (VariableDescriptor) descriptor; } - if (thisType != null) { - VariableDescriptor variable = getThisType().getMemberScope().getVariable(name); - if (variable != null) { - return variable; - } - } +// if (implicitReceiver != null) { +// VariableDescriptor variable = getImplicitReceiver().getMemberScope().getVariable(name); +// if (variable != null) { +// return variable; +// } +// } VariableDescriptor variableDescriptor = getWorkerScope().getVariable(name); if (variableDescriptor != null) { @@ -203,9 +192,9 @@ public class WritableScopeImpl extends WritableScopeWithImports { result.addAllFunctions(functionGroup); } - if (thisType != null) { - result.addAllFunctions(getThisType().getMemberScope().getFunctionGroup(name)); - } +// if (implicitReceiver != null) { +// result.addAllFunctions(getImplicitReceiver().getMemberScope().getFunctionGroup(name)); +// } result.addAllFunctions(getWorkerScope().getFunctionGroup(name)); @@ -230,7 +219,7 @@ public class WritableScopeImpl extends WritableScopeWithImports { Map variableClassOrNamespaceDescriptors = getVariableClassOrNamespaceDescriptors(); DeclarationDescriptor originalDescriptor = variableClassOrNamespaceDescriptors.get(name); if (originalDescriptor != null) { - diagnosticHolder.report(REDECLARATION.on(originalDescriptor, classifierDescriptor)); + redeclarationHandler.handleRedeclaration(originalDescriptor, classifierDescriptor); } variableClassOrNamespaceDescriptors.put(name, classifierDescriptor); allDescriptors.add(classifierDescriptor); @@ -250,11 +239,11 @@ public class WritableScopeImpl extends WritableScopeWithImports { @NotNull @Override - public JetType getThisType() { - if (thisType == null) { - return super.getThisType(); + public ReceiverDescriptor getImplicitReceiver() { + if (implicitReceiver == null) { + return super.getImplicitReceiver(); } - return thisType; + return implicitReceiver; } @Override @@ -262,7 +251,7 @@ public class WritableScopeImpl extends WritableScopeWithImports { Map variableClassOrNamespaceDescriptors = getVariableClassOrNamespaceDescriptors(); DeclarationDescriptor oldValue = variableClassOrNamespaceDescriptors.put(namespaceDescriptor.getName(), namespaceDescriptor); if (oldValue != null) { - diagnosticHolder.report(REDECLARATION.on(oldValue, namespaceDescriptor)); + redeclarationHandler.handleRedeclaration(oldValue, namespaceDescriptor); } allDescriptors.add(namespaceDescriptor); } @@ -286,11 +275,19 @@ public class WritableScopeImpl extends WritableScopeWithImports { } @Override - public void setThisType(@NotNull JetType thisType) { - if (this.thisType != null) { + public void setImplicitReceiver(@NotNull ImplicitReceiverDescriptor implicitReceiver) { + if (this.implicitReceiver != null) { throw new UnsupportedOperationException("Receiver redeclared"); } - this.thisType = thisType; + this.implicitReceiver = implicitReceiver; + } + + @Override + public void getImplicitReceiversHierarchy(@NotNull List result) { + if (implicitReceiver != null && implicitReceiver != ReceiverDescriptor.NO_RECEIVER) { + result.add(implicitReceiver); + } + super.getImplicitReceiversHierarchy(result); } @SuppressWarnings({"NullableProblems"}) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/WritableScopeWithImports.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeWithImports.java similarity index 90% rename from compiler/frontend/src/org/jetbrains/jet/lang/resolve/WritableScopeWithImports.java rename to compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeWithImports.java index 6151d0f708a..00dee3bc289 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/WritableScopeWithImports.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WritableScopeWithImports.java @@ -1,9 +1,8 @@ -package org.jetbrains.jet.lang.resolve; +package org.jetbrains.jet.lang.resolve.scopes; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.diagnostics.DiagnosticHolder; import java.util.ArrayList; import java.util.List; @@ -18,11 +17,11 @@ public abstract class WritableScopeWithImports extends JetScopeAdapter implement @Nullable private List imports; private WritableScope currentIndividualImportScope; - protected final DiagnosticHolder diagnosticHolder; + protected final RedeclarationHandler redeclarationHandler; - public WritableScopeWithImports(@NotNull JetScope scope, @NotNull DiagnosticHolder diagnosticHolder) { + public WritableScopeWithImports(@NotNull JetScope scope, @NotNull RedeclarationHandler redeclarationHandler) { super(scope); - this.diagnosticHolder = diagnosticHolder; + this.redeclarationHandler = redeclarationHandler; } public WritableScopeWithImports setDebugName(@NotNull String debugName) { @@ -97,7 +96,7 @@ public abstract class WritableScopeWithImports extends JetScopeAdapter implement public void importClassifierAlias(@NotNull String importedClassifierName, @NotNull ClassifierDescriptor classifierDescriptor) { if (currentIndividualImportScope == null) { - WritableScopeImpl writableScope = new WritableScopeImpl(JetScope.EMPTY, getContainingDeclaration(), DiagnosticHolder.DO_NOTHING).setDebugName("Individual import scope"); + WritableScopeImpl writableScope = new WritableScopeImpl(EMPTY, getContainingDeclaration(), RedeclarationHandler.DO_NOTHING).setDebugName("Individual import scope"); importScope(writableScope); currentIndividualImportScope = writableScope; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/WriteThroughScope.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WriteThroughScope.java similarity index 88% rename from compiler/frontend/src/org/jetbrains/jet/lang/resolve/WriteThroughScope.java rename to compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WriteThroughScope.java index 3018808e29e..4c36fd0949e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/WriteThroughScope.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/WriteThroughScope.java @@ -1,11 +1,11 @@ -package org.jetbrains.jet.lang.resolve; +package org.jetbrains.jet.lang.resolve.scopes; import com.google.common.collect.Lists; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.diagnostics.DiagnosticHolder; -import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ImplicitReceiverDescriptor; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import java.util.Collection; @@ -16,8 +16,8 @@ public class WriteThroughScope extends WritableScopeWithImports { private final WritableScope writableWorker; private Collection allDescriptors; - public WriteThroughScope(@NotNull JetScope outerScope, @NotNull WritableScope scope, @NotNull DiagnosticHolder diagnosticHolder) { - super(outerScope, diagnosticHolder); + public WriteThroughScope(@NotNull JetScope outerScope, @NotNull WritableScope scope, @NotNull RedeclarationHandler redeclarationHandler) { + super(outerScope, redeclarationHandler); this.writableWorker = scope; } @@ -41,8 +41,8 @@ public class WriteThroughScope extends WritableScopeWithImports { @Override @NotNull - public JetType getThisType() { - return writableWorker.getThisType(); + public ReceiverDescriptor getImplicitReceiver() { + return writableWorker.getImplicitReceiver(); } @Override @@ -147,10 +147,11 @@ public class WriteThroughScope extends WritableScopeWithImports { } @Override - public void setThisType(@NotNull JetType thisType) { - writableWorker.setThisType(thisType); + public void setImplicitReceiver(@NotNull ImplicitReceiverDescriptor implicitReceiver) { + writableWorker.setImplicitReceiver(implicitReceiver); } + @NotNull @Override public Collection getAllDescriptors() { if (allDescriptors == null) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ClassReceiver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ClassReceiver.java new file mode 100644 index 00000000000..53cd89136e2 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ClassReceiver.java @@ -0,0 +1,13 @@ +package org.jetbrains.jet.lang.resolve.scopes.receivers; + +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; + +/** + * @author abreslav + */ +public class ClassReceiver extends ImplicitReceiverDescriptor { + + public ClassReceiver(ClassDescriptor classDescriptor) { + super(classDescriptor, classDescriptor.getDefaultType()); + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ExplicitReceiver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ExplicitReceiver.java new file mode 100644 index 00000000000..2b58bf569c8 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ExplicitReceiver.java @@ -0,0 +1,22 @@ +package org.jetbrains.jet.lang.resolve.scopes.receivers; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.types.JetType; + +/** + * @author abreslav + */ +public class ExplicitReceiver implements ReceiverDescriptor { + + private final JetType type; + + public ExplicitReceiver(@NotNull JetType type) { + this.type = type; + } + + @NotNull + @Override + public JetType getReceiverType() { + return type; + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ExtensionCallableReceiver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ExtensionCallableReceiver.java new file mode 100644 index 00000000000..2828c2c39b8 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ExtensionCallableReceiver.java @@ -0,0 +1,13 @@ +package org.jetbrains.jet.lang.resolve.scopes.receivers; + +import org.jetbrains.jet.lang.descriptors.CallableDescriptor; + +/** + * @author abreslav + */ +public class ExtensionCallableReceiver extends ImplicitReceiverDescriptor { + + public ExtensionCallableReceiver(CallableDescriptor callableDescriptor) { + super(callableDescriptor, callableDescriptor.getReceiverType()); + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ImplicitReceiverDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ImplicitReceiverDescriptor.java new file mode 100644 index 00000000000..8910ce1810a --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ImplicitReceiverDescriptor.java @@ -0,0 +1,32 @@ +package org.jetbrains.jet.lang.resolve.scopes.receivers; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.types.JetType; + +/** + * Describes a "this" receiver + * + * @author abreslav + */ +public abstract class ImplicitReceiverDescriptor implements ReceiverDescriptor { + private final JetType receiverType; + private final DeclarationDescriptor declarationDescriptor; + + protected ImplicitReceiverDescriptor(DeclarationDescriptor declarationDescriptor, JetType receiverType) { + this.receiverType = receiverType; + this.declarationDescriptor = declarationDescriptor; + } + + @Override + @NotNull + public JetType getReceiverType() { + return receiverType; + } + + @NotNull + public DeclarationDescriptor getDeclarationDescriptor() { + return declarationDescriptor; + } +} + diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ReceiverDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ReceiverDescriptor.java new file mode 100644 index 00000000000..c909cd5125a --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/scopes/receivers/ReceiverDescriptor.java @@ -0,0 +1,27 @@ +package org.jetbrains.jet.lang.resolve.scopes.receivers; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.types.JetStandardClasses; +import org.jetbrains.jet.lang.types.JetType; + +/** + * @author abreslav + */ +public interface ReceiverDescriptor { + + ReceiverDescriptor NO_RECEIVER = new ReceiverDescriptor() { + @NotNull + @Override + public JetType getReceiverType() { + return JetStandardClasses.getNothingType(); + } + + @Override + public String toString() { + return "NO_RECEIVER"; + } + }; + + @NotNull + JetType getReceiverType(); +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/DeferredType.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/DeferredType.java index fae49326ec9..b405df67340 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/DeferredType.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/DeferredType.java @@ -2,7 +2,7 @@ package org.jetbrains.jet.lang.types; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.resolve.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; import java.util.List; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/ErrorUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/ErrorUtils.java index 8c23eb4103f..ebcff036fb7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/ErrorUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/ErrorUtils.java @@ -3,7 +3,8 @@ package org.jetbrains.jet.lang.types; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.resolve.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; import java.util.*; @@ -32,8 +33,12 @@ public class ErrorUtils { @NotNull @Override - public JetType getThisType() { - return createErrorType(""); + public ReceiverDescriptor getImplicitReceiver() { + return ReceiverDescriptor.NO_RECEIVER; + } + + @Override + public void getImplicitReceiversHierarchy(@NotNull List result) { } @NotNull @@ -64,6 +69,7 @@ public class ErrorUtils { return ERROR_CLASS; // TODO : review } + @NotNull @Override public Collection getAllDescriptors() { return Collections.emptyList(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardClasses.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardClasses.java index f307299eb96..3ce7eb0d2d6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardClasses.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardClasses.java @@ -6,11 +6,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.diagnostics.DiagnosticHolder; -import org.jetbrains.jet.lang.resolve.JetScope; -import org.jetbrains.jet.lang.resolve.JetScopeImpl; -import org.jetbrains.jet.lang.resolve.WritableScope; -import org.jetbrains.jet.lang.resolve.WritableScopeImpl; +import org.jetbrains.jet.lang.resolve.scopes.*; import java.lang.reflect.Field; import java.lang.reflect.Modifier; @@ -198,7 +194,7 @@ public class JetStandardClasses { /*package*/ static final JetScope STANDARD_CLASSES; static { - WritableScope writableScope = new WritableScopeImpl(JetScope.EMPTY, STANDARD_CLASSES_NAMESPACE, DiagnosticHolder.DO_NOTHING).setDebugName("JetStandardClasses.STANDARD_CLASSES"); + WritableScope writableScope = new WritableScopeImpl(JetScope.EMPTY, STANDARD_CLASSES_NAMESPACE, RedeclarationHandler.DO_NOTHING).setDebugName("JetStandardClasses.STANDARD_CLASSES"); STANDARD_CLASSES = writableScope; writableScope.addClassifierAlias("Unit", getTuple(0)); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java index e1c19b1a575..1ec692c6930 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java @@ -9,9 +9,11 @@ import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionGroup; import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.diagnostics.DiagnosticHolder; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.resolve.*; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.RedeclarationHandler; +import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; import org.jetbrains.jet.plugin.JetFileType; import java.io.IOException; @@ -99,7 +101,7 @@ public class JetStandardLibrary { JetSemanticServices bootstrappingSemanticServices = JetSemanticServices.createSemanticServices(this); BindingTraceContext bindingTraceContext = new BindingTraceContext(); - WritableScopeImpl writableScope = new WritableScopeImpl(JetStandardClasses.STANDARD_CLASSES, JetStandardClasses.STANDARD_CLASSES_NAMESPACE, DiagnosticHolder.THROW_EXCEPTION).setDebugName("Root bootstrap scope"); + WritableScopeImpl writableScope = new WritableScopeImpl(JetStandardClasses.STANDARD_CLASSES, JetStandardClasses.STANDARD_CLASSES_NAMESPACE, RedeclarationHandler.THROW_EXCEPTION).setDebugName("Root bootstrap scope"); // this.libraryScope = bootstrappingTDA.process(JetStandardClasses.STANDARD_CLASSES, file.getRootNamespace().getDeclarations()); // bootstrappingTDA.process(writableScope, JetStandardClasses.STANDARD_CLASSES_NAMESPACE, file.getRootNamespace().getDeclarations()); TopDownAnalyzer.processStandardLibraryNamespace(bootstrappingSemanticServices, bindingTraceContext, writableScope, JetStandardClasses.STANDARD_CLASSES_NAMESPACE, file.getRootNamespace()); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetType.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetType.java index 930e9c2ae22..35d0c24f26a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetType.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetType.java @@ -2,7 +2,7 @@ package org.jetbrains.jet.lang.types; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.annotations.Annotated; -import org.jetbrains.jet.lang.resolve.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; import java.util.List; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeImpl.java index c5371ba11bb..69be07784c9 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeImpl.java @@ -6,7 +6,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotatedImpl; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.resolve.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; import java.util.Collections; import java.util.Iterator; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index 6950b92af0f..440a0451e62 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -23,6 +23,9 @@ import org.jetbrains.jet.lang.resolve.calls.CallResolver; import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResult; import org.jetbrains.jet.lang.resolve.constants.*; import org.jetbrains.jet.lang.resolve.constants.StringValue; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.WritableScope; +import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.util.slicedmap.WritableSlice; @@ -367,7 +370,7 @@ public class JetTypeInferrer { } DeclarationDescriptor containingDescriptor = outerScope.getContainingDeclaration(); - WritableScope scope = new WritableScopeImpl(outerScope, containingDescriptor, context.trace).setDebugName("getBlockReturnedType"); + WritableScope scope = new WritableScopeImpl(outerScope, containingDescriptor, new TraceBasedRedeclarationHandler(context.trace)).setDebugName("getBlockReturnedType"); return getBlockReturnedTypeWithWritableScope(scope, block, coercionStrategyForLastExpression, context); } @@ -891,7 +894,7 @@ public class JetTypeInferrer { if (receiverTypeRef != null) { receiverType = context.typeResolver.resolveType(context.scope, receiverTypeRef); } else { - receiverType = context.scope.getThisType(); + receiverType = context.scope.getImplicitReceiver().getReceiverType(); } FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl( @@ -899,36 +902,46 @@ public class JetTypeInferrer { List parameterTypes = new ArrayList(); List valueParameterDescriptors = Lists.newArrayList(); - List parameters = functionLiteral.getValueParameters(); + List declaredValueParameters = functionLiteral.getValueParameters(); JetType expectedType = context.expectedType; - - List valueParameters = null; + boolean functionTypeExpected = expectedType != NO_EXPECTED_TYPE && JetStandardClasses.isFunctionType(expectedType); - if (functionTypeExpected) { - valueParameters = JetStandardClasses.getValueParameters(functionDescriptor, expectedType); + List expectedValueParameters = (functionTypeExpected) + ? JetStandardClasses.getValueParameters(functionDescriptor, expectedType) + : null; + + if (functionTypeExpected && declaredValueParameters.isEmpty() && expectedValueParameters.size() == 1) { + ValueParameterDescriptor valueParameterDescriptor = expectedValueParameters.get(0); + ValueParameterDescriptor it = new ValueParameterDescriptorImpl( + functionDescriptor, 0, Collections.emptyList(), "it", valueParameterDescriptor.getInType(), valueParameterDescriptor.getOutType(), valueParameterDescriptor.hasDefaultValue(), valueParameterDescriptor.isVararg() + ); + valueParameterDescriptors.add(it); + parameterTypes.add(it.getOutType()); + context.trace.record(AUTO_CREATED_IT, it); } + else { + for (int i = 0; i < declaredValueParameters.size(); i++) { + JetParameter declaredParameter = declaredValueParameters.get(i); + JetTypeReference typeReference = declaredParameter.getTypeReference(); - for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) { - JetParameter parameter = parameters.get(i); - JetTypeReference typeReference = parameter.getTypeReference(); - - JetType type; - if (typeReference != null) { - type = context.typeResolver.resolveType(context.scope, typeReference); - } - else { - if (valueParameters != null) { - type = valueParameters.get(i).getOutType(); + JetType type; + if (typeReference != null) { + type = context.typeResolver.resolveType(context.scope, typeReference); } else { -// context.trace.getErrorHandler().genericError(parameter.getNode(), "Cannot infer a type for this parameter. To specify it explicitly use the {(p : Type) => ...} notation"); - context.trace.report(CANNOT_INFER_PARAMETER_TYPE.on(parameter)); - type = ErrorUtils.createErrorType("Cannot be inferred"); + if (expectedValueParameters != null && i < expectedValueParameters.size()) { + type = expectedValueParameters.get(i).getOutType(); + } + else { + // context.trace.getErrorHandler().genericError(declaredParameter.getNode(), "Cannot infer a type for this declaredParameter. To specify it explicitly use the {(p : Type) => ...} notation"); + context.trace.report(CANNOT_INFER_PARAMETER_TYPE.on(declaredParameter)); + type = ErrorUtils.createErrorType("Cannot be inferred"); + } } + ValueParameterDescriptor valueParameterDescriptor = context.classDescriptorResolver.resolveValueParameterDescriptor(functionDescriptor, declaredParameter, i, type); + parameterTypes.add(valueParameterDescriptor.getOutType()); + valueParameterDescriptors.add(valueParameterDescriptor); } - ValueParameterDescriptor valueParameterDescriptor = context.classDescriptorResolver.resolveValueParameterDescriptor(functionDescriptor, parameter, i, type); - parameterTypes.add(valueParameterDescriptor.getOutType()); - valueParameterDescriptors.add(valueParameterDescriptor); } JetType effectiveReceiverType; @@ -974,7 +987,11 @@ public class JetTypeInferrer { @Override public JetType visitParenthesizedExpression(JetParenthesizedExpression expression, TypeInferenceContext context) { - return context.services.checkType(getType(expression.getExpression(), context.replaceScope(context.scope)), expression, context); + JetExpression innerExpression = expression.getExpression(); + if (innerExpression == null) { + return null; + } + return context.services.checkType(getType(innerExpression, context.replaceScope(context.scope)), expression, context); } @Override @@ -1251,7 +1268,7 @@ public class JetTypeInferrer { } } else { - thisType = context.scope.getThisType(); + thisType = context.scope.getImplicitReceiver().getReceiverType(); DeclarationDescriptor declarationDescriptorForUnqualifiedThis = context.scope.getDeclarationDescriptorForUnqualifiedThis(); if (declarationDescriptorForUnqualifiedThis != null) { @@ -1814,7 +1831,7 @@ public class JetTypeInferrer { } protected WritableScopeImpl newWritableScopeImpl(JetScope scope, BindingTrace trace) { - return new WritableScopeImpl(scope, scope.getContainingDeclaration(), trace); + return new WritableScopeImpl(scope, scope.getContainingDeclaration(), new TraceBasedRedeclarationHandler(trace)); } @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/NamespaceType.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/NamespaceType.java index dad72cb210c..35702cf2dba 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/NamespaceType.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/NamespaceType.java @@ -2,7 +2,7 @@ package org.jetbrains.jet.lang.types; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.resolve.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; import java.util.List; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java index 7f548f50877..9745f1e646e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java @@ -3,7 +3,7 @@ package org.jetbrains.jet.lang.types; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; -import org.jetbrains.jet.lang.resolve.SubstitutingScope; +import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope; import java.util.ArrayList; import java.util.List; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java index 9d5a28a5844..ca595ac72cf 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java @@ -7,8 +7,8 @@ import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.resolve.ChainedScope; -import org.jetbrains.jet.lang.resolve.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.ChainedScope; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.util.CommonSuppliers; import java.util.*; diff --git a/docs/JVMLS_talk_2011.ppt b/docs/JVMLS_talk_2011.ppt new file mode 100755 index 00000000000..af8effa1b2b Binary files /dev/null and b/docs/JVMLS_talk_2011.ppt differ diff --git a/docs/JVMLS_workshop_2011.ppt b/docs/JVMLS_workshop_2011.ppt new file mode 100755 index 00000000000..04f20e155a5 Binary files /dev/null and b/docs/JVMLS_workshop_2011.ppt differ diff --git a/docs/Kotlin_OopenSystems.pages b/docs/Kotlin_OopenSystems.pages new file mode 100644 index 00000000000..438eb3a0b96 Binary files /dev/null and b/docs/Kotlin_OopenSystems.pages differ diff --git a/docs/OSCON_Kotlin.key b/docs/OSCON_Kotlin.key new file mode 100755 index 00000000000..74011b5995b Binary files /dev/null and b/docs/OSCON_Kotlin.key differ diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 184822264e8..48949cbb3f0 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -19,6 +19,11 @@ + + + + diff --git a/idea/src/org/jetbrains/jet/checkers/CheckerTestUtil.java b/idea/src/org/jetbrains/jet/checkers/CheckerTestUtil.java new file mode 100644 index 00000000000..edff0f640a1 --- /dev/null +++ b/idea/src/org/jetbrains/jet/checkers/CheckerTestUtil.java @@ -0,0 +1,316 @@ +package org.jetbrains.jet.checkers; + +import com.google.common.collect.*; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiFile; +import org.jetbrains.jet.lang.diagnostics.Diagnostic; +import org.jetbrains.jet.lang.resolve.BindingContext; + +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @author abreslav + */ +public class CheckerTestUtil { + public static final Comparator DIAGNOSTIC_COMPARATOR = new Comparator() { + @Override + public int compare(Diagnostic o1, Diagnostic o2) { + TextRange range1 = getTextRange(o1); + TextRange range2 = getTextRange(o2); + int startOffset1 = range1.getStartOffset(); + int startOffset2 = range2.getStartOffset(); + if (startOffset1 != startOffset2) { + // Start early -- go first + return startOffset1 - range2.getStartOffset(); + } + // start at the same offset, the one who end later is the outer, i.e. goes first + return range2.getEndOffset() - range1.getEndOffset(); + } + }; + private static final Pattern RANGE_START_OR_END_PATTERN = Pattern.compile("()|()"); + private static final Pattern INDIVIDUAL_DIAGNOSTIC_PATTERN = Pattern.compile("\\w+"); + + public interface DiagnosticDiffCallbacks { + void missingDiagnostic(String type, int expectedStart, int expectedEnd); + void unexpectedDiagnostic(String type, int actualStart, int actualEnd); + } + + public static void diagnosticsDiff(List expected, Collection actual, DiagnosticDiffCallbacks callbacks) { + Iterator expectedDiagnostics = expected.iterator(); + List sortedDiagnosticDescriptors = getSortedDiagnosticDescriptors(actual); + Iterator actualDiagnostics = sortedDiagnosticDescriptors.iterator(); + + DiagnosedRange currentExpected = safeAdvance(expectedDiagnostics); + DiagnosticDescriptor currentActual = safeAdvance(actualDiagnostics); + while (currentExpected != null || currentActual != null) { + if (currentExpected != null) { + if (currentActual == null) { + missingDiagnostics(callbacks, currentExpected); + currentExpected = safeAdvance(expectedDiagnostics); + } + else { + int expectedStart = currentExpected.getStart(); + int actualStart = currentActual.getStart(); + int expectedEnd = currentExpected.getEnd(); + int actualEnd = currentActual.getEnd(); + if (expectedStart < actualStart) { + missingDiagnostics(callbacks, currentExpected); + currentExpected = safeAdvance(expectedDiagnostics); + } + else if (expectedStart > actualStart) { + unexpectedDiagnostics(currentActual.getDiagnostics(), callbacks); + currentActual = safeAdvance(actualDiagnostics); + } + else if (expectedEnd > actualEnd) { + assert expectedStart == actualStart; + missingDiagnostics(callbacks, currentExpected); + currentExpected = safeAdvance(expectedDiagnostics); + } + else if (expectedEnd < actualEnd) { + assert expectedStart == actualStart; + unexpectedDiagnostics(currentActual.getDiagnostics(), callbacks); + currentActual = safeAdvance(actualDiagnostics); + } + else { + assert expectedStart == actualStart && expectedEnd == actualEnd; + Multiset actualDiagnosticTypes = currentActual.getDiagnosticTypeStrings(); + Multiset expectedDiagnosticTypes = currentExpected.getDiagnostics(); + if (!actualDiagnosticTypes.equals(expectedDiagnosticTypes)) { + Multiset expectedCopy = HashMultiset.create(expectedDiagnosticTypes); + expectedCopy.removeAll(actualDiagnosticTypes); + Multiset actualCopy = HashMultiset.create(actualDiagnosticTypes); + actualCopy.removeAll(expectedDiagnosticTypes); + + for (String type : expectedCopy) { + callbacks.missingDiagnostic(type, expectedStart, expectedEnd); + } + for (String type : actualCopy) { + callbacks.unexpectedDiagnostic(type, actualStart, actualEnd); + } + } + currentExpected = safeAdvance(expectedDiagnostics); + currentActual = safeAdvance(actualDiagnostics); + } + + } + } + else { + if (currentActual != null) { + unexpectedDiagnostics(currentActual.getDiagnostics(), callbacks); + currentActual = safeAdvance(actualDiagnostics); + } + else { + break; + } + } + +// assert expectedDiagnostics.hasNext() || actualDiagnostics.hasNext(); + } + } + + private static void unexpectedDiagnostics(List actual, DiagnosticDiffCallbacks callbacks) { + for (Diagnostic diagnostic : actual) { + TextRange textRange = getTextRange(diagnostic); + callbacks.unexpectedDiagnostic(diagnostic.getFactory().getName(), textRange.getStartOffset(), textRange.getEndOffset()); + } + } + + private static void missingDiagnostics(DiagnosticDiffCallbacks callbacks, DiagnosedRange currentExpected) { + for (String type : currentExpected.getDiagnostics()) { + callbacks.missingDiagnostic(type, currentExpected.getStart(), currentExpected.getEnd()); + } + } + + private static T safeAdvance(Iterator iterator) { + return iterator.hasNext() ? iterator.next() : null; + } + + public static String parseDiagnosedRanges(String text, List result) { + Matcher matcher = RANGE_START_OR_END_PATTERN.matcher(text); + + Stack opened = new Stack(); + + int offsetCompensation = 0; + + while (matcher.find()) { + int effectiveOffset = matcher.start() - offsetCompensation; + String matchedText = matcher.group(); + if ("".equals(matchedText)) { + opened.pop().setEnd(effectiveOffset); + } + else { + Matcher diagnosticTypeMatcher = INDIVIDUAL_DIAGNOSTIC_PATTERN.matcher(matchedText); + DiagnosedRange range = new DiagnosedRange(effectiveOffset); + while (diagnosticTypeMatcher.find()) { + range.addDiagnostic(diagnosticTypeMatcher.group()); + } + opened.push(range); + result.add(range); + } + offsetCompensation += matchedText.length(); + } + + assert opened.isEmpty() : "Stack is not empty"; + + matcher.reset(); + return matcher.replaceAll(""); + } + + public static StringBuffer addDiagnosticMarkersToText(PsiFile psiFile, BindingContext bindingContext) { + Collection diagnostics = bindingContext.getDiagnostics(); + + StringBuffer result = new StringBuffer(); + String text = psiFile.getText(); + if (!diagnostics.isEmpty()) { + List diagnosticDescriptors = getSortedDiagnosticDescriptors(diagnostics); + + Stack opened = new Stack(); + ListIterator iterator = diagnosticDescriptors.listIterator(); + DiagnosticDescriptor currentDescriptor = iterator.next(); + + for (int i = 0; i < text.length(); i++) { + char c = text.charAt(i); + while (!opened.isEmpty() && i == opened.peek().end) { + closeDiagnosticString(result); + opened.pop(); + } + while (currentDescriptor != null && i == currentDescriptor.start) { + openDiagnosticsString(result, currentDescriptor); + if (currentDescriptor.getEnd() == i) { + closeDiagnosticString(result); + } + else { + opened.push(currentDescriptor); + } + if (iterator.hasNext()) { + currentDescriptor = iterator.next(); + } + else { + currentDescriptor = null; + } + } + result.append(c); + } + while (!opened.isEmpty() && text.length() == opened.peek().end) { + closeDiagnosticString(result); + opened.pop(); + } + + assert opened.isEmpty() : "Stack is not empty"; + + } + else { + result.append(text); + } + return result; + } + + private static void openDiagnosticsString(StringBuffer result, DiagnosticDescriptor currentDescriptor) { + result.append(" iterator = currentDescriptor.diagnostics.iterator(); iterator.hasNext(); ) { + Diagnostic diagnostic = iterator.next(); + result.append(diagnostic.getFactory().getName()); + if (iterator.hasNext()) { + result.append(", "); + } + } + result.append("!>"); + } + + private static void closeDiagnosticString(StringBuffer result) { + result.append(""); + } + + private static List getSortedDiagnosticDescriptors(Collection diagnostics) { + List list = Lists.newArrayList(diagnostics); + Collections.sort(list, DIAGNOSTIC_COMPARATOR); + + List diagnosticDescriptors = Lists.newArrayList(); + DiagnosticDescriptor currentDiagnosticDescriptor = null; + for (Iterator iterator = list.iterator(); iterator.hasNext(); ) { + Diagnostic diagnostic = iterator.next(); + + TextRange textRange = getTextRange(diagnostic); + if (currentDiagnosticDescriptor != null && currentDiagnosticDescriptor.equalRange(textRange)) { + currentDiagnosticDescriptor.diagnostics.add(diagnostic); + } + else { + currentDiagnosticDescriptor = new DiagnosticDescriptor(textRange.getStartOffset(), textRange.getEndOffset(), diagnostic); + diagnosticDescriptors.add(currentDiagnosticDescriptor); + } + } + return diagnosticDescriptors; + } + + private static TextRange getTextRange(Diagnostic currentDiagnostic) { + return currentDiagnostic.getFactory().getTextRange(currentDiagnostic); + } + + private static class DiagnosticDescriptor { + private final int start; + private final int end; + private final List diagnostics = Lists.newArrayList(); + + DiagnosticDescriptor(int start, int end, Diagnostic diagnostic) { + this.start = start; + this.end = end; + this.diagnostics.add(diagnostic); + } + + public boolean equalRange(TextRange textRange) { + return start == textRange.getStartOffset() && end == textRange.getEndOffset(); + } + + public Multiset getDiagnosticTypeStrings() { + Multiset actualDiagnosticTypes = HashMultiset.create(); + for (Diagnostic diagnostic : diagnostics) { + actualDiagnosticTypes.add(diagnostic.getFactory().getName()); + } + return actualDiagnosticTypes; + } + + public int getStart() { + return start; + } + + public int getEnd() { + return end; + } + + public List getDiagnostics() { + return diagnostics; + } + } + + public static class DiagnosedRange { + private final int start; + private int end; + private final Multiset diagnostics = HashMultiset.create(); + + private DiagnosedRange(int start) { + this.start = start; + } + + public int getStart() { + return start; + } + + public int getEnd() { + return end; + } + + public Multiset getDiagnostics() { + return diagnostics; + } + + public void setEnd(int end) { + this.end = end; + } + + public void addDiagnostic(String diagnostic) { + diagnostics.add(diagnostic); + } + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/JetHighlighter.java b/idea/src/org/jetbrains/jet/plugin/JetHighlighter.java index 243f8a72e93..79903d2774b 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetHighlighter.java +++ b/idea/src/org/jetbrains/jet/plugin/JetHighlighter.java @@ -97,6 +97,24 @@ public class JetHighlighter extends SyntaxHighlighterBase { JET_AUTO_CAST_EXPRESSION = TextAttributesKey.createTextAttributesKey("JET.AUTO.CAST.EXPRESSION", clone); } + public static final TextAttributesKey JET_AUTOCREATED_IT; + + static { + TextAttributes attributes = new TextAttributes(); + attributes.setFontType(Font.BOLD); +// TODO: proper attributes + JET_AUTOCREATED_IT = TextAttributesKey.createTextAttributesKey("JET.AUTO.CREATED.IT", attributes); + } + + public static final TextAttributesKey JET_FUNCTION_LITERAL_DELIMITER; + + static { + TextAttributes attributes = new TextAttributes(); + attributes.setFontType(Font.BOLD); +// TODO: proper attributes + JET_FUNCTION_LITERAL_DELIMITER = TextAttributesKey.createTextAttributesKey("JET.AUTO.CREATED.IT", attributes); + } + public static final TextAttributesKey JET_DEBUG_INFO; static { diff --git a/idea/src/org/jetbrains/jet/plugin/actions/CopyAsDiagnosticTestAction.java b/idea/src/org/jetbrains/jet/plugin/actions/CopyAsDiagnosticTestAction.java new file mode 100644 index 00000000000..b9c35a7986d --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/actions/CopyAsDiagnosticTestAction.java @@ -0,0 +1,50 @@ +package org.jetbrains.jet.plugin.actions; + +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.LangDataKeys; +import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.Editor; +import com.intellij.psi.PsiFile; +import org.jetbrains.jet.checkers.CheckerTestUtil; +import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.plugin.AnalyzerFacade; + +import java.awt.*; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.ClipboardOwner; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.Transferable; + +/** + * @author abreslav + */ +public class CopyAsDiagnosticTestAction extends AnAction { + @Override + public void actionPerformed(AnActionEvent e) { + Editor editor = e.getData(PlatformDataKeys.EDITOR); + PsiFile psiFile = e.getData(LangDataKeys.PSI_FILE); + assert editor != null && psiFile != null; + + BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache((JetFile) psiFile); + + String result = CheckerTestUtil.addDiagnosticMarkersToText(psiFile, bindingContext).toString(); + + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + clipboard.setContents(new StringSelection(result), new ClipboardOwner() { + @Override + public void lostOwnership(Clipboard clipboard, Transferable contents) {} + }); + } + + + @Override + public void update(AnActionEvent e) { + Editor editor = e.getData(PlatformDataKeys.EDITOR); + PsiFile psiFile = e.getData(LangDataKeys.PSI_FILE); + e.getPresentation().setEnabled(editor != null && psiFile instanceof JetFile && ApplicationManager.getApplication().isInternal()); + } + +} diff --git a/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java b/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java index 02bf994dfba..29f8a1abe65 100644 --- a/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java +++ b/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java @@ -15,6 +15,7 @@ import com.intellij.psi.PsiReference; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; +import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.diagnostics.*; import org.jetbrains.jet.lang.psi.*; @@ -28,6 +29,10 @@ import org.jetbrains.jet.plugin.quickfix.QuickFixes; import java.util.Collection; import java.util.Set; +import static org.jetbrains.jet.lang.resolve.BindingContext.AUTOCAST; +import static org.jetbrains.jet.lang.resolve.BindingContext.AUTO_CREATED_IT; +import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET; + /** * @author abreslav */ @@ -52,7 +57,7 @@ public class JetPsiChecker implements Annotator { if (errorReportingEnabled) { Collection diagnostics = bindingContext.getDiagnostics(); - Set redeclarations = Sets.newHashSet(); + Set redeclarations = Sets.newHashSet(); for (Diagnostic diagnostic : diagnostics) { Annotation annotation = null; if (diagnostic.getSeverity() == Severity.ERROR) { @@ -72,8 +77,7 @@ public class JetPsiChecker implements Annotator { } else if (diagnostic instanceof RedeclarationDiagnostic) { RedeclarationDiagnostic redeclarationDiagnostic = (RedeclarationDiagnostic) diagnostic; - markRedeclaration(redeclarations, redeclarationDiagnostic.getA(), bindingContext, holder); - markRedeclaration(redeclarations, redeclarationDiagnostic.getB(), bindingContext, holder); + annotation = markRedeclaration(redeclarations, redeclarationDiagnostic, holder); } else { annotation = holder.createErrorAnnotation(diagnostic.getFactory().getTextRange(diagnostic), getMessage(diagnostic)); @@ -82,7 +86,7 @@ public class JetPsiChecker implements Annotator { else if (diagnostic.getSeverity() == Severity.WARNING) { annotation = holder.createWarningAnnotation(diagnostic.getFactory().getTextRange(diagnostic), getMessage(diagnostic)); } - if (annotation != null && diagnostic instanceof DiagnosticWithPsiElement) { + if (annotation != null && diagnostic instanceof DiagnosticWithPsiElementImpl) { DiagnosticWithPsiElement diagnosticWithPsiElement = (DiagnosticWithPsiElement) diagnostic; if (diagnostic.getFactory() instanceof PsiElementOnlyDiagnosticFactory) { PsiElementOnlyDiagnosticFactory factory = (PsiElementOnlyDiagnosticFactory) diagnostic.getFactory(); @@ -102,9 +106,21 @@ public class JetPsiChecker implements Annotator { highlightBackingFields(holder, file, bindingContext); file.acceptChildren(new JetVisitorVoid() { + @Override + public void visitSimpleNameExpression(JetSimpleNameExpression expression) { + DeclarationDescriptor target = bindingContext.get(REFERENCE_TARGET, expression); + if (target instanceof ValueParameterDescriptor) { + ValueParameterDescriptor parameterDescriptor = (ValueParameterDescriptor) target; + if (bindingContext.get(AUTO_CREATED_IT, parameterDescriptor)) { + holder.createInfoAnnotation(expression, "Automatically declared based on the expected type").setTextAttributes(JetHighlighter.JET_AUTOCREATED_IT); + } + } + super.visitSimpleNameExpression(expression); + } + @Override public void visitExpression(JetExpression expression) { - JetType autoCast = bindingContext.get(BindingContext.AUTOCAST, expression); + JetType autoCast = bindingContext.get(AUTOCAST, expression); if (autoCast != null) { holder.createInfoAnnotation(expression, "Automatically cast to " + autoCast).setTextAttributes(JetHighlighter.JET_AUTO_CAST_EXPRESSION); } @@ -135,19 +151,10 @@ public class JetPsiChecker implements Annotator { return diagnostic.getMessage(); } - private void markRedeclaration(Set redeclarations, DeclarationDescriptor redeclaration, BindingContext bindingContext, AnnotationHolder holder) { - if (!redeclarations.add(redeclaration)) return; - PsiElement declarationPsiElement = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, redeclaration); - if (declarationPsiElement instanceof JetNamedDeclaration) { - PsiElement nameIdentifier = ((JetNamedDeclaration) declarationPsiElement).getNameIdentifier(); - if (nameIdentifier != null) { - holder.createErrorAnnotation(nameIdentifier, "Redeclaration"); - } - } - else if (declarationPsiElement != null) { - holder.createErrorAnnotation(declarationPsiElement, "Redeclaration"); - } - } + private Annotation markRedeclaration(Set redeclarations, RedeclarationDiagnostic diagnostic, AnnotationHolder holder) { + if (!redeclarations.add(diagnostic.getPsiElement())) return null; + return holder.createErrorAnnotation(diagnostic.getFactory().getTextRange(diagnostic), getMessage(diagnostic)); + } private void highlightBackingFields(final AnnotationHolder holder, JetFile file, final BindingContext bindingContext) { diff --git a/idea/src/org/jetbrains/jet/plugin/annotations/SoftKeywordsAnnotator.java b/idea/src/org/jetbrains/jet/plugin/annotations/SoftKeywordsAnnotator.java index 77aa4d0eac4..194d06ab932 100644 --- a/idea/src/org/jetbrains/jet/plugin/annotations/SoftKeywordsAnnotator.java +++ b/idea/src/org/jetbrains/jet/plugin/annotations/SoftKeywordsAnnotator.java @@ -3,8 +3,10 @@ */ package org.jetbrains.jet.plugin.annotations; +import com.intellij.lang.ASTNode; import com.intellij.lang.annotation.AnnotationHolder; import com.intellij.lang.annotation.Annotator; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.psi.PsiElement; import com.intellij.psi.impl.source.tree.LeafPsiElement; import org.jetbrains.annotations.NotNull; @@ -13,20 +15,41 @@ import org.jetbrains.jet.plugin.JetHighlighter; import org.jetbrains.jet.lexer.JetTokens; public class SoftKeywordsAnnotator implements Annotator { - public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) { - if (element instanceof LeafPsiElement) { - if (JetTokens.SOFT_KEYWORDS.contains(((LeafPsiElement) element).getElementType())) { - holder.createInfoAnnotation(element, null).setTextAttributes(JetHighlighter.JET_SOFT_KEYWORD); + public void annotate(@NotNull PsiElement element, @NotNull final AnnotationHolder holder) { + element.accept(new JetVisitorVoid() { + @Override + public void visitElement(PsiElement element) { + if (element instanceof LeafPsiElement) { + if (JetTokens.SOFT_KEYWORDS.contains(((LeafPsiElement) element).getElementType())) { + holder.createInfoAnnotation(element, null).setTextAttributes(JetHighlighter.JET_SOFT_KEYWORD); + } + } } - } - else if (element instanceof JetAnnotationEntry) { - JetAnnotationEntry entry = (JetAnnotationEntry) element; - JetTypeReference typeReference = entry.getTypeReference(); - if (typeReference != null) { - JetTypeElement typeElement = typeReference.getTypeElement(); - markAnnotationIdentifiers(typeElement, holder); + + @Override + public void visitAnnotationEntry(JetAnnotationEntry annotationEntry) { + JetTypeReference typeReference = annotationEntry.getTypeReference(); + if (typeReference != null) { + JetTypeElement typeElement = typeReference.getTypeElement(); + markAnnotationIdentifiers(typeElement, holder); + } } - } + + @Override + public void visitFunctionLiteralExpression(JetFunctionLiteralExpression expression) { + if (ApplicationManager.getApplication().isUnitTestMode()) return; + JetFunctionLiteral functionLiteral = expression.getFunctionLiteral(); + holder.createInfoAnnotation(functionLiteral.getOpenBraceNode(), null).setTextAttributes(JetHighlighter.JET_FUNCTION_LITERAL_DELIMITER); + ASTNode closingBraceNode = functionLiteral.getClosingBraceNode(); + if (closingBraceNode != null) { + holder.createInfoAnnotation(closingBraceNode, null).setTextAttributes(JetHighlighter.JET_FUNCTION_LITERAL_DELIMITER); + } + ASTNode arrowNode = functionLiteral.getArrowNode(); + if (arrowNode != null) { + holder.createInfoAnnotation(arrowNode, null).setTextAttributes(JetHighlighter.JET_FUNCTION_LITERAL_DELIMITER); + } + } + }); } private void markAnnotationIdentifiers(JetTypeElement typeElement, @NotNull AnnotationHolder holder) { diff --git a/idea/src/org/jetbrains/jet/plugin/references/JetPsiReference.java b/idea/src/org/jetbrains/jet/plugin/references/JetPsiReference.java index 033497955d8..a9f3c0a488b 100644 --- a/idea/src/org/jetbrains/jet/plugin/references/JetPsiReference.java +++ b/idea/src/org/jetbrains/jet/plugin/references/JetPsiReference.java @@ -89,7 +89,7 @@ public abstract class JetPsiReference implements PsiPolyVariantReference { JetFile file = (JetFile) getElement().getContainingFile(); BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(file); Collection declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, myExpression); - assert declarationDescriptors != null; + if (declarationDescriptors != null) return ResolveResult.EMPTY_ARRAY; ResolveResult[] results = new ResolveResult[declarationDescriptors.size()]; int i = 0; for (DeclarationDescriptor descriptor : declarationDescriptors) { diff --git a/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.java b/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.java index 7896d7bcf63..b90af3696ef 100644 --- a/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.java +++ b/idea/src/org/jetbrains/jet/plugin/references/JetSimpleNameReference.java @@ -13,7 +13,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.plugin.AnalyzerFacade; import org.jetbrains.jet.resolve.DescriptorRenderer; diff --git a/idea/testData/checkerWithErrorTypes/checkerTestUtil/test.jet b/idea/testData/checkerWithErrorTypes/checkerTestUtil/test.jet new file mode 100644 index 00000000000..e78606b8885 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/checkerTestUtil/test.jet @@ -0,0 +1,15 @@ +fun foo(u : Unit) : Int = 1 + +fun test() : Int { + foo(1) + val a : fun() : Unit = { + foo(1) + } + return 1 - "1" +} + +class A() { + val x : Int = foo1(xx) +} + +fun foo1() {} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/Abstract.jet b/idea/testData/checkerWithErrorTypes/full/Abstract.jet new file mode 100644 index 00000000000..113ff0a34d6 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/Abstract.jet @@ -0,0 +1,241 @@ +namespace abstract + +class MyClass() { + //properties + val a: Int + val a1: Int = 1 + abstract val a2: Int + abstract val a3: Int = 1 + + var b: Int private set + var b1: Int = 0; private set + abstract var b2: Int private set + abstract var b3: Int = 0; private set + + var c: Int set(v: Int) { $c = v } + var c1: Int = 0; set(v: Int) { $c1 = v } + abstract var c2: Int set(v: Int) { $c2 = v } + abstract var c3: Int = 0; set(v: Int) { $c3 = v } + + val e: Int get() = a + val e1: Int = 0; get() = a + abstract val e2: Int get() = a + abstract val e3: Int = 0; get() = a + + //methods + fun f() + fun g() {} + abstract fun h() + abstract fun j() {} + + //property accessors + var i: Int abstract get abstract set + var i1: Int = 0; abstract get abstract set + + var j: Int get() = i; abstract set + var j1: Int = 0; get() = i; abstract set + + var k: Int abstract set + var k1: Int = 0; abstract set + + var l: Int abstract get abstract set + var l1: Int = 0; abstract get abstract set + + var n: Int abstract get abstract set(v: Int) {} +} + +abstract class MyAbstractClass() { + //properties + val a: Int + val a1: Int = 1 + abstract val a2: Int + abstract val a3: Int = 1 + + var b: Int private set + var b1: Int = 0; private set + abstract var b2: Int private set + abstract var b3: Int = 0; private set + + var c: Int set(v: Int) { $c = v } + var c1: Int = 0; set(v: Int) { $c1 = v } + abstract var c2: Int set(v: Int) { $c2 = v } + abstract var c3: Int = 0; set(v: Int) { $c3 = v } + + val e: Int get() = a + val e1: Int = 0; get() = a + abstract val e2: Int get() = a + abstract val e3: Int = 0; get() = a + + //methods + fun f() + fun g() {} + abstract fun h() + abstract fun j() {} + + //property accessors + var i: Int abstract get abstract set + var i1: Int = 0; abstract get abstract set + + var j: Int get() = i; abstract set + var j1: Int get() = i; abstract set + + var k: Int abstract set + var k1: Int = 0; abstract set + + var l: Int abstract get abstract set + var l1: Int = 0; abstract get abstract set + + var n: Int abstract get abstract set(v: Int) {} +} + +trait MyTrait { + //properties + val a: Int + val a1: Int = 1 + abstract val a2: Int + abstract val a3: Int = 1 + + var b: Int private set + var b1: Int = 0; private set + abstract var b2: Int private set + abstract var b3: Int = 0; private set + + var c: Int set(v: Int) { $c = v } + var c1: Int = 0; set(v: Int) { $c1 = v } + abstract var c2: Int set(v: Int) { $c2 = v } + abstract var c3: Int = 0; set(v: Int) { $c3 = v } + + val e: Int get() = a + val e1: Int = 0; get() = a + abstract val e2: Int get() = a + abstract val e3: Int = 0; get() = a + + //methods + fun f() + fun g() {} + abstract fun h() + abstract fun j() {} + + //property accessors + var i: Int abstract get abstract set + var i1: Int = 0; abstract get abstract set + + var j: Int get() = i; abstract set + var j1: Int = 0; get() = i; abstract set + + var k: Int abstract set + var k1: Int = 0; abstract set + + var l: Int abstract get abstract set + var l1: Int = 0; abstract get abstract set + + var n: Int abstract get abstract set(v: Int) {} +} + +enum class MyEnum() { + //properties + val a: Int + val a1: Int = 1 + abstract val a2: Int + abstract val a3: Int = 1 + + var b: Int private set + var b1: Int = 0; private set + abstract var b2: Int private set + abstract var b3: Int = 0; private set + + var c: Int set(v: Int) { $c = v } + var c1: Int = 0; set(v: Int) { $c1 = v } + abstract var c2: Int set(v: Int) { $c2 = v } + abstract var c3: Int = 0; set(v: Int) { $c3 = v } + + val e: Int get() = a + val e1: Int = 0; get() = a + abstract val e2: Int get() = a + abstract val e3: Int = 0; get() = a + + //methods + fun f() + fun g() {} + abstract fun h() + abstract fun j() {} + + //property accessors + var i: Int abstract get abstract set + var i1: Int = 0; abstract get abstract set + + var j: Int get() = i; abstract set + var j1: Int = 0; get() = i; abstract set + + var k: Int abstract set + var k1: Int = 0; abstract set + + var l: Int abstract get abstract set + var l1: Int = 0; abstract get abstract set + + var n: Int abstract get abstract set(v: Int) {} +} + +abstract enum class MyAbstractEnum() {} + +namespace MyNamespace { + //properties + val a: Int + val a1: Int = 1 + abstract val a2: Int + abstract val a3: Int = 1 + + var b: Int private set + var b1: Int = 0; private set + abstract var b2: Int private set + abstract var b3: Int = 0; private set + + var c: Int set(v: Int) { $c = v } + var c1: Int = 0; set(v: Int) { $c1 = v } + abstract var c2: Int set(v: Int) { $c2 = v } + abstract var c3: Int = 0; set(v: Int) { $c3 = v } + + val e: Int get() = a + val e1: Int = 0; get() = a + abstract val e2: Int get() = a + abstract val e3: Int = 0; get() = a + + //methods + fun f() + fun g() {} + abstract fun h() + abstract fun j() {} + + //property accessors + var i: Int abstract get abstract set + var i1: Int = 0; abstract get abstract set + + var j: Int get() = i; abstract set + var j1: Int = 0; get() = i; abstract set + + var k: Int abstract set + var k1: Int = 0; abstract set + + var l: Int abstract get abstract set + var l1: Int = 0; abstract get abstract set + + var n: Int abstract get abstract set(v: Int) {} +} + +//creating an instance +abstract class B1( + val i: Int, + val s: String +) { +} + +class B2() : B1(1, "r") {} + +abstract class B3(i: Int) { + this(): this(1) +} + +fun foo(a: B3) { + val a = B3() + val b = B1(2, "s") +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/AnonymousInitializers.jet b/idea/testData/checkerWithErrorTypes/full/AnonymousInitializers.jet new file mode 100644 index 00000000000..955798a7a9c --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/AnonymousInitializers.jet @@ -0,0 +1,34 @@ +class NoC { + { + + } + + val a : Int get() = 1 + + { + + } +} + +class WithC() { + val x : Int + { + $x = 1 + $y = 2 + val b = x + + } + + val a : Int get() = 1 + + { + val z = b + val zz = x + val zzz = $a + } + + this(a : Int) : this() { + val b = x + } + +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/BinaryCallsOnNullableValues.jet b/idea/testData/checkerWithErrorTypes/full/BinaryCallsOnNullableValues.jet new file mode 100644 index 00000000000..86d34c881be --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/BinaryCallsOnNullableValues.jet @@ -0,0 +1,41 @@ +class A() { + fun equals(a : Any?) : Boolean = false +} + +class B() { + fun equals(a : Any?) : Boolean? = false +} + +class C() { + fun equals(a : Any?) : Int = 0 +} + +fun f(): Unit { + var x: Int? = 1 + x = 1 + x + 1 + x plus 1 + x < 1 + x += 1 + + x == 1 + x != 1 + + A() == 1 + B() == 1 + C() == 1 + + x === "1" + x !== "1" + + x === 1 + x !== 1 + + x..2 + x in 1..2 + + val y : Boolean? = true + false || y + y && true + y && 1 +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/Bounds.jet b/idea/testData/checkerWithErrorTypes/full/Bounds.jet new file mode 100644 index 00000000000..37066cb74ab --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/Bounds.jet @@ -0,0 +1,40 @@ +namespace boundsWithSubstitutors { + open class A + class B>() + + class C : A + + val a = B() + val a1 = B<Int>() + + class X() + + val b = X, C>> + val b0 = XAny?> + val b1 = X, String>> + +} + + open class A {} + open class B() + + abstract class CInt>, X : fun (B<Char>) : (B<Any>, B)>() : B<Any>() { // 2 errors + val a = B<Char>() // error + + abstract val x : fun (B<Char>) : B<Any> + } + + +fun test() { + foo<Int?>() + foo() + bar() + bar() + bar<Double?>() + bar<Double>() + 1.buzz<Double>() +} + +fun foo() {} +fun bar() {} +fun Int> Int.buzz() : Unit {} diff --git a/idea/testData/checkerWithErrorTypes/full/BreakContinue.jet b/idea/testData/checkerWithErrorTypes/full/BreakContinue.jet new file mode 100644 index 00000000000..2bf691799e0 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/BreakContinue.jet @@ -0,0 +1,28 @@ +class C { + + fun f (a : Boolean, b : Boolean) { + @b (while (true) + @a { + break@f + break + break@b + break@a + }) + + continue + + @b (while (true) + @a { + continue@f + continue + continue@b + continue@a + }) + + break + + continue@f + break@f + } + +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/Builders.jet b/idea/testData/checkerWithErrorTypes/full/Builders.jet new file mode 100644 index 00000000000..1d26cbbc8b2 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/Builders.jet @@ -0,0 +1,121 @@ +import java.util.* + +namespace html { + + abstract class Factory { + abstract fun create() : T + } + + abstract class Element + + class TextElement(val text : String) : Element + + abstract class Tag(val name : String) : Element { + val children = ArrayList() + val attributes = HashMap() + + protected fun initTag(init : fun T.() : Unit) : T + where class object T : Factory{ + val tag = T.create() + tag.init() + children.add(tag) + return tag + } + } + + abstract class TagWithText(name : String) : Tag(name) { + fun String.plus() { + children.add(TextElement(this)) + } + } + + class HTML() : TagWithText("html") { + class object : Factory { + override fun create() = HTML() + } + + fun head(init : fun Head.() : Unit) = initTag(init) + + fun body(init : fun Body.() : Unit) = initTag(init) + } + + class Head() : TagWithText("head") { + class object : Factory { + override fun create() = Head() + } + + fun title(init : fun Title.() : Unit) = initTag(init) + } + + class Title() : TagWithText("title") + + abstract class BodyTag(name : String) : TagWithText(name) { + } + + class Body() : BodyTag("body") { + class object : Factory<Body> { + override fun create() = Body() + } + + fun b(init : fun B.() : Unit) = initTag<B>(init) + fun p(init : fun P.() : Unit) = initTag<P>(init) + fun h1(init : fun H1.() : Unit) = initTag<H1>(init) + fun a(href : String, init : fun A.() : Unit) { + val a = initTag<A>(init) + a.href = href + } + } + + class B() : BodyTag("b") + class P() : BodyTag("p") + class H1() : BodyTag("h1") + class A() : BodyTag("a") { + var href : String + get() = attributes["href"] + set(value) { attributes["href"] = value } + } + + fun Map<String, String>.set(key : String, value : String) = this.put(key, value) + + fun html(init : fun HTML.() : Unit) : HTML { + val html = HTML() + html.init() + return html + } + +} + +namespace foo { + +import html.* + +fun result(args : Array<String>) = + html { + head { + title {+"XML encoding with Groovy"} + } + body { + h1 {+"XML encoding with Groovy"} + p {+"this format can be used as an alternative markup to XML"} + + // an element with attributes and text content + a(href = "http://groovy.codehaus.org") {+"Groovy"} + + // mixed content + p { + +"This is some" + b {+"mixed"} + +"text. For more see the" + a(href = "http://groovy.codehaus.org") {+"Groovy"} + +"project" + } + p {+"some text"} + + // content generated by + p { + for (arg in args) + +arg + } + } + } +} diff --git a/idea/testData/checkerWithErrorTypes/full/Casts.jet b/idea/testData/checkerWithErrorTypes/full/Casts.jet new file mode 100644 index 00000000000..163619fd4d0 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/Casts.jet @@ -0,0 +1,16 @@ +fun test() : Unit { + var x : Int? = 0 + var y : Int = 0 + + x : Int? + y : Int + x as Int : Int + y <!USELESS_CAST!>as<!> Int : Int + x <!USELESS_CAST!>as<!> Int? : Int? + y <!USELESS_CAST_STATIC_ASSERT_IS_FINE!>as<!> Int? : Int? + x as? Int : Int? + y <!USELESS_CAST!>as?<!> Int : Int? + x <!USELESS_CAST!>as?<!> Int? : Int? + y <!USELESS_CAST_STATIC_ASSERT_IS_FINE!>as?<!> Int? : Int? + () +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/ClassObjects.jet b/idea/testData/checkerWithErrorTypes/full/ClassObjects.jet new file mode 100644 index 00000000000..5be76d57e39 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/ClassObjects.jet @@ -0,0 +1,30 @@ +namespace Jet86 + +class A { + class object { + val x = 1 + } + <!MANY_CLASS_OBJECTS!>class object { // error + val x = 1 + }<!> +} + +class B() { + val x = 12 +} + +object b { + <!CLASS_OBJECT_NOT_ALLOWED!>class object { + val x = 1 + }<!> // error +} + +val a = A.x +val c = <!NO_CLASS_OBJECT!>B<!>.x +val d = b.<!UNRESOLVED_REFERENCE!>x<!> + +val s = <!NO_CLASS_OBJECT!>System<!> // error +fun test() { + System.out?.println() + java.lang.System.out?.println() +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/Constants.jet b/idea/testData/checkerWithErrorTypes/full/Constants.jet new file mode 100644 index 00000000000..cc908e189f0 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/Constants.jet @@ -0,0 +1,8 @@ +fun test() { + 1 : Byte + 1 : Int + <!TYPE_MISMATCH, TYPE_MISMATCH!>1<!> : Double + 1 <!USELESS_CAST!>as<!> Byte + 1 <!USELESS_CAST!>as<!> Int + <!ERROR_COMPILE_TIME_VALUE!>1<!> <!CAST_NEVER_SUCCEEDS!>as<!> Double +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/Constructors.jet b/idea/testData/checkerWithErrorTypes/full/Constructors.jet new file mode 100644 index 00000000000..c6adf21f4b9 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/Constructors.jet @@ -0,0 +1,51 @@ + +open class NoC +class NoC1 : NoC + +class WithC0() : NoC<!NO_CONSTRUCTOR!>()<!> +open class WithC1() : NoC +class NoC2 : <!SUPERTYPE_NOT_INITIALIZED!>WithC1<!> +class NoC3 : WithC1<!PRIMARY_CONSTRUCTOR_MISSING_SUPER_CONSTRUCTOR_CALL!>()<!> +class WithC2() : <!SUPERTYPE_NOT_INITIALIZED!>WithC1<!> + +class NoPC { + <!SECONDARY_CONSTRUCTOR_BUT_NO_PRIMARY!>this<!>() {} +} + +class WithPC0() { + this(a : Int) : this() {} +} + +class WithPC1(a : Int) { + <!SECONDARY_CONSTRUCTOR_NO_INITIALIZER_LIST!>this<!>() {} + + this(b : Long) : this("") {} + + this(s : String) : this(1) {} + + this(b : Char) : <!NONE_APPLICABLE!>this("", 2)<!> {} + + this(b : Byte) : this(""), <!MANY_CALLS_TO_THIS!>this(1)<!> {} +} + + +class Foo() : <!SUPERTYPE_NOT_INITIALIZED, FINAL_SUPERTYPE!>WithPC0<!>, <!MANY_CLASSES_IN_SUPERTYPE_LIST!>this<!>() { + +} + +class WithCPI_Dup(<!REDECLARATION, REDECLARATION!>x<!> : Int) { + var <!REDECLARATION, REDECLARATION, MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>x<!> : Int +} + +class WithCPI(x : Int) { + val a = 1 + val b : Int = $a + val xy : Int = x +} + +class <!PRIMARY_CONSTRUCTOR_MISSING_STATEFUL_PROPERTY!>NoCPI<!> { + val a = <!PROPERTY_INITIALIZER_NO_PRIMARY_CONSTRUCTOR!>1<!> + var ab = <!PROPERTY_INITIALIZER_NO_BACKING_FIELD!>1<!> + get() = 1 + set(v) {} +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/CyclicHierarchy.jet b/idea/testData/checkerWithErrorTypes/full/CyclicHierarchy.jet new file mode 100644 index 00000000000..ff99017a12b --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/CyclicHierarchy.jet @@ -0,0 +1,30 @@ +open trait A { + fun foo() {} +} +open trait B : A, <!CYCLIC_INHERITANCE_HIERARCHY!>E<!> {} +open trait C : B {} +open trait D : <!CYCLIC_INHERITANCE_HIERARCHY!>B<!> {} +open trait E : <!CYCLIC_INHERITANCE_HIERARCHY!>F<!> {} +open trait F : <!CYCLIC_INHERITANCE_HIERARCHY!>D<!>, C {} +open trait G : F {} +open trait H : F {} + +val a : A? = null +val b : B? = null +val c : C? = null +val d : D? = null +val e : E? = null +val f : F? = null +val g : G? = null +val h : H? = null + +fun test() { + a?.foo() + b?.foo() + c?.foo() + d?.foo() + e?.<!UNRESOLVED_REFERENCE!>foo<!>() + f?.foo() + g?.foo() + h?.foo() +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/Enums.jet b/idea/testData/checkerWithErrorTypes/full/Enums.jet new file mode 100644 index 00000000000..0ef400fda22 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/Enums.jet @@ -0,0 +1,10 @@ +enum class List<out T>(val size : Int) { + Nil : List<Nothing>(0) { + val a = 1 + } + Cons<out T>(val head : T, val tail : List<T>) : List<T>(tail.size + 1) + +} + +val foo = List.Nil +val foo1 = foo.a \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/ExtensionFunctions.jet b/idea/testData/checkerWithErrorTypes/full/ExtensionFunctions.jet new file mode 100644 index 00000000000..54edfbaa527 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/ExtensionFunctions.jet @@ -0,0 +1,71 @@ +fun Int?.optint() : Unit {} +val Int?.optval : Unit = () + +fun <T, E> T.foo(x : E, y : A) : T { + y.plus(1) + y plus 1 + y + 1.0 + + this<!UNNECESSARY_SAFE_CALL!>?.<!>minus<T>(this) + + return this +} + +class A + +fun A.plus(a : Any) { + + 1.foo() + true.<!NONE_APPLICABLE!>foo()<!> + + 1 +} + +fun A.plus(a : Int) { + 1 +} + +fun <T> T.minus(t : T) : Int = 1 + +fun test() { + val y = 1.abs +} +val Int.abs : Int + get() = if (this > 0) this else -this; + +val <T> T.<!MUST_BE_INITIALIZED!>foo<!> : T + +fun Int.foo() = this + +namespace null_safety { + + fun parse(cmd: String): Command? { return null } + class Command() { + // fun equals(other : Any?) : Boolean + val foo : Int = 0 + } + + fun Any.equals(other : Any?) : Boolean = true + fun Any?.equals1(other : Any?) : Boolean = true + fun Any.equals2(other : Any?) : Boolean = true + + fun main(args: Array<String>) { + + System.out?.print(1) + + val command = parse("") + + command<!UNSAFE_CALL!>.<!>foo + + command.equals(null) + command<!UNNECESSARY_SAFE_CALL!>?.<!>equals(null) + command.equals1(null) + command<!UNNECESSARY_SAFE_CALL!>?.<!>equals1(null) + + val c = Command() + c<!UNNECESSARY_SAFE_CALL!>?.<!>equals2(null) + + if (command == null) 1 + } + +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/ForRangeConventions.jet b/idea/testData/checkerWithErrorTypes/full/ForRangeConventions.jet new file mode 100644 index 00000000000..1f14e587fcd --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/ForRangeConventions.jet @@ -0,0 +1,81 @@ +import java.util.*; + +class NotRange1() { + +} + +abstract class NotRange2() { + abstract fun iterator() : Unit +} + +abstract class ImproperIterator1 { + abstract fun hasNext() : Boolean +} + +abstract class NotRange3() { + abstract fun iterator() : ImproperIterator1 +} + +abstract class ImproperIterator2 { + abstract fun next() : Boolean +} + +abstract class NotRange4() { + abstract fun iterator() : ImproperIterator2 +} + +abstract class ImproperIterator3 { + abstract fun hasNext() : Int + abstract fun next() : Int +} + +abstract class NotRange5() { + abstract fun iterator() : ImproperIterator3 +} + +abstract class AmbiguousHasNextIterator { + abstract fun hasNext() : Boolean + val hasNext : Boolean get() = false + abstract fun next() : Int +} + +abstract class NotRange6() { + abstract fun iterator() : AmbiguousHasNextIterator +} + +abstract class ImproperIterator4 { + val hasNext : Int get() = 1 + abstract fun next() : Int +} + +abstract class NotRange7() { + abstract fun iterator() : ImproperIterator3 +} + +abstract class GoodIterator { + abstract fun hasNext() : Boolean + abstract fun next() : Int +} + +abstract class Range0() { + abstract fun iterator() : GoodIterator +} + +abstract class Range1() { + abstract fun iterator() : Iterator<Int> +} + +fun test(notRange1: NotRange1, notRange2: NotRange2, notRange3: NotRange3, notRange4: NotRange4, notRange5: NotRange5, notRange6: NotRange6, notRange7: NotRange7, range0: Range0, range1: Range1) { + for (i in <!ITERATOR_MISSING!>notRange1<!>); + for (i in <!HAS_NEXT_MISSING, NEXT_MISSING!>notRange2<!>); + for (i in <!NEXT_MISSING!>notRange3<!>); + for (i in <!HAS_NEXT_MISSING!>notRange4<!>); + for (i in <!HAS_NEXT_FUNCTION_TYPE_MISMATCH!>notRange5<!>); + for (i in <!HAS_NEXT_PROPERTY_AND_FUNCTION_AMBIGUITY!>notRange6<!>); + for (i in <!HAS_NEXT_FUNCTION_TYPE_MISMATCH!>notRange7<!>); + for (i in range0); + for (i in range1); + + for (i in (ArrayList<Int>() : List<Int>)); +} + diff --git a/idea/testData/checkerWithErrorTypes/full/FunctionReturnTypes.jet b/idea/testData/checkerWithErrorTypes/full/FunctionReturnTypes.jet new file mode 100644 index 00000000000..64012287566 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/FunctionReturnTypes.jet @@ -0,0 +1,166 @@ +fun none() {} + +fun unitEmptyInfer() {} +fun unitEmpty() : Unit {} +fun unitEmptyReturn() : Unit {return} +fun unitIntReturn() : Unit {return <!TYPE_MISMATCH!>1<!>} +fun unitUnitReturn() : Unit {return ()} +fun test1() : Any = {<!RETURN_NOT_ALLOWED, RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY!>return<!>} +fun test2() : Any = @a {return@a 1} +fun test3() : Any { <!RETURN_TYPE_MISMATCH!>return<!> } + +fun bbb() { + return <!TYPE_MISMATCH!>1<!> +} + +fun foo(expr: StringBuilder): Int { + val c = 'a' + when(c) { + 0.chr => throw Exception("zero") + else => throw Exception("nonzero" + c) + } +} + + +fun unitShort() : Unit = () +fun unitShortConv() : Unit = <!TYPE_MISMATCH!>1<!> +fun unitShortNull() : Unit = <!TYPE_MISMATCH!>null<!> + +fun intEmpty() : Int <!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>{}<!> +fun intShortInfer() = 1 +fun intShort() : Int = 1 +//fun intBlockInfer() {1} +fun intBlock() : Int {return 1} +fun intBlock() : Int {<!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>1<!>} + +fun intString(): Int = <!TYPE_MISMATCH!>"s"<!> +fun intFunctionLiteral(): Int = <!TYPE_MISMATCH!>{ 10 }<!> + +fun blockReturnUnitMismatch() : Int {<!RETURN_TYPE_MISMATCH!>return<!>} +fun blockReturnValueTypeMismatch() : Int {return <!ERROR_COMPILE_TIME_VALUE!>3.4<!>} +fun blockReturnValueTypeMatch() : Int {return 1} +fun blockReturnValueTypeMismatchUnit() : Int {return <!TYPE_MISMATCH!>()<!>} + +fun blockAndAndMismatch() : Int { + <!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>true && false<!> +} +fun blockAndAndMismatch() : Int { + return <!TYPE_MISMATCH!>true && false<!> +} +fun blockAndAndMismatch() : Int { + <!UNREACHABLE_CODE!>(return <!ERROR_COMPILE_TIME_VALUE!>true<!>) && (return <!ERROR_COMPILE_TIME_VALUE!>false<!>)<!> +} + +fun blockAndAndMismatch() : Int { + <!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>true || false<!> +} +fun blockAndAndMismatch() : Int { + return <!TYPE_MISMATCH!>true || false<!> +} +fun blockAndAndMismatch() : Int { + <!UNREACHABLE_CODE!>(return <!ERROR_COMPILE_TIME_VALUE!>true<!>) || (return <!ERROR_COMPILE_TIME_VALUE!>false<!>)<!> +} +fun blockReturnValueTypeMatch() : Int { + return if (1 > 2) <!ERROR_COMPILE_TIME_VALUE!>1.0<!> else <!ERROR_COMPILE_TIME_VALUE!>2.0<!> +} +fun blockReturnValueTypeMatch() : Int { + return <!TYPE_MISMATCH!>if (1 > 2) 1<!> +} +fun blockReturnValueTypeMatch() : Int { + return <!TYPE_MISMATCH!>if (1 > 2) else 1<!> +} +fun blockReturnValueTypeMatch() : Int { + if (1 > 2) + return <!ERROR_COMPILE_TIME_VALUE!>1.0<!> + else return <!ERROR_COMPILE_TIME_VALUE!>2.0<!> +} +fun blockReturnValueTypeMatch() : Int { + if (1 > 2) + return <!ERROR_COMPILE_TIME_VALUE!>1.0<!> + return <!ERROR_COMPILE_TIME_VALUE!>2.0<!> +} +fun blockReturnValueTypeMatch() : Int { + if (1 > 2) + else return <!ERROR_COMPILE_TIME_VALUE!>1.0<!> + return <!ERROR_COMPILE_TIME_VALUE!>2.0<!> +} +fun blockReturnValueTypeMatch() : Int { + if (1 > 2) + <!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>1.0<!> + else <!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>2.0<!> +} +fun blockReturnValueTypeMatch() : Int { + if (1 > 2) + 1.0 + else 2.0 + return 1 +} +fun blockReturnValueTypeMatch() : Int { + <!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>if (1 > 2) + <!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>1.0<!><!> +} +fun blockReturnValueTypeMatch() : Int { + return <!TYPE_MISMATCH!>if (1 > 2) + 1<!> +} +fun blockReturnValueTypeMatch() : Int { + <!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>if (1 > 2) + else <!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>1.0<!><!> +} +fun blockReturnValueTypeMatch() : Int { + if (1 > 2) + return 1 + else return <!ERROR_COMPILE_TIME_VALUE!>1.0<!> +} +fun blockNoReturnIfValDeclaration(): Int { + <!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>val x = 1<!> +} +fun blockNoReturnIfEmptyIf(): Int { + if (1 < 2) <!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>{}<!> else <!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>{}<!> +} +fun blockNoReturnIfUnitInOneBranch(): Int { + if (1 < 2) { + return 1 + } else { + if (3 < 4) <!NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY!>{ + }<!> else { + return 2 + } + } +} +fun nonBlockReturnIfEmptyIf(): Int = if (1 < 2) <!TYPE_MISMATCH!>{}<!> else <!TYPE_MISMATCH!>{}<!> +fun nonBlockNoReturnIfUnitInOneBranch(): Int = if (1 < 2) <!TYPE_MISMATCH!>{}<!> else 2 + +val a = <!RETURN_NOT_ALLOWED!>return 1<!> + +class A() { + this(a : Int) : this() { + if (a == 1) + return + return <!TYPE_MISMATCH!>1<!> + } + +} +fun illegalConstantBody(): Int = <!TYPE_MISMATCH!>"s"<!> +fun illegalConstantBlock(): String { + return <!ERROR_COMPILE_TIME_VALUE!>1<!> +} +fun illegalIfBody(): Int = + if (1 < 2) <!ERROR_COMPILE_TIME_VALUE!>'a'<!> else { <!ERROR_COMPILE_TIME_VALUE!>1.0<!> } +fun illegalIfBlock(): Boolean { + if (1 < 2) + return false + else { return <!ERROR_COMPILE_TIME_VALUE!>1<!> } +} +fun illegalReturnIf(): Char { + return if (1 < 2) 'a' else { <!ERROR_COMPILE_TIME_VALUE!>1<!> } +} + +fun returnNothing(): Nothing { + throw 1 +} +fun f(): Int { + if (1 < 2) { return 1 } else returnNothing() +} + +fun f(): Int = if (1 < 2) 1 else returnNothing() diff --git a/idea/testData/checkerWithErrorTypes/full/GenericArgumentConsistency.jet b/idea/testData/checkerWithErrorTypes/full/GenericArgumentConsistency.jet new file mode 100644 index 00000000000..fafd2cf98c8 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/GenericArgumentConsistency.jet @@ -0,0 +1,42 @@ +trait A<in T> {} +trait B<T> : A<Int> {} +trait C<T> : <!INCONSISTENT_TYPE_PARAMETER_VALUES!>B<T>, A<T><!> {} +trait C1<T> : B<T>, A<Any> {} +trait D : <!INCONSISTENT_TYPE_PARAMETER_VALUES, INCONSISTENT_TYPE_PARAMETER_VALUES!>C<Boolean>, B<Double><!>{} + +trait A1<out T> {} +trait B1 : A1<Int> {} +trait B2 : A1<Any>, B1 {} + +trait BA1<T> {} +trait BB1 : BA1<Int> {} +trait BB2 : <!INCONSISTENT_TYPE_PARAMETER_VALUES!>BA1<Any>, BB1<!> {} + + +namespace x { + trait AA1<out T> {} + trait AB1 : AA1<Int> {} + trait AB3 : AA1<Comparable<Int>> {} + trait AB2 : AA1<Number>, AB1, AB3 {} +} + +namespace x2 { + trait AA1<out T> {} + trait AB1 : AA1<Any> {} + trait AB3 : AA1<Comparable<Int>> {} + trait AB2 : <!INCONSISTENT_TYPE_PARAMETER_VALUES!>AA1<Number>, AB1, AB3<!> {} +} + +namespace x3 { + trait AA1<in T> {} + trait AB1 : AA1<Any> {} + trait AB3 : AA1<Comparable<Int>> {} + trait AB2 : AA1<Number>, AB1, AB3 {} +} + +namespace sx2 { + trait AA1<in T> {} + trait AB1 : AA1<Int> {} + trait AB3 : AA1<Comparable<Int>> {} + trait AB2 : <!INCONSISTENT_TYPE_PARAMETER_VALUES!>AA1<Number>, AB1, AB3<!> {} +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/IncDec.jet b/idea/testData/checkerWithErrorTypes/full/IncDec.jet new file mode 100644 index 00000000000..5b7143f3eef --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/IncDec.jet @@ -0,0 +1,46 @@ +class IncDec() { + fun inc() : IncDec = this + fun dec() : IncDec = this +} + +fun testIncDec() { + var x = IncDec() + x++ + ++x + x-- + --x + x = x++ + x = x-- + x = ++x + x = --x +} + +class WrongIncDec() { + fun inc() : Int = 1 + fun dec() : Int = 1 +} + +fun testWrongIncDec() { + var x = WrongIncDec() + x<!RESULT_TYPE_MISMATCH!>++<!> + <!RESULT_TYPE_MISMATCH!>++<!>x + x<!RESULT_TYPE_MISMATCH!>--<!> + <!RESULT_TYPE_MISMATCH!>--<!>x +} + +class UnitIncDec() { + fun inc() : Unit {} + fun dec() : Unit {} +} + +fun testUnitIncDec() { + var x = UnitIncDec() + x++ + ++x + x-- + --x + x = <!TYPE_MISMATCH!>x++<!> + x = <!TYPE_MISMATCH!>x--<!> + x = <!TYPE_MISMATCH!>++x<!> + x = <!TYPE_MISMATCH!>--x<!> +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/IsExpressions.jet b/idea/testData/checkerWithErrorTypes/full/IsExpressions.jet new file mode 100644 index 00000000000..960f3711e37 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/IsExpressions.jet @@ -0,0 +1,7 @@ +fun test() { + if (1 is Int) { + if (1 is <!INCOMPATIBLE_TYPES!>Boolean<!>) { + + } + } +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/MultipleBounds.jet b/idea/testData/checkerWithErrorTypes/full/MultipleBounds.jet new file mode 100644 index 00000000000..773ebaea33f --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/MultipleBounds.jet @@ -0,0 +1,72 @@ +namespace Jet87 + +open class A() { + fun foo() : Int = 1 +} + +trait B { + fun bar() : Double = 1.0; +} + +class C() : A(), B + +class D() { + class object : A(), B {} +} + +class Test1<T : A>() + where + T : B, + <!NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER!>B<!> : T, // error + class object T : A, + class object T : B, + class object <!NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER!>B<!> : T + { + + fun test(t : T) { + T.foo() + T.bar() + t.foo() + t.bar() + } +} + +fun test() { + Test1<<!UPPER_BOUND_VIOLATED!>B<!>>() + Test1<<!UPPER_BOUND_VIOLATED!>A<!>>() + Test1<C>() +} + +class Foo() {} + +class Bar<T : <!FINAL_UPPER_BOUND!>Foo<!>> + +class Buzz<T> where T : <!FINAL_UPPER_BOUND!>Bar<<!UPPER_BOUND_VIOLATED!>Int<!>><!>, T : <!UNRESOLVED_REFERENCE!>nioho<!> + +class X<T : <!FINAL_UPPER_BOUND!>Foo<!>> +class Y<<!CONFLICTING_UPPER_BOUNDS!>T<!> : <!FINAL_UPPER_BOUND!>Foo<!>> where T : <!FINAL_UPPER_BOUND!>Bar<Foo><!> + +fun <T : A> test2(t : T) + where + T : B, + <!NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER!>B<!> : T, + class object <!NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER!>B<!> : T, + class object T : B, + class object T : A +{ + T.foo() + T.bar() + t.foo() + t.bar() +} + +val t1 = test2<<!UPPER_BOUND_VIOLATED!>A<!>>(A()) +val t2 = test2<<!UPPER_BOUND_VIOLATED!>B<!>>(C()) +val t3 = test2<C>(C()) + +class Test<<!CONFLICTING_CLASS_OBJECT_UPPER_BOUNDS!>T<!>> + where + class object T : <!FINAL_CLASS_OBJECT_UPPER_BOUND!>Foo<!>, + class object T : A {} + +val <T, B : T> x : Int = 0 diff --git a/idea/testData/checkerWithErrorTypes/full/NamespaceAsExpression.jet b/idea/testData/checkerWithErrorTypes/full/NamespaceAsExpression.jet new file mode 100644 index 00000000000..a7e2a3a78a7 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/NamespaceAsExpression.jet @@ -0,0 +1,8 @@ +namespace root + +namespace a { + +} + +val x = <!EXPRESSION_EXPECTED_NAMESPACE_FOUND, UNRESOLVED_REFERENCE!>a<!> +val y2 = <!NAMESPACE_IS_NOT_AN_EXPRESSION!>namespace<!> diff --git a/idea/testData/checkerWithErrorTypes/full/NamespaceQualified.jet b/idea/testData/checkerWithErrorTypes/full/NamespaceQualified.jet new file mode 100644 index 00000000000..a298efcacfe --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/NamespaceQualified.jet @@ -0,0 +1,63 @@ +namespace foobar + +namespace a { + import java.* + + val a : util.List<Int>? = null + val a1 : <!UNRESOLVED_REFERENCE!>List<!><Int>? = null + +} + +abstract class Foo<T>() { + abstract val x : T<Int> +} + +namespace a { + import java.util.* + + val b : List<Int>? = a + val b1 : <!UNRESOLVED_REFERENCE!>util<!>.List<Int>? = a +} + +val x1 = a.a + +val y1 = a.b + + +///////////////////////////////////////////////////////////////////////// + +fun done<O>(result : O) : Iteratee<Any?, O> = StrangeIterateeImpl<Any?, O>(result) + +abstract class Iteratee<in I, out O> { + abstract fun process(item : I) : Iteratee<I, O> + abstract val isDone : Boolean + abstract val result : O + abstract fun done() : O +} + +class StrangeIterateeImpl<in I, out O>(val obj: O) : Iteratee<I, O> { + override fun process(item: I): Iteratee<I, O> = StrangeIterateeImpl<I, O>(obj) + override val isDone = true + override val result = obj + override fun done() = obj +} + +abstract class Sum() : Iteratee<Int, Int> { + override fun process(item : Int) : Iteratee<Int, Int> { + return foobar.done<Int>(item); + } + abstract override val isDone : Boolean + abstract override val result : Int + abstract override fun done() : Int +} + +abstract class Collection<E> : Iterable<E> { + fun iterate<O>(iteratee : Iteratee<E, O>) : O { + for (x in this) { + val it = iteratee.process(x) + if (it.isDone) return it.result + iteratee = it + } + return iteratee.done() + } +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/Nullability.jet b/idea/testData/checkerWithErrorTypes/full/Nullability.jet new file mode 100644 index 00000000000..8479b364cd8 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/Nullability.jet @@ -0,0 +1,280 @@ +fun test() { + val a : Int? = 0 + if (a != null) { + a.plus(1) + } + else { + a?.plus(1) + } + + val out : java.io.PrintStream? = null//= System.out + val ins = System.`in` + + out?.println() + ins?.read() + + if (ins != null) { + ins.read() + out?.println() + if (out != null) { + ins.read(); + out.println(); + } + } + + if (out != null && ins != null) { + ins.read(); + out.println(); + } + + if (out == null) { + out?.println() + } else { + out.println() + } + + if (out != null && ins != null || out != null) { + ins?.read(); + out.println(); + } + + if (out == null || out.println(0) == ()) { + out?.println(1) + } + else { + out.println(2) + } + + if (out != null && out.println() == ()) { + out.println(); + } + else { + out?.println(); + } + + if (out == null || out != null && out.println() == ()) { + out?.println(); + } + else { + out.println(); + } + + if (1 == 2 || out != null && out.println(1) == ()) { + out?.println(2); + } + else { + out?.println(3) + } + + out?.println() + ins?.read() + + if (ins != null) { + ins.read() + out?.println() + if (out != null) { + ins.read(); + out.println(); + } + } + + if (out != null && ins != null) { + ins.read(); + out.println(); + } + + if (out == null) { + out?.println() + } else { + out.println() + } + + if (out != null && ins != null || out != null) { + ins?.read(); + out.println(); + } + + if (out == null || out.println(0) == ()) { + out?.println(1) + } + else { + out.println(2) + } + + if (out != null && out.println() == ()) { + out.println(); + } + else { + out?.println(); + } + + if (out == null || out != null && out.println() == ()) { + out?.println(); + } + else { + out.println(); + } + + if (1 == 2 || out != null && out.println(1) == ()) { + out?.println(2); + } + else { + out?.println(3) + } + + if (1 > 2) { + if (out == null) return; + out.println(); + } + out?.println(); + + while (out != null) { + out.println(); + } + out?.println(); + + while (out == null) { + out?.println(); + } + out.println() + +} + + +fun f(out : String?) { + out?.get(0) + if (out != null) else return; + out.get(0) +} + +fun f1(out : String?) { + out?.get(0) + if (out != null) else { + 1 + 2 + return; + } + out.get(0) +} + +fun f2(out : String?) { + out?.get(0) + if (out == null) { + 1 + 2 + return; + } + out.get(0) +} + +fun f3(out : String?) { + out?.get(0) + if (out == null) { + 1 + 2 + return; + } + else { + 1 + 2 + } + out.get(0) +} + +fun f4(s : String?) { + s?.get(0) + while (1 < 2 && s != null) { + s.get(0) + } + s?.get(0) + while (s == null || 1 < 2) { + s?.get(0) + } + s.get(0) +} + +fun f5(s : String?) { + s?.get(0) + while (1 < 2 && s != null) { + s.get(0) + } + s?.get(0) + while (s == null || 1 < 2) { + if (1 > 2) break + s?.get(0) + } + s?.get(0); +} + +fun f6(s : String?) { + s?.get(0) + do { + s?.get(0) + if (1 < 2) break; + } while (s == null) + s?.get(0) + do { + s?.get(0) + } while (s == null) + s.get(0) +} + +fun f7(s : String?, t : String?) { + s?.get(0) + if (!(s == null)) { + s.get(0) + } + s?.get(0) + if (!(s != null)) { + s?.get(0) + } + else { + s.get(0) + } + s?.get(0) + if (!!(s != null)) { + s.get(0) + } + else { + s?.get(0) + } + s?.get(0) + t?.get(0) + if (!(s == null || t == null)) { + s.get(0) + t.get(0) + } + else { + s?.get(0) + t?.get(0) + } + s?.get(0) + t?.get(0) + if (!(s == null && s == null)) { + s.get(0) + t?.get(0) + } + else { + s?.get(0) + t?.get(0) + } +} + +fun f8(b : String?, a : String) { + b?.get(0) + if (b == a) { + b.get(0); + } + b?.get(0) + if (a == b) { + b.get(0) + } + if (a != b) { + b?.get(0) + } + else { + b.get(0) + } +} + +fun f9(a : Int?) : Int { + if (a != null) + return a + return 1 +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/Objects.jet b/idea/testData/checkerWithErrorTypes/full/Objects.jet new file mode 100644 index 00000000000..79ed4e42644 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/Objects.jet @@ -0,0 +1,83 @@ +namespace toplevelObjectDeclarations { + open class Foo(y : Int) { + open fun foo() : Int = 1 + } + + class T : <!SUPERTYPE_NOT_INITIALIZED!>Foo<!> {} + + object A : <!SUPERTYPE_NOT_INITIALIZED!>Foo<!> { + val x : Int = 2 + + fun test() : Int { + return x + foo() + } + } + + object B : <!UNRESOLVED_REFERENCE!>A<!> {} + + val x = A.foo() + + val y = object : Foo(x) { + { + x + 12 + } + + override fun foo() : Int = 1 + } + + val z = y.foo() +} + +namespace nestedObejcts { + object A { + val b = B + val d = A.B.A + + object B { + val a = A + val e = B.A + + object A { + val a = A + val b = B + val x = nestedObejcts.A.B.A + val y = this<!AMBIGUOUS_LABEL!>@A<!> + } + } + + } + object B { + val b = B + val c = A.B + } + + val a = A + val b = B + val c = A.B + val d = A.B.A + val e = B.<!UNRESOLVED_REFERENCE!>A<!>.B +} + +namespace localObjects { + object A { + val x : Int = 0 + } + + open class Foo { + fun foo() : Int = 1 + } + + fun test() { + A.x + val b = object : Foo { + } + b.foo() + + object B { + fun foo() {} + } + B.foo() + } + + val bb = <!UNRESOLVED_REFERENCE!>B<!>.foo() +} diff --git a/idea/testData/checkerWithErrorTypes/full/Override.jet b/idea/testData/checkerWithErrorTypes/full/Override.jet new file mode 100644 index 00000000000..fecb1c72304 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/Override.jet @@ -0,0 +1,76 @@ +namespace override + +namespace normal { + trait MyTrait { + fun foo() + } + + abstract class MyAbstractClass { + abstract fun bar() + } + + open class MyClass : MyTrait, MyAbstractClass { + override fun foo() {} + override fun bar() {} + } + + class MyChildClass : MyClass {} + + class <!ABSTRACT_METHOD_NOT_IMPLEMENTED!>MyIllegalClass<!> : MyTrait, MyAbstractClass {} + + class <!ABSTRACT_METHOD_NOT_IMPLEMENTED!>MyIllegalClass2<!> : MyTrait, MyAbstractClass { + override fun foo() {} + } + + class <!ABSTRACT_METHOD_NOT_IMPLEMENTED!>MyIllegalClass3<!> : MyTrait, MyAbstractClass { + override fun bar() {} + } + + class <!ABSTRACT_METHOD_NOT_IMPLEMENTED!>MyIllegalClass4<!> : MyTrait, MyAbstractClass { + fun <!VIRTUAL_METHOD_HIDDEN!>foo<!>() {} + <!NOTHING_TO_OVERRIDE!>override<!> fun other() {} + } + + class MyChildClass1 : MyClass { + fun <!VIRTUAL_METHOD_HIDDEN!>foo<!>() {} + override fun bar() {} + } +} + +namespace generics { + trait MyTrait<T> { + fun foo(t: T) : T + } + + abstract class MyAbstractClass<T> { + abstract fun bar(t: T) : T + } + + open class MyGenericClass<T> : MyTrait<T>, MyAbstractClass<T> { + override fun foo(t: T) = t + override fun bar(t: T) = t + } + + class MyChildClass : MyGenericClass<Int> {} + class MyChildClass1<T> : MyGenericClass<T> {} + class MyChildClass2<T> : MyGenericClass<T> { + fun <!VIRTUAL_METHOD_HIDDEN!>foo<!>(t: T) = t + override fun bar(t: T) = t + } + + open class MyClass : MyTrait<Int>, MyAbstractClass<String> { + override fun foo(i: Int) = i + override fun bar(s: String) = s + } + + class <!ABSTRACT_METHOD_NOT_IMPLEMENTED!>MyIllegalGenericClass1<!><T> : MyTrait<T>, MyAbstractClass<T> {} + class <!ABSTRACT_METHOD_NOT_IMPLEMENTED!>MyIllegalGenericClass2<!><T, R> : MyTrait<T>, MyAbstractClass<R> { + <!NOTHING_TO_OVERRIDE!>override<!> fun foo(r: R) = r + } + class <!ABSTRACT_METHOD_NOT_IMPLEMENTED!>MyIllegalClass1<!> : MyTrait<Int>, MyAbstractClass<String> {} + + class <!ABSTRACT_METHOD_NOT_IMPLEMENTED!>MyIllegalClass2<!><T> : MyTrait<Int>, MyAbstractClass<Int> { + fun foo(t: T) = t + fun bar(t: T) = t + } +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/PrimaryConstructors.jet b/idea/testData/checkerWithErrorTypes/full/PrimaryConstructors.jet new file mode 100644 index 00000000000..8756860955f --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/PrimaryConstructors.jet @@ -0,0 +1,14 @@ +class <!PRIMARY_CONSTRUCTOR_MISSING_STATEFUL_PROPERTY!>X<!> { + val <!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>x<!> : Int +} + +open class Y() { + val x : Int = 2 +} + +class Y1 { + val x : Int get() = 1 +} + +class Z : Y<!PRIMARY_CONSTRUCTOR_MISSING_SUPER_CONSTRUCTOR_CALL!>()<!> { +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/ProjectionsInSupertypes.jet b/idea/testData/checkerWithErrorTypes/full/ProjectionsInSupertypes.jet new file mode 100644 index 00000000000..c02bb72b6a2 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/ProjectionsInSupertypes.jet @@ -0,0 +1,6 @@ +trait A<T> {} +trait B<T> {} +trait C<T> {} +trait D<T> {} + +trait Test : A<<!PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE!>in<!> Int>, B<<!PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE!>out<!> Int>, C<<!PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE!>*<!>><!NULLABLE_SUPERTYPE!>?<!><!NULLABLE_SUPERTYPE!>?<!><!NULLABLE_SUPERTYPE!>?<!>, D<Int> {} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/Properties.jet b/idea/testData/checkerWithErrorTypes/full/Properties.jet new file mode 100644 index 00000000000..999ebc5173e --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/Properties.jet @@ -0,0 +1,28 @@ + var x : Int = 1 + x + get() : Int = 1 + set(<!REF_SETTER_PARAMETER!>ref<!> value : <!WRONG_SETTER_PARAMETER_TYPE!>Long<!>) { + $x = value.int + $x = <!TYPE_MISMATCH!>1.lng<!> + } + + val xx : Int = <!PROPERTY_INITIALIZER_NO_BACKING_FIELD!>1 + x<!> + get() : Int = 1 + <!VAL_WITH_SETTER!>set(value : Long) {}<!> + + val p : Int = <!PROPERTY_INITIALIZER_NO_BACKING_FIELD!>1<!> + get() = 1 + +class Test() { + var a : Int = 111 + var b : Int get() = <!UNRESOLVED_REFERENCE!>$a<!>; set(x) {a = x; <!UNRESOLVED_REFERENCE!>$a<!> = x} + + this(i : Int) : this() { + <!NO_BACKING_FIELD!>$b<!> = $a + $a = <!NO_BACKING_FIELD!>$b<!> + a = <!NO_BACKING_FIELD!>$b<!> + } + fun f() { + <!UNRESOLVED_REFERENCE!>$b<!> = <!UNRESOLVED_REFERENCE!>$a<!> + a = <!UNRESOLVED_REFERENCE!>$b<!> + } +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/QualifiedExpressions.jet b/idea/testData/checkerWithErrorTypes/full/QualifiedExpressions.jet new file mode 100644 index 00000000000..67233fd840f --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/QualifiedExpressions.jet @@ -0,0 +1,11 @@ +namespace qualified_expressions + +fun test(s: String?) { + val a: Int = <!TYPE_MISMATCH!>s?.length<!> + val b: Int? = s?.length + val c: Int = s?.length ?: -11 + val d: Int = s?.length ?: <!TYPE_MISMATCH!>"empty"<!> + val e: String = <!TYPE_MISMATCH!>s?.length<!> ?: "empty" + val f: Int = s?.length ?: b ?: 1 + val g: Int? = e? startsWith("s")?.length +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/QualifiedThis.jet b/idea/testData/checkerWithErrorTypes/full/QualifiedThis.jet new file mode 100644 index 00000000000..f23c01cfd20 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/QualifiedThis.jet @@ -0,0 +1,41 @@ +class Dup { + fun Dup() : Unit { + this<!AMBIGUOUS_LABEL!>@Dup<!> + } +} + +class A() { + fun foo() : Unit { + this@A + this<!UNRESOLVED_REFERENCE!>@a<!> + this + } + + val x = this@A.foo() + val y = this.foo() + val z = foo() +} + +fun foo1() : Unit { + <!NO_THIS!>this<!> + this<!UNRESOLVED_REFERENCE!>@a<!> +} + +namespace closures { + class A(val a:Int) { + + class B() { + val x = this@B : B + val y = this@A : A + val z = this : B + val Int.xx = this : Int + fun Char.xx() : Any { + this : Char + val a = {Double.() => this : Double + this@xx : Char} + val b = @a{Double.() => this@a : Double + this@xx : Char} + val c = @a{() => <!NO_THIS!>this@a<!> + this@xx : Char} + return (@a{Double.() => this@a : Double + this@xx : Char}) + } + } + } +} diff --git a/idea/testData/checkerWithErrorTypes/full/RecursiveTypeInference.jet b/idea/testData/checkerWithErrorTypes/full/RecursiveTypeInference.jet new file mode 100644 index 00000000000..11eb880a193 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/RecursiveTypeInference.jet @@ -0,0 +1,42 @@ +namespace a { + val foo = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>bar()<!> + + fun bar() = foo +} + +namespace b { + fun foo() = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>bar()<!> + + fun bar() = foo() +} + +namespace c { + fun bazz() = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>bar()<!> + + fun foo() = bazz() + + fun bar() = foo() +} + +namespace ok { + + namespace a { + val foo = bar() + + fun bar() : Int = foo + } + + namespace b { + fun foo() : Int = bar() + + fun bar() = foo() + } + + namespace c { + fun bazz() = bar() + + fun foo() : Int = bazz() + + fun bar() = foo() + } +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/Redeclarations.jet b/idea/testData/checkerWithErrorTypes/full/Redeclarations.jet new file mode 100644 index 00000000000..3068a16b54d --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/Redeclarations.jet @@ -0,0 +1,16 @@ +namespace redeclarations { + object <!REDECLARATION, REDECLARATION!>A<!> { + val x : Int = 0 + + val A = 1 + } + + namespace <!REDECLARATION!>A<!> { + class A {} + } + + class <!REDECLARATION, REDECLARATION!>A<!> {} + + val <!REDECLARATION!>A<!> = 1 + +} diff --git a/idea/testData/checkerWithErrorTypes/full/ResolveToJava.jet b/idea/testData/checkerWithErrorTypes/full/ResolveToJava.jet new file mode 100644 index 00000000000..e2385007530 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/ResolveToJava.jet @@ -0,0 +1,52 @@ +import java.* +import util.* +import <!UNRESOLVED_REFERENCE!>utils<!>.* + +import java.io.PrintStream +import java.lang.Comparable as Com + +val l : List<in Int> = ArrayList<Int>() + +fun test(l : java.util.List<Int>) { + val x : java.<!UNRESOLVED_REFERENCE!>List<!> + val y : java.util.List<Int> + val b : java.lang.Object + val a : util.List<Int> + val z : java.<!UNRESOLVED_REFERENCE!>utils<!>.List<Int> + + val f : java.io.File? = null + + Collections.<!UNRESOLVED_REFERENCE!>emptyList<!> + Collections.emptyList<Int> + Collections.emptyList<Int>() + Collections.emptyList() + + Collections.singleton<Int>(1) : Set<Int>? + Collections.singleton<Int>(<!ERROR_COMPILE_TIME_VALUE!>1.0<!>) + + <!UNRESOLVED_REFERENCE!>List<!><Int> + + + val o = "sdf" <!CAST_NEVER_SUCCEEDS!>as<!> Object + + try { + // ... + } + catch(e: Exception) { + System.out?.println(e.getMessage()) + } + + PrintStream("sdf") + + val c : Com<Int>? = null + + c : java.lang.Comparable<Int>? + +// Collections.sort<Integer>(ArrayList<Integer>()) + xxx.<!UNRESOLVED_REFERENCE!>Class<!>() +} + + +namespace xxx { + import java.lang.Class; +} diff --git a/idea/testData/checkerWithErrorTypes/full/StringTemplates.jet b/idea/testData/checkerWithErrorTypes/full/StringTemplates.jet new file mode 100644 index 00000000000..108ffe1d7dd --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/StringTemplates.jet @@ -0,0 +1,21 @@ +fun demo() { + val abc = 1 + val a = "" + val asd = 1 + val bar = 5 + fun map(f : fun () : Any?) : Int = 1 + fun buzz(f : fun () : Any?) : Int = 1 + val sdf = 1 + val foo = 3; + "$abc" + "$" + "$.$.asdf$\t" + "asd\$" + "asd$a<!ILLEGAL_ESCAPE_SEQUENCE!>\x<!>" + "asd$a$asd$ $<!UNRESOLVED_REFERENCE!>xxx<!>" + "fosdfasdo${1 + bar + 100}}sdsdfgdsfsdf" + "foo${bar + map {foo}}sdfsdf" + "foo${bar + map { "foo" }}sdfsdf" + "foo${bar + map { + "foo$sdf${ buzz{}}" }}sdfsdf" +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/SupertypeListChecks.jet b/idea/testData/checkerWithErrorTypes/full/SupertypeListChecks.jet new file mode 100644 index 00000000000..b63a4d3af5d --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/SupertypeListChecks.jet @@ -0,0 +1,51 @@ +// KT-286 Check supertype lists + +/* +In a supertype list: + Same type should not be mentioned twice + Same type should not be indirectly mentioned with incoherent type arguments + Every trait's required dependencies should be satisfied + No final types should appear + Only one class is allowed +*/ + +class C1() + +open class OC1() + +open class C2 {} + +open class C3 {} + +trait T1 {} + +trait T2<T> {} + +trait Test<!CONSTRUCTOR_IN_TRAIT!>()<!> { + <!CONSTRUCTOR_IN_TRAIT, SECONDARY_CONSTRUCTOR_NO_INITIALIZER_LIST!>this<!>(x : Int) {} +} + +trait Test1 : C2<!SUPERTYPE_INITIALIZED_IN_TRAIT!>()<!> {} + +trait Test2 : C2 {} + +trait Test3 : C2, <!MANY_CLASSES_IN_SUPERTYPE_LIST!>C3<!> {} + +trait Test4 : T1 {} + +trait Test5 : T1, <!SUPERTYPE_APPEARS_TWICE!>T1<!> {} + +trait Test6 : <!FINAL_SUPERTYPE!>C1<!> {} + +class CTest1() : OC1() {} + +class CTest2 : C2 {} + +class CTest3 : C2, <!MANY_CLASSES_IN_SUPERTYPE_LIST!>C3<!> {} + +class CTest4 : T1 {} + +class CTest5 : T1, <!SUPERTYPE_APPEARS_TWICE!>T1<!> {} + +class CTest6 : <!SUPERTYPE_NOT_INITIALIZED, FINAL_SUPERTYPE!>C1<!> {} + diff --git a/idea/testData/checkerWithErrorTypes/full/TraitSupertypeList.jet b/idea/testData/checkerWithErrorTypes/full/TraitSupertypeList.jet new file mode 100644 index 00000000000..7f109773457 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/TraitSupertypeList.jet @@ -0,0 +1,11 @@ +open class bar() + +trait Foo<!CONSTRUCTOR_IN_TRAIT!>()<!> : bar<!SUPERTYPE_INITIALIZED_IN_TRAIT!>()<!>, <!MANY_CLASSES_IN_SUPERTYPE_LIST, SUPERTYPE_APPEARS_TWICE!>bar<!>, <!MANY_CLASSES_IN_SUPERTYPE_LIST, SUPERTYPE_APPEARS_TWICE!>bar<!> { + <!CONSTRUCTOR_IN_TRAIT, SECONDARY_CONSTRUCTOR_NO_INITIALIZER_LIST!>this<!>(x : Int) {} +} + +trait Foo2 : bar, Foo { +} + +open class Foo1() : bar(), <!SUPERTYPE_NOT_INITIALIZED, MANY_CLASSES_IN_SUPERTYPE_LIST, SUPERTYPE_APPEARS_TWICE!>bar<!>, Foo, <!SUPERTYPE_APPEARS_TWICE!>Foo<!><!CONSTRUCTOR_IN_TRAIT!>()<!> {} +open class Foo12 : bar<!PRIMARY_CONSTRUCTOR_MISSING_SUPER_CONSTRUCTOR_CALL!>()<!>, <!SUPERTYPE_NOT_INITIALIZED, MANY_CLASSES_IN_SUPERTYPE_LIST, SUPERTYPE_APPEARS_TWICE!>bar<!> {} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/UnreachableCode.jet b/idea/testData/checkerWithErrorTypes/full/UnreachableCode.jet new file mode 100644 index 00000000000..2a72a04117d --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/UnreachableCode.jet @@ -0,0 +1,161 @@ +fun t1() : Int{ + return 0 + <!UNREACHABLE_CODE!>1<!> +} + +fun t1a() : Int { + <!RETURN_TYPE_MISMATCH!>return<!> + <!UNREACHABLE_CODE!>return 1<!> + <!UNREACHABLE_CODE!>1<!> +} + +fun t1b() : Int { + return 1 + <!UNREACHABLE_CODE!>return 1<!> + <!UNREACHABLE_CODE!>1<!> +} + +fun t1c() : Int { + return 1 + <!RETURN_TYPE_MISMATCH, UNREACHABLE_CODE!>return<!> + <!UNREACHABLE_CODE!>1<!> +} + +fun t2() : Int { + if (1 > 2) + return 1 + else return 1 + <!UNREACHABLE_CODE!>1<!> +} + +fun t2a() : Int { + if (1 > 2) { + return 1 + <!UNREACHABLE_CODE!>1<!> + } else { return 1 + <!UNREACHABLE_CODE!>2<!> + } + <!UNREACHABLE_CODE!>1<!> +} + +fun t3() : Any { + if (1 > 2) + return 2 + else return "" + <!UNREACHABLE_CODE!>1<!> +} + +fun t4(a : Boolean) : Int { + do { + return 1 + } + while (<!UNREACHABLE_CODE!>a<!>) + <!UNREACHABLE_CODE!>1<!> +} + +fun t4break(a : Boolean) : Int { + do { + break + } + while (<!UNREACHABLE_CODE!>a<!>) + return 1 +} + +fun t5() : Int { + do { + return 1 + <!UNREACHABLE_CODE!>2<!> + } + while (<!UNREACHABLE_CODE!>1 > 2<!>) + <!UNREACHABLE_CODE!>return 1<!> +} + +fun t6() : Int { + while (1 > 2) { + return 1 + <!UNREACHABLE_CODE!>2<!> + } + return 1 +} + +fun t6break() : Int { + while (1 > 2) { + break + <!UNREACHABLE_CODE!>2<!> + } + return 1 +} + +fun t7(b : Int) : Int { + for (i in 1..b) { + return 1 + <!UNREACHABLE_CODE!>2<!> + } + return 1 +} + +fun t7break(b : Int) : Int { + for (i in 1..b) { + return 1 + <!UNREACHABLE_CODE!>2<!> + } + return 1 +} + +fun t7() : Int { + try { + return 1 + <!UNREACHABLE_CODE!>2<!> + } + catch (e : Any) { + 2 + } + return 1 // this is OK, like in Java +} + +fun t8() : Int { + try { + return 1 + <!UNREACHABLE_CODE!>2<!> + } + catch (e : Any) { + return 1 + <!UNREACHABLE_CODE!>2<!> + } + <!UNREACHABLE_CODE!>return 1<!> +} + +fun blockAndAndMismatch() : Boolean { + <!UNREACHABLE_CODE!>(return true) || (return false)<!> + <!UNREACHABLE_CODE!>return true<!> +} + +fun tf() : Int { + try {<!UNREACHABLE_CODE!>return 1<!>} finally{return 1} + <!UNREACHABLE_CODE!>return 1<!> +} + +fun failtest(a : Int) : Int { + <!UNREACHABLE_BECAUSE_OF_NOTHING!>if (fail() || true) { + + }<!> + <!UNREACHABLE_BECAUSE_OF_NOTHING!>return 1<!> +} + +fun foo(a : Nothing) : Unit { + 1 + a + <!UNREACHABLE_BECAUSE_OF_NOTHING!>2<!> +} + +fun fail() : Nothing { + throw java.lang.RuntimeException() +} + +fun nullIsNotNothing() : Unit { + val x : Int? = 1 + if (x != null) { + return + } + fail() +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/Unresolved.jet b/idea/testData/checkerWithErrorTypes/full/Unresolved.jet new file mode 100644 index 00000000000..48ea2a58e4d --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/Unresolved.jet @@ -0,0 +1,30 @@ +namespace unresolved + +fun testGenericArgumentsCount() { + val p1: Tuple2<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><Int><!> = (2, 2) + val p2: <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>Tuple2<!> = (2, 2) +} + +fun testUnresolved() { + if (<!UNRESOLVED_REFERENCE!>a<!> is String) { + val s = <!UNRESOLVED_REFERENCE!>a<!> + } + <!UNRESOLVED_REFERENCE!>foo<!>(<!UNRESOLVED_REFERENCE!>a<!>) + val s = "s" + <!UNRESOLVED_REFERENCE!>foo<!>(s) + foo1(<!UNRESOLVED_REFERENCE!>i<!>) + s.<!UNRESOLVED_REFERENCE!>foo<!>() + + when(<!UNRESOLVED_REFERENCE!>a<!>) { + is Int => <!UNRESOLVED_REFERENCE!>a<!> + is String => <!UNRESOLVED_REFERENCE!>a<!> + } + + //TODO + for (j in <!UNRESOLVED_REFERENCE!>collection<!>) { + val i: Int = j + j += 1 + } +} + +fun foo1(i: Int) {} diff --git a/idea/testData/checkerWithErrorTypes/full/Variance.jet b/idea/testData/checkerWithErrorTypes/full/Variance.jet new file mode 100644 index 00000000000..9b6531ffd02 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/Variance.jet @@ -0,0 +1,40 @@ +namespace variance + +abstract class Consumer<in T> {} + +abstract class Producer<out T> {} + +abstract class Usual<T> {} + +fun foo(c: Consumer<Int>, p: Producer<Int>, u: Usual<Int>) { + val c1: Consumer<Any> = <!TYPE_MISMATCH!>c<!> + val c2: Consumer<Int> = c1 + + val p1: Producer<Any> = p + val p2: Producer<Int> = <!TYPE_MISMATCH!>p1<!> + + val u1: Usual<Any> = <!TYPE_MISMATCH!>u<!> + val u2: Usual<Int> = <!TYPE_MISMATCH!>u1<!> +} + +//Arrays copy example +class Array<T>(val length : Int) { + fun get(index : Int) : T { return null } + fun set(index : Int, value : T) { /* ... */ } +} + +fun copy1(from : Array<Any>, to : Array<Any>) {} + +fun copy2(from : Array<out Any>, to : Array<in Any>) {} + +fun <T> copy3(from : Array<out T>, to : Array<in T>) {} + +fun copy4(from : Array<out Number>, to : Array<in Int>) {} + +fun f(ints: Array<Int>, any: Array<Any>, numbers: Array<Number>) { + copy1(<!TYPE_MISMATCH!>ints<!>, any) + copy2(ints, any) //ok + copy2(ints, <!TYPE_MISMATCH!>numbers<!>) + copy3<Int>(ints, numbers) + copy4(ints, numbers) //ok +} diff --git a/idea/testData/checkerWithErrorTypes/full/When.jet b/idea/testData/checkerWithErrorTypes/full/When.jet new file mode 100644 index 00000000000..f8612546d1c --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/When.jet @@ -0,0 +1,61 @@ +fun foo() : Int { + val s = "" + val x = 1 + when (x) { + is * => 1 + is <!INCOMPATIBLE_TYPES!>String<!> => 1 + !is Int => 1 + is Any? => 1 + <!INCOMPATIBLE_TYPES!>s<!> => 1 + 1 => 1 + 1 + <!UNRESOLVED_REFERENCE!>a<!> => 1 + in 1..<!UNRESOLVED_REFERENCE!>a<!> => 1 + !in 1..<!UNRESOLVED_REFERENCE!>a<!> => 1 + .<!UNRESOLVED_REFERENCE!>a<!> => 1 + .equals(1).<!UNRESOLVED_REFERENCE!>a<!> => 1 + <!UNNECESSARY_SAFE_CALL!>?.<!>equals(1) => 1 + else => 1 + } + return when (<!USELESS_ELVIS!>x<!>?:null) { + <!UNSAFE_CALL!>.<!>equals(1) => 1 + ?.equals(1).equals(2) => 1 + } +} + +val _type_test : Int = foo() // this is needed to ensure the inferred return type of foo() + +fun test() { + val x = 1; + val s = ""; + + when (x) { + <!INCOMPATIBLE_TYPES!>s<!> => 1 + is <!INCOMPATIBLE_TYPES!>""<!> => 1 + x => 1 + is 1 => 1 + is <!TYPE_MISMATCH_IN_TUPLE_PATTERN!>(1, 1)<!> => 1 + } + + val z = (1, 1) + + when (z) { + is (*, *) => 1 + is (*, 1) => 1 + is (1, 1) => 1 + is (1, <!INCOMPATIBLE_TYPES!>"1"<!>) => 1 + is <!TYPE_MISMATCH_IN_TUPLE_PATTERN!>(1, "1", *)<!> => 1 + is boo @ (1, <!INCOMPATIBLE_TYPES!>"a"<!>, *) => 1 + is boo @ <!TYPE_MISMATCH_IN_TUPLE_PATTERN!>(1, *)<!> => 1 + } + + when (z) { + <!ELSE_MISPLACED_IN_WHEN!>else => 1<!> + (1, 1) => 2 + } + + when (z) { + else => 1 + } +} + +val (Int, Int).boo : (Int, Int, Int) = (1, 1, 1) diff --git a/idea/testData/checkerWithErrorTypes/full/infos/Autocasts.jet b/idea/testData/checkerWithErrorTypes/full/infos/Autocasts.jet new file mode 100644 index 00000000000..ff7066a34f5 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/infos/Autocasts.jet @@ -0,0 +1,255 @@ +open class A() { + fun foo() {} +} + +class B() : A() { + fun bar() {} +} + +fun f9() { + val a : A? + a?.foo() + a?.<!UNRESOLVED_REFERENCE!>bar<!>() + if (a is B) { + a.bar() + a.foo() + } + a?.foo() + a?.<!UNRESOLVED_REFERENCE!>bar<!>() + if (!(a is B)) { + a?.<!UNRESOLVED_REFERENCE!>bar<!>() + a?.foo() + } + if (!(a is B) || a.bar() == ()) { + a?.<!UNRESOLVED_REFERENCE!>bar<!>() + } + if (!(a is B)) { + return; + } + a.bar() + a.foo() +} + +fun f10() { + val a : A? + if (!(a is B)) { + return; + } + if (!(a is B)) { + return; + } +} + +class C() : A() { + fun bar() { + + } +} + +fun f10(a : A?) { + if (a is B) { + if (a is C) { + a.bar(); + } + } +} + +fun f11(a : A?) { + when (a) { + is B => a.bar() + is A => a.foo() + is Any => a.foo() + is Any? => a.<!UNRESOLVED_REFERENCE!>bar<!>() + else => a?.foo() + } +} + +fun f12(a : A?) { + when (a) { + is B => a.bar() + is A => a.foo() + is Any => a.foo(); + is Any? => a.<!UNRESOLVED_REFERENCE!>bar<!>() + is val c : <!TYPE_MISMATCH_IN_BINDING_PATTERN!>B<!> => c.foo() + is val c is C => c.bar() + is val c is C => a.bar() + else => a?.foo() + } + + if (a is val b) { + a?.<!UNRESOLVED_REFERENCE!>bar<!>() + b?.foo() + } + if (a is val b is B) { + b.foo() + a.bar() + b.bar() + } +} + +fun f13(a : A?) { + if (a is val c is B) { + c.foo() + c.bar() + } + else { + a?.foo() + <!UNRESOLVED_REFERENCE!>c<!>.bar() + } + + a?.foo() + if (!(a is val c is B)) { + a?.foo() + <!UNRESOLVED_REFERENCE!>c<!>.bar() + } + else { + a.foo() + <!UNRESOLVED_REFERENCE!>c<!>.bar() + } + + a?.foo() + if (a is val c is B && a.foo() == () && c.bar() == ()) { + c.foo() + c.bar() + } + else { + a?.foo() + <!UNRESOLVED_REFERENCE!>c<!>.bar() + } + + if (!(a is val c is B) || !(a is val x is C)) { + <!UNRESOLVED_REFERENCE!>x<!> + <!UNRESOLVED_REFERENCE!>c<!> + } + else { + <!UNRESOLVED_REFERENCE!>x<!> + <!UNRESOLVED_REFERENCE!>c<!> + } + + if (!(a is val c is B) || !(a is val c is C)) { + } + + if (!(a is val c is B)) return + a.bar() + <!UNRESOLVED_REFERENCE!>c<!>.foo() + <!UNRESOLVED_REFERENCE!>c<!>.bar() +} + +fun f14(a : A?) { + while (!(a is val c is B)) { + } + a.bar() + <!UNRESOLVED_REFERENCE!>c<!>.bar() +} +fun f15(a : A?) { + do { + } while (!(a is val c is B)) + a.bar() + <!UNRESOLVED_REFERENCE!>c<!>.bar() +} + +fun getStringLength(obj : Any) : Char? { + if (obj !is String) + return null + return obj.get(0) // no cast to String is needed +} + +fun toInt(i: Int?): Int = if (i != null) i else 0 +fun illegalWhenBody(a: Any): Int = when(a) { + is Int => a + is String => <!TYPE_MISMATCH!>a<!> +} +fun illegalWhenBlock(a: Any): Int { + when(a) { + is Int => return a + is String => return <!TYPE_MISMATCH!>a<!> + } +} +fun declarations(a: Any?) { + if (a is String) { + val p4: (Int, String) = (2, a) + } + if (a is String?) { + if (a != null) { + val s: String = a + } + } + if (a != null) { + if (a is String?) { + val s: String = a + } + } +} +fun vars(a: Any?) { + var b: Int = 0 + if (a is Int) { + b = a + } +} +fun tuples(a: Any?) { + if (a != null) { + val s: (Any, String) = (a, <!TYPE_MISMATCH!>a<!>) + } + if (a is String) { + val s: (Any, String) = (a, a) + } + fun illegalTupleReturnType(): (Any, String) = (<!TYPE_MISMATCH!>a<!>, <!TYPE_MISMATCH!>a<!>) + if (a is String) { + fun legalTupleReturnType(): (Any, String) = (a, a) + } + val illegalFunctionLiteral: Function0<Int> = <!TYPE_MISMATCH!>{ <!TYPE_MISMATCH!>a<!> }<!> + val illegalReturnValueInFunctionLiteral: Function0<Int> = { (): Int => <!TYPE_MISMATCH!>a<!> } + + if (a is Int) { + val legalFunctionLiteral: Function0<Int> = { a } + val alsoLegalFunctionLiteral: Function0<Int> = { (): Int => a } + } +} +fun returnFunctionLiteralBlock(a: Any?): Function0<Int> { + if (a is Int) return { a } + else return { 1 } +} +fun returnFunctionLiteral(a: Any?): Function0<Int> = + if (a is Int) { (): Int => a } + else { () => 1 } + +fun illegalTupleReturnType(a: Any): (Any, String) = (a, <!TYPE_MISMATCH!>a<!>) + +fun declarationInsidePattern(x: (Any, Any)): String = when(x) { is (val a is String, *) => a; else => "something" } + +fun mergeAutocasts(a: Any?) { + if (a is String || a is Int) { + a.<!UNRESOLVED_REFERENCE!>compareTo<!>("") + a.toString() + } + if (a is Int || a is String) { + a.<!UNRESOLVED_REFERENCE!>compareTo<!>("") + } + when (a) { + is String, is Any => a.<!UNRESOLVED_REFERENCE!>compareTo<!>("") + } + if (a is String && a is Any) { + val i: Int = a.compareTo("") + } + if (a is String && a.compareTo("") == 0) {} + if (a is String || a.<!UNRESOLVED_REFERENCE!>compareTo<!>("") == 0) {} +} + +//mutability +fun f(): String { + var a: Any = 11 + if (a is String) { + val i: String = <!AUTOCAST_IMPOSSIBLE!>a<!> + <!AUTOCAST_IMPOSSIBLE!>a<!>.compareTo("f") + val f: Function0<String> = { <!AUTOCAST_IMPOSSIBLE!>a<!> } + return <!AUTOCAST_IMPOSSIBLE!>a<!> + } + return "" +} + +fun foo(var a: Any): Int { + if (a is Int) { + return <!AUTOCAST_IMPOSSIBLE!>a<!> + } + return 1 +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/infos/PropertiesWithBackingFields.jet b/idea/testData/checkerWithErrorTypes/full/infos/PropertiesWithBackingFields.jet new file mode 100644 index 00000000000..8bdd70dd54a --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/infos/PropertiesWithBackingFields.jet @@ -0,0 +1,57 @@ +abstract class Test() { + abstract val x : Int + abstract val x1 : Int get + abstract val x2 : Int <!ABSTRACT_PROPERTY_WITH_GETTER!>get() = 1<!> + + val <!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>a<!> : Int + val <!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>b<!> : Int get + val c = 1 + + val c1 = 1 + get + val c2 : Int + get() = 1 + val c3 : Int + get() { return 1 } + val c4 : Int + get() = 1 + val <!MUST_BE_INITIALIZED!>c5<!> : Int + get() = $c5 + 1 + + abstract var y : Int + abstract var y1 : Int get + abstract var y2 : Int set + abstract var y3 : Int set get + abstract var y4 : Int set <!ABSTRACT_PROPERTY_WITH_GETTER!>get() = 1<!> + abstract var y5 : Int <!ABSTRACT_PROPERTY_WITH_SETTER!>set(x) {}<!> <!ABSTRACT_PROPERTY_WITH_GETTER!>get() = 1<!> + abstract var y6 : Int <!ABSTRACT_PROPERTY_WITH_SETTER!>set(x) {}<!> + + var <!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>v<!> : Int + var <!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>v1<!> : Int get + var <!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>v2<!> : Int get set + var <!MUST_BE_INITIALIZED!>v3<!> : Int get() = 1; set + var v4 : Int get() = 1; set(x){} + + var <!MUST_BE_INITIALIZED!>v5<!> : Int get() = 1; set(x){$v5 = x} + var <!MUST_BE_INITIALIZED!>v6<!> : Int get() = $v6 + 1; set(x){} + + val v7 : Int abstract get + var v8 : Int abstract get abstract set + var <!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>v9<!> : Int abstract set + var <!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>v10<!> : Int abstract get + +} + +open class Super(i : Int) + +class TestPCParameters(w : Int, x : Int, val y : Int, var z : Int) : Super(w) { + + val xx = w + + { + w + 1 + } + + fun foo() = x + +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/regression/AmbiguityOnLazyTypeComputation.jet b/idea/testData/checkerWithErrorTypes/full/regression/AmbiguityOnLazyTypeComputation.jet new file mode 100644 index 00000000000..779ee4c4d97 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/regression/AmbiguityOnLazyTypeComputation.jet @@ -0,0 +1,12 @@ +// One of the two passes is making a scope and turning vals into functions +// See KT-76 + +namespace x + +val b : Foo = Foo() +val a1 = b.compareTo(2) + +class Foo() { + fun compareTo(other : Byte) : Int = 0 + fun compareTo(other : Char) : Int = 0 +} diff --git a/idea/testData/checkerWithErrorTypes/full/regression/AssignmentsUnderOperators.jet b/idea/testData/checkerWithErrorTypes/full/regression/AssignmentsUnderOperators.jet new file mode 100644 index 00000000000..5a7c24b7fd0 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/regression/AssignmentsUnderOperators.jet @@ -0,0 +1,6 @@ +fun test() { + val a : Any? = null + if (a is Any) else a = null; + while (a is Any) a = null + while (true) a = null +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/regression/CoercionToUnit.jet b/idea/testData/checkerWithErrorTypes/full/regression/CoercionToUnit.jet new file mode 100644 index 00000000000..6733ab3a31e --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/regression/CoercionToUnit.jet @@ -0,0 +1,9 @@ +fun foo(u : Unit) : Int = 1 + +fun test() : Int { + foo(<!TYPE_MISMATCH!>1<!>) + val a : fun() : Unit = { + foo(<!TYPE_MISMATCH!>1<!>) + } + return 1 +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/regression/DoubleDefine.jet b/idea/testData/checkerWithErrorTypes/full/regression/DoubleDefine.jet new file mode 100644 index 00000000000..fbca6a41c99 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/regression/DoubleDefine.jet @@ -0,0 +1,66 @@ +import java.* +import util.* + +import java.io.* + +fun takeFirst(expr: StringBuilder): Char { + val c = expr.charAt(0) + expr.deleteCharAt(0) + return c +} + +fun evaluateArg(expr: AbstractStringBuilder, numbers: ArrayList<Int>): Int { + if (expr.length() == 0) throw Exception("Syntax error: Character expected"); + val c = takeFirst(<!TYPE_MISMATCH!>expr<!>) + if (c >= '0' && c <= '9') { + val n = c - '0' + if (!numbers.contains(n)) throw Exception("You used incorrect number: " + n) + numbers.remove(n) + return n + } + throw Exception("Syntax error: Unrecognized character " + c) +} + +fun evaluateAdd(expr: StringBuilder, numbers: ArrayList<Int>): Int { + val lhs = evaluateArg(expr, numbers) + if (expr.length() > 0) { + + } + return lhs +} + +fun evaluate(expr: StringBuilder, numbers: ArrayList<Int>): Int { + val lhs = evaluateAdd(expr, numbers) + if (expr.length() > 0) { + val c = expr.charAt(0) + expr.deleteCharAt(0) + } + return lhs +} + +fun main(args: Array<String>) { + System.out?.println("24 game") + val numbers = ArrayList<Int>(4) + val rnd = Random(); + val prompt = StringBuilder() + for(val i in 0..3) { + val n = rnd.nextInt(9) + 1 + numbers.add(n) + if (i > 0) prompt.append(" "); + prompt.append(n) + } + System.out?.println("Your numbers: " + prompt) + System.out?.println("Enter your expression:") + val reader = BufferedReader(InputStreamReader(System.`in`)) + val expr = StringBuilder(reader.readLine()) + try { + val result = evaluate(expr, numbers) + if (result != 24) + System.out?.println("Sorry, that's " + result) + else + System.out?.println("You won!"); + } + catch(e: Throwable) { + System.out?.println(e.getMessage()) + } +} diff --git a/idea/testData/checkerWithErrorTypes/full/regression/Jet11.jet b/idea/testData/checkerWithErrorTypes/full/regression/Jet11.jet new file mode 100644 index 00000000000..eb42b6f2427 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/regression/Jet11.jet @@ -0,0 +1,4 @@ +// JET-11 Redeclaration & Forward reference for classes cause an exception +open class <!REDECLARATION!>NoC<!> +class NoC1 : NoC +open class <!REDECLARATION!>NoC<!> diff --git a/idea/testData/checkerWithErrorTypes/full/regression/Jet121.jet b/idea/testData/checkerWithErrorTypes/full/regression/Jet121.jet new file mode 100644 index 00000000000..fc29dfe5293 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/regression/Jet121.jet @@ -0,0 +1,14 @@ +namespace jet121 { + fun box() : String { + val answer = apply("OK") { String.() : Int => + get(0) + length + } + + return if (answer == 2) "OK" else "FAIL" + } + + fun apply(arg:String, f : fun String.() : Int) : Int { + return arg.f() + } +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/regression/Jet124.jet b/idea/testData/checkerWithErrorTypes/full/regression/Jet124.jet new file mode 100644 index 00000000000..317b1438f41 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/regression/Jet124.jet @@ -0,0 +1,8 @@ +fun foo1() : fun (Int) : Int = { (x: Int) => x } + +fun foo() { + val h : fun (Int) : Int = foo1(); + h(1) + val m : fun (Int) : Int = {(a : Int) => 1}//foo1() + m(1) +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/regression/Jet169.jet b/idea/testData/checkerWithErrorTypes/full/regression/Jet169.jet new file mode 100644 index 00000000000..000536ce340 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/regression/Jet169.jet @@ -0,0 +1,8 @@ +fun set(key : String, value : String) { + val a : String? = "" + when (a) { + "" => a<!UNSAFE_CALL!>.<!>get(0) + is String, is Any => a.compareTo("") + else => a.toString() + } +} diff --git a/idea/testData/checkerWithErrorTypes/full/regression/Jet17.jet b/idea/testData/checkerWithErrorTypes/full/regression/Jet17.jet new file mode 100644 index 00000000000..32cf98cd2fc --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/regression/Jet17.jet @@ -0,0 +1,6 @@ +// JET-17 Do not infer property types by the initializer before the containing scope is ready + +class WithC() { + val a = 1 + val b = $a // error here, but must not be +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/regression/Jet183-1.jet b/idea/testData/checkerWithErrorTypes/full/regression/Jet183-1.jet new file mode 100644 index 00000000000..37c72d83ef6 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/regression/Jet183-1.jet @@ -0,0 +1,21 @@ +abstract enum class ProtocolState { + WAITING { + override fun signal() = ProtocolState.TALKING + } + + TALKING { + override fun signal() = ProtocolState.WAITING + } + + abstract fun signal() : ProtocolState +} + + +fun box(): String { + val x: ProtocolState = ProtocolState.WAITING + x = x.signal() + if (x != ProtocolState.TALKING) return "fail 1" + x = x.signal() + if (x != ProtocolState.WAITING) return "fail 2" + return "OK" +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/regression/Jet183.jet b/idea/testData/checkerWithErrorTypes/full/regression/Jet183.jet new file mode 100644 index 00000000000..59df6e106d6 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/regression/Jet183.jet @@ -0,0 +1,22 @@ +abstract enum class ProtocolState { + WAITING { + override fun signal() = ProtocolState.TALKING + } + + TALKING { + override fun signal() = ProtocolState.WAITING + } + + abstract fun signal() : ProtocolState +} + +enum class Foo<T> { + <!NO_GENERICS_IN_SUPERTYPE_SPECIFIER!>X<!> + +} + + + +fun box() { + val x: ProtocolState = ProtocolState.WAITING +} diff --git a/idea/testData/checkerWithErrorTypes/full/regression/Jet53.jet b/idea/testData/checkerWithErrorTypes/full/regression/Jet53.jet new file mode 100644 index 00000000000..e880fe25bbd --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/regression/Jet53.jet @@ -0,0 +1,4 @@ +import java.util.Collections +import java.util.List + +val ab = Collections.emptyList<Int>() : List<Int>? \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/regression/Jet67.jet b/idea/testData/checkerWithErrorTypes/full/regression/Jet67.jet new file mode 100644 index 00000000000..49a449094ec --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/regression/Jet67.jet @@ -0,0 +1,4 @@ +abstract class XXX { + val a : Int abstract get + +} diff --git a/idea/testData/checkerWithErrorTypes/full/regression/Jet68.jet b/idea/testData/checkerWithErrorTypes/full/regression/Jet68.jet new file mode 100644 index 00000000000..2d9cc4c7b21 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/regression/Jet68.jet @@ -0,0 +1,11 @@ +class Foo() + +fun test() { + val f : Foo? = null + if (f == null) { + + } + if (f != null) { + + } +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/regression/Jet69.jet b/idea/testData/checkerWithErrorTypes/full/regression/Jet69.jet new file mode 100644 index 00000000000..dd198aa0f61 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/regression/Jet69.jet @@ -0,0 +1,10 @@ +class Command() {} + +fun parse(cmd: String): Command? { return null } + +fun Any.equals(other : Any?) : Boolean = this === other + +fun main(args: Array<String>) { + val command = parse("") + if (command == null) 1 // error on this line, but must be OK +} diff --git a/idea/testData/checkerWithErrorTypes/full/regression/Jet72.jet b/idea/testData/checkerWithErrorTypes/full/regression/Jet72.jet new file mode 100644 index 00000000000..d3d3272c8e3 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/regression/Jet72.jet @@ -0,0 +1,17 @@ +// JET-72 Type inference doesn't work when iterating over ArrayList + +import java.util.ArrayList + +abstract class Item(val room: Object) { + abstract val name : String +} + +val items: ArrayList<Item> = ArrayList<Item> + +fun test(room : Object) { + for(val item: Item in items) { + if (item.room === room) { + System.out?.println("You see " + item.name) + } + } +} diff --git a/idea/testData/checkerWithErrorTypes/full/regression/Jet81.jet b/idea/testData/checkerWithErrorTypes/full/regression/Jet81.jet new file mode 100644 index 00000000000..c3df9ba023f --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/regression/Jet81.jet @@ -0,0 +1,22 @@ +// JET-81 Assertion fails when processing self-referring anonymous objects + +val y = object { + val a = y; +} + +val z = y.a; + +object A { + val x = A +} + +val a = object { + { + b + 1 + } + val x = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>b<!> + val y = 1 +} + +val b = a.x +val c = a.y diff --git a/idea/testData/checkerWithErrorTypes/full/regression/OverrideResolution.jet b/idea/testData/checkerWithErrorTypes/full/regression/OverrideResolution.jet new file mode 100644 index 00000000000..b58ac616160 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/regression/OverrideResolution.jet @@ -0,0 +1,16 @@ +fun box() { + val a : C + a.foo() +} + +open class A { + open fun foo() {} +} + +open class B : A { + override fun foo() {} +} + +open class C : B { + override fun foo() {} +} diff --git a/idea/testData/checkerWithErrorTypes/full/regression/ScopeForSecondaryConstructors.jet b/idea/testData/checkerWithErrorTypes/full/regression/ScopeForSecondaryConstructors.jet new file mode 100644 index 00000000000..2cac1044074 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/regression/ScopeForSecondaryConstructors.jet @@ -0,0 +1,18 @@ + class Foo(var bar : Int, barr : Int, val barrr : Int) { + { + bar = 1 + barr = 1 + barrr = 1 + 1 : Int + this : Foo + } + + this(val bar : Int) : this(1, 1, 1) { + bar = 1 + this.bar + 1 : Int + val a : Int =1 + this : Foo + } + } + diff --git a/idea/testData/checkerWithErrorTypes/full/regression/SpecififcityByReceiver.jet b/idea/testData/checkerWithErrorTypes/full/regression/SpecififcityByReceiver.jet new file mode 100644 index 00000000000..bbca53527c8 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/regression/SpecififcityByReceiver.jet @@ -0,0 +1,9 @@ +fun Any.equals(other : Any?) : Boolean = true + +fun main(args: Array<String>) { + + val command : Any = 1 + + command<!UNNECESSARY_SAFE_CALL!>?.<!>equals(null) + command.equals(null) +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/regression/ThisConstructorInGenericClass.jet b/idea/testData/checkerWithErrorTypes/full/regression/ThisConstructorInGenericClass.jet new file mode 100644 index 00000000000..cb4408bd600 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/regression/ThisConstructorInGenericClass.jet @@ -0,0 +1,3 @@ +class Z() { + this(x : Int) : this() {} +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/regression/WrongTraceInCallResolver.jet b/idea/testData/checkerWithErrorTypes/full/regression/WrongTraceInCallResolver.jet new file mode 100644 index 00000000000..952ac6c3dbe --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/regression/WrongTraceInCallResolver.jet @@ -0,0 +1,9 @@ +open class Foo {} +open class Bar {} + +fun <T : Bar, T1> foo(x : Int) {} +fun <T1, T : Foo> foo(x : Long) {} + +fun f(): Unit { + foo<<!UPPER_BOUND_VIOLATED!>Int<!>, Int>(1) +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/regression/kt251.jet b/idea/testData/checkerWithErrorTypes/full/regression/kt251.jet new file mode 100644 index 00000000000..bfbc0784224 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/regression/kt251.jet @@ -0,0 +1,33 @@ +class A() { + var x: Int = 0 + get() = <!TYPE_MISMATCH!>"s"<!> + set(value: <!WRONG_SETTER_PARAMETER_TYPE!>String<!>) { + $x = <!TYPE_MISMATCH!>value<!> + } + val y: Int + get(): <!WRONG_GETTER_RETURN_TYPE!>String<!> = "s" + val z: Int + get() { + return <!TYPE_MISMATCH!>"s"<!> + } + + var a: Any = 1 + set(v: <!WRONG_SETTER_PARAMETER_TYPE!>String<!>) { + $a = v + } + val b: Int + get(): <!WRONG_GETTER_RETURN_TYPE!>Any<!> = "s" + val c: Int + get() { + return 1 + } + val d = 1 + get() { + return $d + } + val e = 1 + get(): <!WRONG_GETTER_RETURN_TYPE!>String<!> { + return <!TYPE_MISMATCH!>$e<!> + } + +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/full/regression/kt303.jet b/idea/testData/checkerWithErrorTypes/full/regression/kt303.jet new file mode 100644 index 00000000000..ed38edc0bf0 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/full/regression/kt303.jet @@ -0,0 +1,11 @@ +// KT-303 Stack overflow on a cyclic class hierarchy + +open class Foo() : <!CYCLIC_INHERITANCE_HIERARCHY!>Bar<!>() { + val a : Int = 1 +} + +open class Bar() : <!CYCLIC_INHERITANCE_HIERARCHY!>Foo<!>() { + +} + +val x : Int = <!TYPE_MISMATCH!>Foo()<!> \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/quick/AutoCreatedIt.jet b/idea/testData/checkerWithErrorTypes/quick/AutoCreatedIt.jet new file mode 100644 index 00000000000..66c9e1f9543 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/quick/AutoCreatedIt.jet @@ -0,0 +1,32 @@ +fun text() { + "direct:a" to "mock:a" + "direct:a" on {it.body == "<hello/>"} to "mock:a" + "direct:a" on {it => it.body == "<hello/>"} to "mock:a" + bar <!TYPE_MISMATCH!>{1}<!> + bar <!TYPE_MISMATCH!>{<!UNRESOLVED_REFERENCE!>it<!> <!UNRESOLVED_REFERENCE!>+<!> 1}<!> + bar {it, it1 => it} + + bar1 {1} + bar1 {it + 1} + + bar2 <!TYPE_MISMATCH!>{<!TYPE_MISMATCH!><!>}<!> + bar2 {1} + bar2 {<!UNRESOLVED_REFERENCE!>it<!>} + bar2 <!TYPE_MISMATCH!>{<!CANNOT_INFER_PARAMETER_TYPE!>it<!> => it}<!> +} + +fun bar(f : fun (Int, Int) : Int) {} +fun bar1(f : fun (Int) : Int) {} +fun bar2(f : fun () : Int) {} + +fun String.to(dest : String) { + +} + +fun String.on(predicate : fun (s : URI) : Boolean) : URI { + return URI(this) +} + +class URI(val body : Any) { + fun to(dest : String) {} +} \ No newline at end of file diff --git a/idea/testData/checkerWithErrorTypes/quick/Basic.jet b/idea/testData/checkerWithErrorTypes/quick/Basic.jet new file mode 100644 index 00000000000..dea3b44a6e1 --- /dev/null +++ b/idea/testData/checkerWithErrorTypes/quick/Basic.jet @@ -0,0 +1,15 @@ +fun foo(u : Unit) : Int = 1 + +fun test() : Int { + foo(<!TYPE_MISMATCH!>1<!>) + val a : fun() : Unit = { + foo(<!TYPE_MISMATCH!>1<!>) + } + return 1 <!NONE_APPLICABLE!>-<!> "1" +} + +class A() { + val x : Int = <!TYPE_MISMATCH!>foo1(<!TOO_MANY_ARGUMENTS, UNRESOLVED_REFERENCE!>xx<!>)<!> +} + +fun foo1() {} \ No newline at end of file diff --git a/idea/testData/psi/ElvisSplit.jet b/idea/testData/psi/ElvisSplit.jet new file mode 100644 index 00000000000..1651641d1d5 --- /dev/null +++ b/idea/testData/psi/ElvisSplit.jet @@ -0,0 +1,2 @@ +val x = 1 : Int?:Any? +val y = null ?: 1 \ No newline at end of file diff --git a/idea/testData/psi/ElvisSplit.txt b/idea/testData/psi/ElvisSplit.txt new file mode 100644 index 00000000000..1048f76cd2e --- /dev/null +++ b/idea/testData/psi/ElvisSplit.txt @@ -0,0 +1,48 @@ +JetFile: ElvisSplit.jet + NAMESPACE + PROPERTY + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('x') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + BINARY_WITH_TYPE + BINARY_WITH_TYPE + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiWhiteSpace(' ') + OPERATION_REFERENCE + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + NULLABLE_TYPE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Int') + PsiElement(QUEST)('?') + OPERATION_REFERENCE + PsiElement(COLON)(':') + TYPE_REFERENCE + NULLABLE_TYPE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Any') + PsiElement(QUEST)('?') + PsiWhiteSpace('\n') + PROPERTY + PsiElement(val)('val') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('y') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + BINARY_EXPRESSION + NULL + PsiElement(null)('null') + PsiWhiteSpace(' ') + OPERATION_REFERENCE + PsiElement(ELVIS)('?:') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/JetLiteFixture.java b/idea/tests/org/jetbrains/jet/JetLiteFixture.java new file mode 100644 index 00000000000..e0c0051493f --- /dev/null +++ b/idea/tests/org/jetbrains/jet/JetLiteFixture.java @@ -0,0 +1,189 @@ +package org.jetbrains.jet; + +import com.intellij.ide.startup.impl.StartupManagerImpl; +import com.intellij.lang.*; +import com.intellij.lang.impl.PsiBuilderFactoryImpl; +import com.intellij.mock.*; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.EditorFactory; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl; +import com.intellij.openapi.fileEditor.impl.LoadTextUtil; +import com.intellij.openapi.fileTypes.FileTypeFactory; +import com.intellij.openapi.fileTypes.FileTypeManager; +import com.intellij.openapi.options.SchemesManagerFactory; +import com.intellij.openapi.progress.impl.ProgressManagerImpl; +import com.intellij.openapi.startup.StartupManager; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.CharsetToolkit; +import com.intellij.psi.*; +import com.intellij.psi.impl.PsiCachedValuesFactory; +import com.intellij.psi.impl.PsiFileFactoryImpl; +import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry; +import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistryImpl; +import com.intellij.psi.util.CachedValuesManager; +import com.intellij.testFramework.LightVirtualFile; +import com.intellij.testFramework.MockSchemesManagerFactory; +import com.intellij.testFramework.PlatformLiteFixture; +import com.intellij.testFramework.TestDataFile; +import com.intellij.util.CachedValuesManagerImpl; +import com.intellij.util.Function; +import com.intellij.util.messages.MessageBus; +import com.intellij.util.messages.MessageBusFactory; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.jet.lang.parsing.JetParserDefinition; +import org.picocontainer.MutablePicoContainer; +import org.picocontainer.PicoContainer; +import org.picocontainer.PicoInitializationException; +import org.picocontainer.PicoIntrospectionException; +import org.picocontainer.defaults.AbstractComponentAdapter; + +import java.io.File; +import java.io.IOException; + +/** + * @author abreslav + */ +public abstract class JetLiteFixture extends PlatformLiteFixture { + protected String myFileExt; + @NonNls + protected final String myFullDataPath; + protected PsiFile myFile; + private MockPsiManager myPsiManager; + private PsiFileFactoryImpl myFileFactory; + protected Language myLanguage; + protected final ParserDefinition[] myDefinitions; + + public JetLiteFixture(@NonNls String dataPath) { + myFileExt = "jet"; + myFullDataPath = getTestDataPath() + "/" + dataPath; + myDefinitions = new ParserDefinition[] {new JetParserDefinition()}; + } + + protected String getTestDataPath() { + return JetTestCaseBase.getTestDataPathBase(); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + initApplication(); + getApplication().getPicoContainer().registerComponent(new AbstractComponentAdapter("com.intellij.openapi.progress.ProgressManager", Object.class) { + @Override + public Object getComponentInstance(PicoContainer container) throws PicoInitializationException, PicoIntrospectionException { + return new ProgressManagerImpl(getApplication()); + } + + @Override + public void verify(PicoContainer container) throws PicoIntrospectionException { + } + }); + myProject = disposeOnTearDown(new MockProjectEx()); + myPsiManager = new MockPsiManager(myProject); + myFileFactory = new PsiFileFactoryImpl(myPsiManager); + final MutablePicoContainer appContainer = getApplication().getPicoContainer(); + registerComponentInstance(appContainer, MessageBus.class, MessageBusFactory.newMessageBus(getApplication())); + registerComponentInstance(appContainer, SchemesManagerFactory.class, new MockSchemesManagerFactory()); + final MockEditorFactory editorFactory = new MockEditorFactory(); + registerComponentInstance(appContainer, EditorFactory.class, editorFactory); + registerComponentInstance(appContainer, FileDocumentManager.class, new MockFileDocumentManagerImpl(new Function<CharSequence, Document>() { + @Override + public Document fun(CharSequence charSequence) { + return editorFactory.createDocument(charSequence); + } + }, FileDocumentManagerImpl.DOCUMENT_KEY)); + registerComponentInstance(appContainer, PsiDocumentManager.class, new MockPsiDocumentManager()); + myLanguage = myLanguage == null && myDefinitions != null && myDefinitions.length > 0 + ? myDefinitions[0].getFileNodeType().getLanguage() + : myLanguage; + registerComponentInstance(appContainer, FileTypeManager.class, new MockFileTypeManager(new MockLanguageFileType(myLanguage, myFileExt))); + registerApplicationService(PsiBuilderFactory.class, new PsiBuilderFactoryImpl()); + registerApplicationService(DefaultASTFactory.class, new DefaultASTFactoryImpl()); + registerApplicationService(ReferenceProvidersRegistry.class, new ReferenceProvidersRegistryImpl()); + myProject.registerService(CachedValuesManager.class, new CachedValuesManagerImpl(myProject, new PsiCachedValuesFactory(myPsiManager))); + myProject.registerService(PsiManager.class, myPsiManager); + myProject.registerService(StartupManager.class, new StartupManagerImpl(myProject)); + myProject.registerService(PsiFileFactory.class, new PsiFileFactoryImpl(myPsiManager)); + + registerExtensionPoint(FileTypeFactory.FILE_TYPE_FACTORY_EP, FileTypeFactory.class); + + for (ParserDefinition definition : myDefinitions) { + addExplicitExtension(LanguageParserDefinitions.INSTANCE, definition.getFileNodeType().getLanguage(), definition); + } + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + myFile = null; + myProject = null; + myPsiManager = null; + } + + protected String loadFile(@NonNls @TestDataFile String name) throws IOException { + return doLoadFile(myFullDataPath, name); + } + + protected static String doLoadFile(String myFullDataPath, String name) throws IOException { + String fullName = myFullDataPath + File.separatorChar + name; + String text = FileUtil.loadFile(new File(fullName), CharsetToolkit.UTF8).trim(); + text = StringUtil.convertLineSeparators(text); + return text; + } + + protected PsiFile createPsiFile(String name, String text) { + return createFile(name + "." + myFileExt, text); + } + + protected PsiFile createFile(@NonNls String name, String text) { + LightVirtualFile virtualFile = new LightVirtualFile(name, myLanguage, text); + virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET); + return myFileFactory.trySetupPsiForFile(virtualFile, myLanguage, true, false); + } + + protected static void ensureParsed(PsiFile file) { + file.accept(new PsiElementVisitor() { + @Override + public void visitElement(PsiElement element) { + element.acceptChildren(this); + } + }); + } + + protected <T> void registerApplicationService(final Class<T> aClass, T object) { + getApplication().registerService(aClass, object); + Disposer.register(myProject, new Disposable() { + @Override + public void dispose() { + getApplication().getPicoContainer().unregisterComponent(aClass.getName()); + } + }); + } + + protected <T> void addExplicitExtension(final LanguageExtension<T> instance, final Language language, final T object) { + instance.addExplicitExtension(language, object); + Disposer.register(myProject, new Disposable() { + @Override + public void dispose() { + instance.removeExplicitExtension(language, object); + } + }); + } + + protected void prepareForTest(String name) throws IOException { + String text = loadFile(name + "." + myFileExt); + createAndCheckPsiFile(name, text); + } + + protected void createAndCheckPsiFile(String name, String text) { + myFile = createPsiFile(name, text); + ensureParsed(myFile); + assertEquals("light virtual file text mismatch", text, ((LightVirtualFile) myFile.getVirtualFile()).getContent().toString()); + assertEquals("virtual file text mismatch", text, LoadTextUtil.loadText(myFile.getVirtualFile())); + assertEquals("doc text mismatch", text, myFile.getViewProvider().getDocument().getText()); + assertEquals("psi text mismatch", text, myFile.getText()); + } +} diff --git a/idea/tests/org/jetbrains/jet/JetTestCaseBase.java b/idea/tests/org/jetbrains/jet/JetTestCaseBase.java index 5ae4d8ff51e..f6ba28dcb72 100644 --- a/idea/tests/org/jetbrains/jet/JetTestCaseBase.java +++ b/idea/tests/org/jetbrains/jet/JetTestCaseBase.java @@ -43,11 +43,11 @@ public abstract class JetTestCaseBase extends LightDaemonAnalyzerTestCase { return getTestDataPathBase(); } - protected static String getTestDataPathBase() { + public static String getTestDataPathBase() { return getHomeDirectory() + "/idea/testData"; } - private static String getHomeDirectory() { + public static String getHomeDirectory() { return new File(PathManager.getResourceRoot(JetTestCaseBase.class, "/org/jetbrains/jet/JetTestCaseBase.class")).getParentFile().getParentFile().getParent(); } @@ -68,7 +68,11 @@ public abstract class JetTestCaseBase extends LightDaemonAnalyzerTestCase { @NotNull protected String getTestFilePath() { - return dataPath + name + ".jet"; + return dataPath + File.separator + name + ".jet"; + } + + protected String getDataPath() { + return dataPath; } public interface NamedTestFactory { diff --git a/idea/tests/org/jetbrains/jet/checkers/CheckerTestUtilTest.java b/idea/tests/org/jetbrains/jet/checkers/CheckerTestUtilTest.java new file mode 100644 index 00000000000..319e0b06789 --- /dev/null +++ b/idea/tests/org/jetbrains/jet/checkers/CheckerTestUtilTest.java @@ -0,0 +1,125 @@ +package org.jetbrains.jet.checkers; + +import com.google.common.collect.Lists; +import com.intellij.psi.PsiFile; +import org.jetbrains.jet.JetLiteFixture; +import org.jetbrains.jet.lang.diagnostics.Diagnostic; +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.ImportingStrategy; + +import java.util.Collections; +import java.util.List; + +/** + * @author abreslav + */ +public class CheckerTestUtilTest extends JetLiteFixture { + + public CheckerTestUtilTest() { + super("checkerWithErrorTypes/checkerTestUtil"); + } + + protected void doTest(TheTest theTest) throws Exception { + prepareForTest("test"); + theTest.test(myFile); + } + + public void testEquals() throws Exception { + doTest(new TheTest() { + @Override + protected void makeTestData(List<Diagnostic> diagnostics, List<CheckerTestUtil.DiagnosedRange> diagnosedRanges) { + } + }); + } + + public void testMissing() throws Exception { + doTest(new TheTest("Missing TYPE_MISMATCH at 56 to 57") { + @Override + protected void makeTestData(List<Diagnostic> diagnostics, List<CheckerTestUtil.DiagnosedRange> diagnosedRanges) { + diagnostics.remove(0); + } + }); + } + + public void testUnexpected() throws Exception { + doTest(new TheTest("Unexpected TYPE_MISMATCH at 56 to 57") { + @Override + protected void makeTestData(List<Diagnostic> diagnostics, List<CheckerTestUtil.DiagnosedRange> diagnosedRanges) { + diagnosedRanges.remove(0); + } + }); + } + + public void testBoth() throws Exception { + doTest(new TheTest("Unexpected TYPE_MISMATCH at 56 to 57", "Missing UNRESOLVED_REFERENCE at 166 to 168") { + @Override + protected void makeTestData(List<Diagnostic> diagnostics, List<CheckerTestUtil.DiagnosedRange> diagnosedRanges) { + diagnosedRanges.remove(0); + diagnostics.remove(diagnostics.size() - 1); + } + }); + } + + public void testMissingInTheMiddle() throws Exception { + doTest(new TheTest("Unexpected NONE_APPLICABLE at 122 to 123", "Missing TYPE_MISMATCH at 161 to 169") { + @Override + protected void makeTestData(List<Diagnostic> diagnostics, List<CheckerTestUtil.DiagnosedRange> diagnosedRanges) { + diagnosedRanges.remove(2); + diagnostics.remove(diagnostics.size() - 3); + } + }); + } + + private static abstract class TheTest { + private final String[] expected; + + protected TheTest(String... expectedMessages) { + this.expected = expectedMessages; + } + + public void test(PsiFile psiFile) { + BindingContext bindingContext = AnalyzingUtils.getInstance(ImportingStrategy.NONE).analyzeFileWithCache((JetFile) psiFile); + String expectedText = CheckerTestUtil.addDiagnosticMarkersToText(psiFile, bindingContext).toString(); + + List<CheckerTestUtil.DiagnosedRange> diagnosedRanges = Lists.newArrayList(); + CheckerTestUtil.parseDiagnosedRanges(expectedText, diagnosedRanges); + + List<Diagnostic> diagnostics = Lists.newArrayList(bindingContext.getDiagnostics()); + Collections.sort(diagnostics, CheckerTestUtil.DIAGNOSTIC_COMPARATOR); + + makeTestData(diagnostics, diagnosedRanges); + + final List<String> expectedMessages = Lists.newArrayList(expected); + final List<String> actualMessages = Lists.newArrayList(); + + CheckerTestUtil.diagnosticsDiff(diagnosedRanges, diagnostics, new CheckerTestUtil.DiagnosticDiffCallbacks() { + @Override + public void missingDiagnostic(String type, int expectedStart, int expectedEnd) { + String message = "Missing " + type + " at " + expectedStart + " to " + expectedEnd; + actualMessages.add(message); + } + + @Override + public void unexpectedDiagnostic(String type, int actualStart, int actualEnd) { + String message = "Unexpected " + type + " at " + actualStart + " to " + actualEnd; + actualMessages.add(message); + } + }); + + assertEquals(listToString(expectedMessages), listToString(actualMessages)); + } + + private String listToString(List<String> expectedMessages) { + StringBuilder stringBuilder = new StringBuilder(); + for (String expectedMessage : expectedMessages) { + stringBuilder.append(expectedMessage).append("\n"); + } + return stringBuilder.toString(); + } + + protected abstract void makeTestData(List<Diagnostic> diagnostics, List<CheckerTestUtil.DiagnosedRange> diagnosedRanges); + } + +} diff --git a/idea/tests/org/jetbrains/jet/checkers/FullJetPsiCheckerTest.java b/idea/tests/org/jetbrains/jet/checkers/FullJetPsiCheckerTest.java new file mode 100644 index 00000000000..597eb5e2b95 --- /dev/null +++ b/idea/tests/org/jetbrains/jet/checkers/FullJetPsiCheckerTest.java @@ -0,0 +1,117 @@ +package org.jetbrains.jet.checkers; + +import com.google.common.collect.Lists; +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.CharsetToolkit; +import junit.framework.Test; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.JetTestCaseBase; +import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; +import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.plugin.AnalyzerFacade; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.List; +import java.util.regex.Pattern; + +/** + * @author abreslav + */ +public class FullJetPsiCheckerTest extends JetTestCaseBase { + + public FullJetPsiCheckerTest(@NonNls String dataPath, String name) { + super(dataPath, name); + } + + + @Override + public void runTest() throws Exception { + String fileName = name + ".jet"; + String fullPath = getTestDataPath() + getTestFilePath(); + + + String expectedText = loadFile(fullPath); + + List<CheckerTestUtil.DiagnosedRange> diagnosedRanges = Lists.newArrayList(); + String clearText = CheckerTestUtil.parseDiagnosedRanges(expectedText, diagnosedRanges); + + configureFromFileText(fileName, clearText); + JetFile jetFile = (JetFile) myFile; + BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(jetFile); + + CheckerTestUtil.diagnosticsDiff(diagnosedRanges, bindingContext.getDiagnostics(), new CheckerTestUtil.DiagnosticDiffCallbacks() { + @Override + public void missingDiagnostic(String type, int expectedStart, int expectedEnd) { + String message = "Missing " + type + DiagnosticUtils.atLocation(myFile, new TextRange(expectedStart, expectedEnd)); + System.err.println(message); + } + + @Override + public void unexpectedDiagnostic(String type, int actualStart, int actualEnd) { + String message = "Unexpected " + type + DiagnosticUtils.atLocation(myFile, new TextRange(actualStart, actualEnd)); + System.err.println(message); + } + }); + + String actualText = CheckerTestUtil.addDiagnosticMarkersToText(jetFile, bindingContext).toString(); + + assertEquals(expectedText, actualText); + +// String myFullDataPath = getTestDataPath() + getDataPath(); +// System.out.println("myFullDataPath = " + myFullDataPath); +// convert(new File(myFullDataPath + "/../../checker/"), new File(myFullDataPath)); + } + + private String loadFile(String fullPath) throws IOException { + final File ioFile = new File(fullPath); + String fileText = FileUtil.loadFile(ioFile, CharsetToolkit.UTF8); + return StringUtil.convertLineSeparators(fileText); + } + + private void convert(File src, File dest) throws IOException { + File[] files = src.listFiles(); + for (File file : files) { + try { + if (file.isDirectory()) { + File destDir = new File(dest, file.getName()); + destDir.mkdir(); + convert(file, destDir); + continue; + } + if (!file.getName().endsWith(".jet")) continue; + String text = loadFile(file.getAbsolutePath()); + Pattern pattern = Pattern.compile("</?(error|warning|info( descr=\"[\\w ]+\")?)>"); + String clearText = pattern.matcher(text).replaceAll(""); + + configureFromFileText(file.getName(), clearText); + + BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache((JetFile) myFile); + String expectedText = CheckerTestUtil.addDiagnosticMarkersToText(myFile, bindingContext).toString(); + + File destFile = new File(dest, file.getName()); + FileWriter fileWriter = new FileWriter(destFile); + fileWriter.write(expectedText); + fileWriter.close(); + } + catch (RuntimeException e) { + e.printStackTrace(); + } + } + } + + public static Test suite() { + return JetTestCaseBase.suiteForDirectory(JetTestCaseBase.getTestDataPathBase(), "/checkerWithErrorTypes/full/", true, new JetTestCaseBase.NamedTestFactory() { + @NotNull + @Override + public Test createTest(@NotNull String dataPath, @NotNull String name) { + return new FullJetPsiCheckerTest(dataPath, name); + } + }); + } +} diff --git a/idea/tests/org/jetbrains/jet/checkers/QuickJetPsiCheckerTest.java b/idea/tests/org/jetbrains/jet/checkers/QuickJetPsiCheckerTest.java new file mode 100644 index 00000000000..b76d37388c0 --- /dev/null +++ b/idea/tests/org/jetbrains/jet/checkers/QuickJetPsiCheckerTest.java @@ -0,0 +1,104 @@ +package org.jetbrains.jet.checkers; + +import com.google.common.collect.Lists; +import com.intellij.openapi.util.TextRange; +import junit.framework.Test; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.JetLiteFixture; +import org.jetbrains.jet.JetTestCaseBase; +import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; +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.ImportingStrategy; + +import java.util.List; + +/** + * @author abreslav + */ +public class QuickJetPsiCheckerTest extends JetLiteFixture { + private String name; + + public QuickJetPsiCheckerTest(@NonNls String dataPath, String name) { + super(dataPath); + this.name = name; + } + + @Override + public String getName() { + return "test" + name; + } + + @Override + public void runTest() throws Exception { + String expectedText = loadFile(name + ".jet"); + List<CheckerTestUtil.DiagnosedRange> diagnosedRanges = Lists.newArrayList(); + String clearText = CheckerTestUtil.parseDiagnosedRanges(expectedText, diagnosedRanges); + + createAndCheckPsiFile(name, clearText); + JetFile jetFile = (JetFile) myFile; + BindingContext bindingContext = AnalyzingUtils.getInstance(ImportingStrategy.NONE).analyzeFileWithCache(jetFile); + + CheckerTestUtil.diagnosticsDiff(diagnosedRanges, bindingContext.getDiagnostics(), new CheckerTestUtil.DiagnosticDiffCallbacks() { + @Override + public void missingDiagnostic(String type, int expectedStart, int expectedEnd) { + String message = "Missing " + type + DiagnosticUtils.atLocation(myFile, new TextRange(expectedStart, expectedEnd)); + System.err.println(message); + } + + @Override + public void unexpectedDiagnostic(String type, int actualStart, int actualEnd) { + String message = "Unexpected " + type + DiagnosticUtils.atLocation(myFile, new TextRange(actualStart, actualEnd)); + System.err.println(message); + } + }); + + String actualText = CheckerTestUtil.addDiagnosticMarkersToText(jetFile, bindingContext).toString(); + + assertEquals(expectedText, actualText); + +// convert(new File(myFullDataPath + "/../../checker/"), new File(myFullDataPath)); + } + +// private void convert(File src, File dest) throws IOException { +// File[] files = src.listFiles(); +// for (File file : files) { +// try { +// if (file.isDirectory()) { +// File destDir = new File(dest, file.getName()); +// destDir.mkdir(); +// convert(file, destDir); +// continue; +// } +// if (!file.getName().endsWith(".jet")) continue; +// String text = doLoadFile(file.getParentFile().getAbsolutePath(), file.getName()); +// Pattern pattern = Pattern.compile("</?(error|warning)>"); +// String clearText = pattern.matcher(text).replaceAll(""); +// createAndCheckPsiFile(name, clearText); +// +// BindingContext bindingContext = AnalyzingUtils.getInstance(ImportingStrategy.NONE).analyzeFileWithCache((JetFile) myFile); +// String expectedText = CheckerTestUtil.addDiagnosticMarkersToText(myFile, bindingContext).toString(); +// +// File destFile = new File(dest, file.getName()); +// FileWriter fileWriter = new FileWriter(destFile); +// fileWriter.write(expectedText); +// fileWriter.close(); +// } +// catch (RuntimeException e) { +// e.printStackTrace(); +// } +// } +// } + + public static Test suite() { + return JetTestCaseBase.suiteForDirectory(JetTestCaseBase.getTestDataPathBase(), "/checkerWithErrorTypes/quick", true, new JetTestCaseBase.NamedTestFactory() { + @NotNull + @Override + public Test createTest(@NotNull String dataPath, @NotNull String name) { + return new QuickJetPsiCheckerTest(dataPath, name); + } + }); + } +} diff --git a/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java b/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java index c5b220f1309..d3678955b79 100644 --- a/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java +++ b/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java @@ -143,42 +143,6 @@ public class JetResolveTest extends ExtensibleResolveTestCase { doTest(path, true, false); } -// public void testBasic() throws Exception { -// doTest("/resolve/Basic.jet", true, true); -// } -// -// public void testResolveToJava() throws Exception { -// doTest("/resolve/ResolveToJava.jet", true, true); -// } -// -// public void testResolveOfInfixExpressions() throws Exception { -// doTest("/resolve/ResolveOfInfixExpressions.jet", true, true); -// } -// -// public void testProjections() throws Exception { -// doTest("/resolve/Projections.jet", true, true); -// } -// -// public void testPrimaryConstructors() throws Exception { -// doTest("/resolve/PrimaryConstructors.jet", true, true); -// } -// -// public void testClassifiers() throws Exception { -// doTest("/resolve/Classifiers.jet", true, true); -// } -// -// public void testConstructorsAndInitializers() throws Exception { -// doTest("/resolve/ConstructorsAndInitializers.jet", true, true); -// } -// -// public void testNamespaces() throws Exception { -// doTest("/resolve/Namespaces.jet", true, true); -// } -// -// public void testTryCatch() throws Exception { -// doTest("/resolve/TryCatch.jet", true, true); -// } - public static Test suite() { return JetTestCaseBase.suiteForDirectory(getHomeDirectory() + "/idea/testData/", "/resolve/", true, new JetTestCaseBase.NamedTestFactory() { @NotNull diff --git a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java index 2b2cee7886a..078051a6a6f 100644 --- a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java +++ b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java @@ -13,11 +13,13 @@ import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.diagnostics.DiagnosticHolder; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.java.JavaPackageScope; import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices; +import org.jetbrains.jet.lang.resolve.scopes.*; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ExplicitReceiver; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.parsing.JetParsingTest; @@ -507,8 +509,8 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase { JetScope scope = new JetScopeAdapter(classDefinitions.BASIC_SCOPE) { @NotNull @Override - public JetType getThisType() { - return thisType; + public ReceiverDescriptor getImplicitReceiver() { + return new ExplicitReceiver(thisType); } }; assertType(scope, expression, expectedType); @@ -527,7 +529,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase { } private WritableScopeImpl addImports(JetScope scope) { - WritableScopeImpl writableScope = new WritableScopeImpl(scope, scope.getContainingDeclaration(), DiagnosticHolder.DO_NOTHING); + WritableScopeImpl writableScope = new WritableScopeImpl(scope, scope.getContainingDeclaration(), RedeclarationHandler.DO_NOTHING); writableScope.importScope(library.getLibraryScope()); JavaSemanticServices javaSemanticServices = new JavaSemanticServices(getProject(), semanticServices, JetTestUtils.DUMMY_TRACE); writableScope.importScope(new JavaPackageScope("", null, javaSemanticServices)); @@ -637,7 +639,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase { trace.record(BindingContext.CLASS, classElement, classDescriptor); - final WritableScope parameterScope = new WritableScopeImpl(scope, classDescriptor, trace); + final WritableScope parameterScope = new WritableScopeImpl(scope, classDescriptor, new TraceBasedRedeclarationHandler(trace)); // This call has side-effects on the parameterScope (fills it in) List<TypeParameterDescriptor> typeParameters @@ -656,7 +658,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase { // } boolean open = classElement.hasModifier(JetTokens.OPEN_KEYWORD); - final WritableScope memberDeclarations = new WritableScopeImpl(JetScope.EMPTY, classDescriptor, trace); + final WritableScope memberDeclarations = new WritableScopeImpl(JetScope.EMPTY, classDescriptor, new TraceBasedRedeclarationHandler(trace)); List<JetDeclaration> declarations = classElement.getDeclarations(); for (JetDeclaration declaration : declarations) { diff --git a/stdlib/src/jet/typeinfo/JetSignature.java b/stdlib/src/jet/typeinfo/JetSignature.java new file mode 100644 index 00000000000..ab2455903c2 --- /dev/null +++ b/stdlib/src/jet/typeinfo/JetSignature.java @@ -0,0 +1,15 @@ +package jet.typeinfo; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.TypeVariable; +import java.util.*; + +/** + * @author alex.tkachman + */ +@Retention(RetentionPolicy.RUNTIME) +@interface JetSignature { + String value(); + +} diff --git a/stdlib/src/jet/typeinfo/TypeInfo.java b/stdlib/src/jet/typeinfo/TypeInfo.java index cd97f0f8547..08c9df501b2 100644 --- a/stdlib/src/jet/typeinfo/TypeInfo.java +++ b/stdlib/src/jet/typeinfo/TypeInfo.java @@ -4,7 +4,9 @@ import jet.JetObject; import jet.Tuple0; import java.lang.reflect.Field; -import java.util.Arrays; +import java.lang.reflect.TypeVariable; +import java.util.*; +import java.util.concurrent.locks.ReentrantReadWriteLock; /** * @author abreslav @@ -12,6 +14,8 @@ import java.util.Arrays; * @author alex.tkachman */ public abstract class TypeInfo<T> implements JetObject { + private final static TypeInfoProjection[] EMPTY = new TypeInfoProjection[0]; + public static final TypeInfo<Byte> BYTE_TYPE_INFO = getTypeInfo(Byte.class, false); public static final TypeInfo<Short> SHORT_TYPE_INFO = getTypeInfo(Short.class, false); public static final TypeInfo<Integer> INT_TYPE_INFO = getTypeInfo(Integer.class, false); @@ -35,20 +39,20 @@ public abstract class TypeInfo<T> implements JetObject { public static final TypeInfo<Tuple0> NULLABLE_TUPLE0_TYPE_INFO = getTypeInfo(Tuple0.class, true); private TypeInfo<?> typeInfo; - private final Class<T> theClass; + private final Signature signature; private final boolean nullable; private final TypeInfoProjection[] projections; private TypeInfo(Class<T> theClass, boolean nullable) { - this.theClass = theClass; - this.nullable = nullable; - this.projections = null; + this(theClass, nullable, EMPTY); } private TypeInfo(Class<T> theClass, boolean nullable, TypeInfoProjection[] projections) { - this.theClass = theClass; + this.signature = Parser.parse(theClass); this.nullable = nullable; this.projections = projections; + if(signature.variables.size() != projections.length) + throw new IllegalStateException("Wrong signature " + theClass.getName()); } public static <T> TypeInfoProjection invariantProjection(final TypeInfo<T> typeInfo) { @@ -85,7 +89,7 @@ public abstract class TypeInfo<T> implements JetObject { public final Object getClassObject() { try { - final Class implClass = theClass.getClassLoader().loadClass(theClass.getCanonicalName()); + final Class implClass = signature.klazz.getClassLoader().loadClass(signature.klazz.getCanonicalName()); final Field classobj = implClass.getField("$classobj"); return classobj.get(null); } catch (Exception e) { @@ -100,25 +104,23 @@ public abstract class TypeInfo<T> implements JetObject { return ((JetObject) obj).getTypeInfo().isSubtypeOf(this); } - return theClass.isAssignableFrom(obj.getClass()); // TODO + return signature.klazz.isAssignableFrom(obj.getClass()); // TODO } public final boolean isSubtypeOf(TypeInfo<?> superType) { if (nullable && !superType.nullable) { return false; } - if (!superType.theClass.isAssignableFrom(theClass)) { + if (!superType.signature.klazz.isAssignableFrom(signature.klazz)) { return false; } - if (projections != null) { - if (superType.projections == null || superType.projections.length != projections.length) { - throw new IllegalArgumentException("inconsistent type infos for the same class"); - } - for (int i = 0; i < projections.length; i++) { - // TODO handle variance here - if (!projections[i].equals(superType.projections[i])) { - return false; - } + if (superType.projections == null || superType.projections.length != projections.length) { + throw new IllegalArgumentException("inconsistent type infos for the same class"); + } + for (int i = 0; i < projections.length; i++) { + // TODO handle variance here + if (!projections[i].equals(superType.projections[i])) { + return false; } } return true; @@ -148,7 +150,7 @@ public abstract class TypeInfo<T> implements JetObject { TypeInfo typeInfo = (TypeInfo) o; - if (!theClass.equals(typeInfo.theClass)) return false; + if (!signature.klazz.equals(typeInfo.signature.klazz)) return false; if (nullable != typeInfo.nullable) return false; if (!Arrays.equals(projections, typeInfo.projections)) return false; @@ -157,13 +159,13 @@ public abstract class TypeInfo<T> implements JetObject { @Override public final int hashCode() { - return 31 * theClass.hashCode() + (projections != null ? Arrays.hashCode(projections) : 0); + return 31 * signature.klazz.hashCode() + Arrays.hashCode(projections); } @Override public final String toString() { - StringBuilder sb = new StringBuilder().append(theClass.getName()); - if (projections != null && projections.length != 0) { + StringBuilder sb = new StringBuilder().append(signature.klazz.getName()); + if (projections.length != 0) { sb.append("<"); for (int i = 0; i != projections.length - 1; ++i) { sb.append(projections[i].toString()).append(","); @@ -196,4 +198,261 @@ public abstract class TypeInfo<T> implements JetObject { return this; } } + + public static class Signature { + final Class klazz; + final List<Var> variables; + final List<Type> superTypes; + + final HashMap<Class,Signature> superSignatures = new HashMap<Class,Signature>(); + + public Signature(Class klazz, List<Var> variables, List<Type> superTypes) { + this.klazz = klazz; + this.superTypes = superTypes; + this.variables = variables; + + for(Type superType : superTypes) { + if(superType instanceof TypeReal) { + TypeReal type = (TypeReal) superType; + Signature parse = Parser.parse(type.klazz); + superSignatures.put(type.klazz, parse); + for(Map.Entry<Class,Signature> entry : parse.superSignatures.entrySet()) { + superSignatures.put(entry.getKey(), entry.getValue()); + } + } + } + } + } + + public static class Var { + final String name; + final TypeInfoVariance variance; + + public Var(String name, TypeInfoVariance variance) { + this.name = name; + this.variance = variance; + } + } + + public abstract static class Type{ + final boolean nullable; + + protected Type(boolean nullable) { + this.nullable = nullable; + } + } + + public static class TypeVar extends Type { + final int varIndex; + + public TypeVar(boolean nullable, int varIndex) { + super(nullable); + this.varIndex = varIndex; + } + } + + public static class TypeProj { + public final TypeInfoVariance variance; + public final Type type; + + public TypeProj(TypeInfoVariance variance, Type type) { + this.variance = variance; + this.type = type; + } + } + + public static class TypeReal extends Type { + public final Class klazz; + public final List<TypeProj> params; + + public TypeReal(Class klazz, boolean nullable, List<TypeProj> params) { + super(nullable); + this.params = params; + this.klazz = klazz; + } + } + + public static class Parser { + static final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + static final WeakHashMap<Class,Signature> map = new WeakHashMap<Class,Signature>(); + + int cur; + final char [] string; + + Map<String,Integer> variables; + + final ClassLoader classLoader; + + Parser(String string, ClassLoader classLoader) { + this.classLoader = classLoader; + this.string = string.toCharArray(); + } + + public static Signature parse(Class klass) { + lock.readLock().lock(); + Signature sig = map.get(klass); + lock.readLock().unlock(); + if (sig == null) { + lock.writeLock().lock(); + + sig = map.get(klass); + if (sig == null) { + sig = internalParse(klass); + map.put(klass, sig); + } + + lock.writeLock().unlock(); + } + return sig; + } + + private static Signature internalParse(Class klass) { + JetSignature annotation = (JetSignature) klass.getAnnotation(JetSignature.class); + if(annotation != null) { + String value = annotation.value(); + if(value != null) { + Parser parser = new Parser(value, klass.getClassLoader()); + return new Signature(klass, parser.parseVars(), parser.parseTypes()); + } + } + return getGenericSignature(klass); + } + + private static Signature getGenericSignature(Class klass) { + // todo complete impl + + TypeVariable[] typeParameters = klass.getTypeParameters(); + Map<String,Integer> variables; + List<Var> vars; + if(typeParameters == null || typeParameters.length == 0) { + variables = Collections.emptyMap(); + vars = Collections.emptyList(); + } + else { + variables = new HashMap<String, Integer>(); + vars = new LinkedList<Var>(); + for (int i = 0; i < typeParameters.length; i++) { + TypeVariable typeParameter = typeParameters[i]; + variables.put(typeParameter.getName(), i); + vars.add(new Var(typeParameter.getName(), TypeInfoVariance.INVARIANT)); + } + } + + List<Type> types = new LinkedList<Type>(); + java.lang.reflect.Type genericSuperclass = klass.getGenericSuperclass(); + return new Signature(klass, vars, types); + } + + public List<Var> parseVars() { + List<Var> list = null; + while(cur != string.length && string[cur] == 'T') { + if(list == null) + list = new LinkedList<Var>(); + list.add(parseVar()); + } + List<Var> vars = list == null ? Collections.<Var>emptyList() : list; + if(vars.isEmpty()) + variables = Collections.emptyMap(); + else { + variables = new HashMap<String, Integer>(); + for(int i=0; i != list.size(); ++i) { + variables.put(list.get(i).name, i); + } + } + return vars; + } + + private Var parseVar() { + TypeInfoVariance variance = parseVariance(); + String name = parseName(); + return new Var(name, variance); + } + + private String parseName() { + int c = ++cur; // skip 'T' + while (string[c] != ';') { + c++; + } + String name = new String(string, cur, c - cur); + cur = c+1; + return name; + } + + private TypeInfoVariance parseVariance() { + if(string[cur] == 'i' && string[cur+1] == 'n' && string[cur+2] == ' ' ) { + cur += 3; + return TypeInfoVariance.IN_VARIANCE; + } + else if (string[cur] == 'o' && string[cur+1] == 'u' && string[cur+2] == 't' && string[cur+2] == ' ') { + cur += 4; + return TypeInfoVariance.OUT_VARIANCE; + } + else { + return TypeInfoVariance.INVARIANT; + } + } + + public List<Type> parseTypes() { + List<Type> types = null; + while(cur != string.length) { + if(types == null) { + types = new LinkedList<Type>(); + } + types.add(parseType()); + } + return types == null ? Collections.<Type>emptyList() : types; + } + + private Type parseType() { + switch (string[cur]) { + case 'L': + String name = parseName(); + Class<?> aClass; + try { + aClass = classLoader.loadClass(name.replace('/','.')); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + List<TypeProj> proj = null; + boolean nullable = false; + if(cur != string.length && string[cur] == '<') { + cur++; + while(string[cur] != '>') { + if(proj == null) + proj = new LinkedList<TypeProj>(); + proj.add(parseProjection()); + } + cur++; + } + if(cur != string.length && string[cur] == '?') { + cur++; + nullable = true; + } + return new TypeReal(aClass, nullable, proj == null ? Collections.<TypeProj>emptyList() : proj); + + case 'T': + return parseTypeVar(); + + default: + throw new IllegalStateException(new String(string)); + } + } + + private Type parseTypeVar() { + String name = parseName(); + boolean nullable = false; + if(string[cur] == '?') { + nullable = true; + cur++; + } + + return new TypeVar(nullable, variables.get(name)); + } + + private TypeProj parseProjection() { + TypeInfoVariance variance = parseVariance(); + Type type = parseType(); + return new TypeProj(variance, type); + } + } } diff --git a/stdlib/src/jet/typeinfo/TypeInfoPattern.java b/stdlib/src/jet/typeinfo/TypeInfoPattern.java new file mode 100644 index 00000000000..eff0ae819cc --- /dev/null +++ b/stdlib/src/jet/typeinfo/TypeInfoPattern.java @@ -0,0 +1,100 @@ +package jet.typeinfo; + +/** + * This class represents how type info of super class should be matched against type parameters of subclass. + * + * For each subclass we create such pattern for subclass itself and all it super classes either during + * static initialization(or maybe when needed). + * + * For each instance of parametrized type we keep it type info, which can be understood as binding of type parameter variables. + * + * @author alex.tkachman + */ +public interface TypeInfoPattern { + TypeInfo substitute(TypeInfo[] variables); + + class Var implements TypeInfoPattern { + public final int index; + + public Var(int index) { + this.index = index; + } + + @Override + public TypeInfo substitute(TypeInfo[] variables) { + return variables[index]; + } + } + + class Const implements TypeInfoPattern { + private final TypeInfo typeInfo; + + public Const(TypeInfo typeInfo) { + this.typeInfo = typeInfo; + } + + @Override + public TypeInfo substitute(TypeInfo[] variables) { + return typeInfo; + } + } + + class Pattern implements TypeInfoPattern { + public static final TypeInfoPatternProjection[] EMPTY = new TypeInfoPatternProjection[0]; + public final Class klazz; + public final boolean nullable; + public final TypeInfoPatternProjection [] patterns; + + public Pattern(Class klazz, boolean nullable, TypeInfoPatternProjection[] patterns) { + this.klazz = klazz; + this.nullable = nullable; + this.patterns = patterns; + } + + public Pattern(Class klazz, boolean nullable) { + this.klazz = klazz; + this.nullable = nullable; + this.patterns = EMPTY; + } + + @Override + public TypeInfo substitute(TypeInfo[] variables) { + return TypeInfo.getTypeInfo(klazz, nullable, TypeInfoPatternProjection.substitute(patterns, variables)); + } + } + + class TypeInfoPatternProjection { + public final TypeInfoVariance variance; + + public final TypeInfoPattern pattern; + + public TypeInfoPatternProjection(TypeInfoVariance variance, TypeInfoPattern pattern) { + this.variance = variance; + this.pattern = pattern; + } + + public TypeInfoProjection substitute(final TypeInfo[] variables) { + return new TypeInfoProjection() { + @Override + public TypeInfoVariance getVariance() { + return variance; + } + + @Override + public TypeInfo getType() { + return pattern.substitute(variables); + } + }; + } + + public static TypeInfoProjection[] substitute(TypeInfoPatternProjection[] patterns, TypeInfo[] variables) { + if(patterns.length == 0) + return TypeInfoProjection.EMPTY_ARRAY; + TypeInfoProjection [] projections = new TypeInfoProjection[patterns.length]; + for (int i = 0; i < projections.length; i++) { + projections[i] = patterns[i].substitute(variables); + } + return projections; + } + } +} diff --git a/stdlib/src/jet/typeinfo/TypeInfoProjection.java b/stdlib/src/jet/typeinfo/TypeInfoProjection.java index ad2553d6085..09d5fdc264c 100644 --- a/stdlib/src/jet/typeinfo/TypeInfoProjection.java +++ b/stdlib/src/jet/typeinfo/TypeInfoProjection.java @@ -4,6 +4,8 @@ package jet.typeinfo; * @author alex.tkachman */ public interface TypeInfoProjection { + TypeInfoProjection[] EMPTY_ARRAY = new TypeInfoProjection[0]; + TypeInfoVariance getVariance(); TypeInfo getType();