diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CompilationException.java b/compiler/backend/src/org/jetbrains/jet/codegen/CompilationException.java index f890d94c0ff..017b499e327 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CompilationException.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CompilationException.java @@ -62,11 +62,13 @@ public class CompilationException extends RuntimeException { private String where() { Throwable cause = getCause(); - if (cause != null && cause.getStackTrace().length > 0) { - return cause.getStackTrace()[0].getFileName() + ":" + cause.getStackTrace()[0].getLineNumber(); + Throwable throwable = cause != null ? cause : this; + StackTraceElement[] stackTrace = throwable.getStackTrace(); + if (stackTrace != null && stackTrace.length > 0) { + return stackTrace[0].getFileName() + ":" + stackTrace[0].getLineNumber(); } else { - return "far away in cyberspace"; + return "unknown"; } } diff --git a/compiler/cli/src/org/jetbrains/jet/compiler/KotlinToJVMBytecodeCompiler.java b/compiler/cli/src/org/jetbrains/jet/compiler/KotlinToJVMBytecodeCompiler.java index 51557493b91..ecc239820ad 100644 --- a/compiler/cli/src/org/jetbrains/jet/compiler/KotlinToJVMBytecodeCompiler.java +++ b/compiler/cli/src/org/jetbrains/jet/compiler/KotlinToJVMBytecodeCompiler.java @@ -71,6 +71,8 @@ public class KotlinToJVMBytecodeCompiler { return null; } + exhaust.throwIfError(); + return generate(environment, dependencies, messageCollector, exhaust, stubs); } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacadeForJVM.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacadeForJVM.java index 8b07dbc02a6..05fef231d78 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacadeForJVM.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/AnalyzerFacadeForJVM.java @@ -96,7 +96,8 @@ public enum AnalyzerFacadeForJVM implements AnalyzerFacade { injector.getTopDownAnalyzer().analyzeFiles(files); - return new AnalyzeExhaust(bindingTraceContext.getBindingContext(), JetStandardLibrary.getInstance()); + + return AnalyzeExhaust.success(bindingTraceContext.getBindingContext(), JetStandardLibrary.getInstance()); } public static AnalyzeExhaust shallowAnalyzeFiles(Collection files, diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index b225cf81b40..9f8015a8b06 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -76,6 +76,7 @@ import org.jetbrains.jet.lang.psi.JetPsiUtil; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.BindingTraceContext; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.FqName; import org.jetbrains.jet.lang.resolve.NamespaceFactory; @@ -92,6 +93,7 @@ import org.jetbrains.jet.lang.resolve.constants.NullValue; import org.jetbrains.jet.lang.resolve.constants.ShortValue; import org.jetbrains.jet.lang.resolve.constants.StringValue; import org.jetbrains.jet.lang.resolve.java.kt.JetClassAnnotation; +import org.jetbrains.jet.lang.types.DeferredType; import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeSubstitutor; @@ -103,6 +105,7 @@ import org.jetbrains.jet.rt.signature.JetSignatureAdapter; import org.jetbrains.jet.rt.signature.JetSignatureExceptionsAdapter; import org.jetbrains.jet.rt.signature.JetSignatureReader; import org.jetbrains.jet.rt.signature.JetSignatureVisitor; +import org.jetbrains.jet.util.lazy.LazyValue; import javax.inject.Inject; import java.util.ArrayList; @@ -330,7 +333,15 @@ public class JavaDescriptorResolver { @Nullable public ClassDescriptor resolveClass(@NotNull FqName qualifiedName, @NotNull DescriptorSearchRule searchRule) { + List tasks = Lists.newArrayList(); + ClassDescriptor clazz = resolveClass(qualifiedName, searchRule, tasks); + for (Runnable task : tasks) { + task.run(); + } + return clazz; + } + private ClassDescriptor resolveClass(@NotNull FqName qualifiedName, @NotNull DescriptorSearchRule searchRule, @NotNull List tasks) { if (qualifiedName.getFqName().endsWith(JvmAbi.TRAIT_IMPL_SUFFIX)) { // TODO: only if -$$TImpl class is created by Kotlin return null; @@ -365,12 +376,12 @@ public class JavaDescriptorResolver { if (psiClass == null) { return null; } - classData = createJavaClassDescriptor(psiClass); + classData = createJavaClassDescriptor(psiClass, tasks); } return classData.getClassDescriptor(); } - private ResolverBinaryClassData createJavaClassDescriptor(@NotNull final PsiClass psiClass) { + private ResolverBinaryClassData createJavaClassDescriptor(@NotNull final PsiClass psiClass, List taskList) { FqName fqName = new FqName(psiClass.getQualifiedName()); if (classDescriptorCache.containsKey(fqName)) { throw new IllegalStateException(psiClass.getQualifiedName()); @@ -384,7 +395,7 @@ public class JavaDescriptorResolver { ResolverBinaryClassData classData = new ResolverBinaryClassData(psiClass, fqName, new MutableClassDescriptorLite(containingDeclaration, kind)); classDescriptorCache.put(fqName, classData); classData.classDescriptor.setName(name); - classData.classDescriptor.setAnnotations(resolveAnnotations(psiClass)); + classData.classDescriptor.setAnnotations(resolveAnnotations(psiClass, taskList)); List supertypes = new ArrayList(); @@ -1596,11 +1607,11 @@ public class JavaDescriptorResolver { return (FunctionDescriptorImpl) substitutedFunctionDescriptor; } - private List resolveAnnotations(PsiModifierListOwner owner) { + private List resolveAnnotations(PsiModifierListOwner owner, @NotNull List tasks) { PsiAnnotation[] psiAnnotations = owner.getModifierList().getAnnotations(); List r = Lists.newArrayListWithCapacity(psiAnnotations.length); for (PsiAnnotation psiAnnotation : psiAnnotations) { - AnnotationDescriptor annotation = resolveAnnotation(psiAnnotation); + AnnotationDescriptor annotation = resolveAnnotation(psiAnnotation, tasks); if (annotation != null) { r.add(annotation); } @@ -1608,9 +1619,18 @@ public class JavaDescriptorResolver { return r; } + private List resolveAnnotations(PsiModifierListOwner owner) { + List tasks = Lists.newArrayList(); + List annotations = resolveAnnotations(owner, tasks); + for (Runnable task : tasks) { + task.run(); + } + return annotations; + } + @Nullable - private AnnotationDescriptor resolveAnnotation(PsiAnnotation psiAnnotation) { - AnnotationDescriptor annotation = new AnnotationDescriptor(); + private AnnotationDescriptor resolveAnnotation(PsiAnnotation psiAnnotation, @NotNull List taskList) { + final AnnotationDescriptor annotation = new AnnotationDescriptor(); String qname = psiAnnotation.getQualifiedName(); if (qname.startsWith("java.lang.annotation.") || qname.startsWith("jet.runtime.typeinfo.") || qname.equals(JvmAbi.JETBRAINS_NOT_NULL_ANNOTATION.getFqName().getFqName())) { @@ -1618,11 +1638,16 @@ public class JavaDescriptorResolver { return null; } - ClassDescriptor clazz = resolveClass(new FqName(psiAnnotation.getQualifiedName()), DescriptorSearchRule.INCLUDE_KOTLIN); + final ClassDescriptor clazz = resolveClass(new FqName(psiAnnotation.getQualifiedName()), DescriptorSearchRule.INCLUDE_KOTLIN, taskList); if (clazz == null) { return null; } - annotation.setAnnotationType(clazz.getDefaultType()); + taskList.add(new Runnable() { + @Override + public void run() { + annotation.setAnnotationType(clazz.getDefaultType()); + } + }); ArrayList> valueArguments = new ArrayList>(); PsiAnnotationParameterList parameterList = psiAnnotation.getParameterList(); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java index 96a3f99304e..d005ef30040 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java @@ -162,7 +162,9 @@ public class JavaTypeTransformer { PsiType[] psiArguments = classType.getParameters(); if (parameters.size() != psiArguments.length) { - throw new IllegalStateException(); + throw new IllegalStateException( + "parameters = " + parameters.size() + ", actual arguments = " + psiArguments.length + + " in " + classType.getPresentableText()); } for (int i = 0; i < parameters.size(); i++) { diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiClassFinderForJvm.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiClassFinderForJvm.java index 07040b7be22..93d038f2f64 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiClassFinderForJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiClassFinderForJvm.java @@ -87,7 +87,7 @@ public class PsiClassFinderForJvm implements PsiClassFinder { if (result != null) { FqName actualQualifiedName = new FqName(result.getQualifiedName()); if (!actualQualifiedName.equals(qualifiedName)) { -// throw new IllegalStateException("requested " + qualifiedName + ", got " + actualQualifiedName); + throw new IllegalStateException("requested " + qualifiedName + ", got " + actualQualifiedName); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/analyzer/AnalyzeExhaust.java b/compiler/frontend/src/org/jetbrains/jet/analyzer/AnalyzeExhaust.java index 3a2a9af1ef9..4c2950bfb42 100644 --- a/compiler/frontend/src/org/jetbrains/jet/analyzer/AnalyzeExhaust.java +++ b/compiler/frontend/src/org/jetbrains/jet/analyzer/AnalyzeExhaust.java @@ -27,12 +27,22 @@ import org.jetbrains.jet.lang.types.lang.JetStandardLibrary; public class AnalyzeExhaust { @NotNull private final BindingContext bindingContext; - @Nullable private final JetStandardLibrary standardLibrary; + private final Throwable error; - public AnalyzeExhaust(@NotNull BindingContext bindingContext, @Nullable JetStandardLibrary standardLibrary) { + private AnalyzeExhaust(@NotNull BindingContext bindingContext, + @Nullable JetStandardLibrary standardLibrary, @Nullable Throwable error) { this.bindingContext = bindingContext; this.standardLibrary = standardLibrary; + this.error = error; + } + + public static AnalyzeExhaust success(@NotNull BindingContext bindingContext, @NotNull JetStandardLibrary standardLibrary) { + return new AnalyzeExhaust(bindingContext, standardLibrary, null); + } + + public static AnalyzeExhaust error(@NotNull BindingContext bindingContext, @NotNull Throwable error) { + return new AnalyzeExhaust(bindingContext, null, error); } @NotNull @@ -40,8 +50,23 @@ public class AnalyzeExhaust { return bindingContext; } - @Nullable + @NotNull public JetStandardLibrary getStandardLibrary() { return standardLibrary; } + + @NotNull + public Throwable getError() { + return error; + } + + public boolean isError() { + return error != null; + } + + public void throwIfError() { + if (isError()) { + throw new IllegalStateException("failed to analyze: " + error, error); + } + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/annotations/AnnotationDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/annotations/AnnotationDescriptor.java index be09c9892c4..53c807cc18c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/annotations/AnnotationDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/annotations/AnnotationDescriptor.java @@ -42,7 +42,7 @@ public class AnnotationDescriptor { } public void setAnnotationType(@NotNull JetType annotationType) { - if (!(annotationType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor)) { + if (false && !(annotationType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor)) { throw new IllegalStateException(); } this.annotationType = annotationType; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java index 42028fc4d2c..d2e374196ed 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -156,11 +156,12 @@ public interface Errors { DiagnosticFactory BY_IN_SECONDARY_CONSTRUCTOR = DiagnosticFactory.create(ERROR, "'by'-clause is only supported for primary constructors"); DiagnosticFactory INITIALIZER_WITH_NO_ARGUMENTS = DiagnosticFactory.create(ERROR, "Constructor arguments required"); DiagnosticFactory MANY_CALLS_TO_THIS = DiagnosticFactory.create(ERROR, "Only one call to 'this(...)' is allowed"); - DiagnosticFactory1 NOTHING_TO_OVERRIDE = DiagnosticFactory1.create(ERROR, "{0} overrides nothing", PositioningStrategies.positionModifier(JetTokens.OVERRIDE_KEYWORD), DescriptorRenderer.TEXT); + DiagnosticFactory1 NOTHING_TO_OVERRIDE = DiagnosticFactory1.create(ERROR, "{0} overrides nothing", PositioningStrategies.POSITION_OVERRIDE_MODIFIER, DescriptorRenderer.TEXT); DiagnosticFactory3 VIRTUAL_MEMBER_HIDDEN = DiagnosticFactory3.create(ERROR, "''{0}'' hides ''{1}'' in class {2} and needs 'override' modifier", PositioningStrategies.POSITION_NAME_IDENTIFIER, DescriptorRenderer.TEXT, DescriptorRenderer.TEXT, DescriptorRenderer.TEXT); DiagnosticFactory3 CANNOT_OVERRIDE_INVISIBLE_MEMBER = - DiagnosticFactory3.create(ERROR, "''{0}'' cannot has no access to ''{1}'' in class {2}, so it cannot override it", PositioningStrategies.positionModifier(JetTokens.OVERRIDE_KEYWORD), DescriptorRenderer.TEXT, DescriptorRenderer.TEXT, DescriptorRenderer.TEXT); + DiagnosticFactory3.create(ERROR, "''{0}'' cannot has no access to ''{1}'' in class {2}, so it cannot override it", PositioningStrategies.POSITION_OVERRIDE_MODIFIER, DescriptorRenderer.TEXT, DescriptorRenderer.TEXT, DescriptorRenderer.TEXT); + DiagnosticFactory CANNOT_INFER_VISIBILITY = DiagnosticFactory.create(ERROR, "Cannot infer visibility. Please specify it explicitly", PositioningStrategies.POSITION_OVERRIDE_MODIFIER); DiagnosticFactory1 ENUM_ENTRY_SHOULD_BE_INITIALIZED = DiagnosticFactory1.create(ERROR, "Missing delegation specifier ''{0}''", PositioningStrategies.POSITION_NAME_IDENTIFIER, NAME); DiagnosticFactory1 ENUM_ENTRY_ILLEGAL_TYPE = DiagnosticFactory1.create(ERROR, "The type constructor of enum entry should be ''{0}''", NAME); @@ -380,6 +381,8 @@ public interface Errors { } }, TO_STRING, TO_STRING); + DiagnosticFactory2 SENSELESS_COMPARISON = DiagnosticFactory2.create(WARNING, "Condition ''{0}'' is always ''{1}''", ELEMENT_TEXT, TO_STRING); + DiagnosticFactory2 OVERRIDING_FINAL_MEMBER = DiagnosticFactory2.create(ERROR, "''{0}'' in ''{1}'' is final and cannot be overridden", NAME, NAME); DiagnosticFactory3 CANNOT_WEAKEN_ACCESS_PRIVILEGE = DiagnosticFactory3.create(ERROR, "Cannot weaken access privilege ''{0}'' for ''{1}'' in ''{2}''", PositioningStrategies.POSITION_VISIBILITY_MODIFIER, TO_STRING, NAME, NAME); DiagnosticFactory3 CANNOT_CHANGE_ACCESS_PRIVILEGE = DiagnosticFactory3.create(ERROR, "Cannot change access privilege ''{0}'' for ''{1}'' in ''{2}''", PositioningStrategies.POSITION_VISIBILITY_MODIFIER, TO_STRING, NAME, NAME); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategies.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategies.java index 5cfdb034a23..96bf5fffeea 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategies.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategies.java @@ -88,6 +88,8 @@ public class PositioningStrategies { public static final PositioningStrategy POSITION_ABSTRACT_MODIFIER = positionModifier(JetTokens.ABSTRACT_KEYWORD); + public static final PositioningStrategy POSITION_OVERRIDE_MODIFIER = positionModifier(JetTokens.OVERRIDE_KEYWORD); + public static PositioningStrategy positionModifier(final JetKeywordToken token) { return new PositioningStrategy() { @NotNull 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 22263d12863..50eb3075b84 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java @@ -1128,27 +1128,20 @@ public class JetExpressionParsing extends AbstractJetParsing { // {(a, b) -> ...} { - PsiBuilder.Marker rollbackMarker = mark(); + boolean preferParamsToExpressions = isConfirmedParametersByComma(); + PsiBuilder.Marker rollbackMarker = mark(); parseFunctionLiteralParametersAndType(); - paramsFound = rollbackOrDropAt(rollbackMarker, ARROW); + paramsFound = preferParamsToExpressions ? + rollbackOrDrop(rollbackMarker, ARROW, "An -> is expected", RBRACE) : + rollbackOrDropAt(rollbackMarker, ARROW); } if (!paramsFound) { // If not found, try a typeRef DOT and then LPAR .. RPAR ARROW // {((A) -> B).(x) -> ... } - PsiBuilder.Marker rollbackMarker = mark(); - int lastDot = matchTokenStreamPredicate(new LastBefore(new At(DOT), new AtSet(ARROW, RPAR))); - if (lastDot >= 0) { - createTruncatedBuilder(lastDot).parseTypeRef(); - if (at(DOT)) { - advance(); // DOT - parseFunctionLiteralParametersAndType(); - } - } - - paramsFound = rollbackOrDropAt(rollbackMarker, ARROW); + paramsFound = parseFunctionTypeDotParametersAndType(); } } else { @@ -1157,69 +1150,21 @@ public class JetExpressionParsing extends AbstractJetParsing { // {a -> ...} // {a, b -> ...} PsiBuilder.Marker rollbackMarker = mark(); + boolean preferParamsToExpressions = (lookahead(1) == COMMA); parseFunctionLiteralShorthandParameterList(); parseOptionalFunctionLiteralType(); - paramsFound = rollbackOrDropAt(rollbackMarker, ARROW); + + paramsFound = preferParamsToExpressions ? + rollbackOrDrop(rollbackMarker, ARROW, "An -> is expected", RBRACE) : + rollbackOrDropAt(rollbackMarker, ARROW); } if (!paramsFound && atSet(JetParsing.TYPE_REF_FIRST)) { // Try to parse a type DOT valueParameterList ARROW // {A.(b) -> ...} - PsiBuilder.Marker rollbackMarker = mark(); - int lastDot = matchTokenStreamPredicate(new LastBefore(new At(DOT), new AtSet(ARROW, RBRACE))); - if (lastDot >= 0) { // There is a receiver type - createTruncatedBuilder(lastDot).parseTypeRef(); - } - - if (at(DOT)) { - advance(); // DOT - parseFunctionLiteralParametersAndType(); - paramsFound = rollbackOrDropAt(rollbackMarker, ARROW); - } - else { - rollbackMarker.rollbackTo(); - } + paramsFound = parseFunctionTypeDotParametersAndType(); } -// int doubleArrowPos = matchTokenStreamPredicate(new FirstBefore(new At(ARROW), new At(RBRACE)) { -// @Override -// public boolean isTopLevel(int openAngleBrackets, int openBrackets, int openBraces, int openParentheses) { -// return openBraces == 0; -// } -// }); -// -// boolean doubleArrowPresent = doubleArrowPos >= 0; -// if (doubleArrowPresent) { -// boolean dontExpectParameters = false; -// -// int lastDot = matchTokenStreamPredicate(new LastBefore(new At(DOT), new AtOffset(doubleArrowPos))); -// if (lastDot >= 0) { // There is a receiver type -// createTruncatedBuilder(lastDot).parseTypeRef(); -// -// expect(DOT, "Expecting '.'"); -// -// if (!at(LPAR)) { -// int firstLParPos = matchTokenStreamPredicate(new FirstBefore(new At(LPAR), new AtOffset(doubleArrowPos))); -// -// if (firstLParPos >= 0) { -// errorUntilOffset("Expecting '('", firstLParPos); -// } else { -// errorUntilOffset("To specify a receiver type, use the full notation: {ReceiverType.(parameters) [: ReturnType] -> ...}", -// doubleArrowPos); -// dontExpectParameters = true; -// } -// } -// -// } -// -// if (at(LPAR)) { -// parseFunctionLiteralParametersAndType(); -// } -// else if (!dontExpectParameters) { -// parseFunctionLiteralShorthandParameterList(); -// } -// -// expectNoAdvance(ARROW, "Expecting '->'"); -// } } + if (!paramsFound) { if (preferBlock) { literal.drop(); @@ -1231,6 +1176,7 @@ public class JetExpressionParsing extends AbstractJetParsing { return; } } + PsiBuilder.Marker body = mark(); parseStatements(); body.done(BLOCK); @@ -1252,6 +1198,25 @@ public class JetExpressionParsing extends AbstractJetParsing { return false; } + private boolean rollbackOrDrop(PsiBuilder.Marker rollbackMarker, + JetToken expected, String expectMessage, + IElementType validForDrop) { + if (at(expected)) { + advance(); // dropAt + rollbackMarker.drop(); + return true; + } + else if (at(validForDrop)) { + rollbackMarker.drop(); + expect(expected, expectMessage); + return true; + } + + rollbackMarker.rollbackTo(); + return false; + } + + /* * SimpleName{,} */ @@ -1289,9 +1254,45 @@ public class JetExpressionParsing extends AbstractJetParsing { parameterList.done(VALUE_PARAMETER_LIST); } + // Check that position is followed by top level comma. It can't be expression and we want it be + // parsed as parameters in function literal + private boolean isConfirmedParametersByComma() { + assert _at(LPAR); + PsiBuilder.Marker lparMarker = mark(); + advance(); // LPAR + int comma = matchTokenStreamPredicate(new FirstBefore(new At(COMMA), new AtSet(ARROW, RPAR))); + lparMarker.rollbackTo(); + return comma > 0; + } + + private boolean parseFunctionTypeDotParametersAndType() { + PsiBuilder.Marker rollbackMarker = mark(); + + // True when it's confirmed that body of literal can't be simple expressions and we prefer to parse + // it to function params if possible. + boolean preferParamsToExpressions = false; + + int lastDot = matchTokenStreamPredicate(new LastBefore(new At(DOT), new AtSet(ARROW, RPAR))); + if (lastDot >= 0) { + createTruncatedBuilder(lastDot).parseTypeRef(); + if (at(DOT)) { + advance(); // DOT + + if (at(LPAR)) { + preferParamsToExpressions = isConfirmedParametersByComma(); + } + + parseFunctionLiteralParametersAndType(); + } + } + + return preferParamsToExpressions ? + rollbackOrDrop(rollbackMarker, ARROW, "An -> is expected", RBRACE) : + rollbackOrDropAt(rollbackMarker, ARROW); + } + private void parseFunctionLiteralParametersAndType() { parseFunctionLiteralParameterList(); - parseOptionalFunctionLiteralType(); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/FqNameUnsafe.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/FqNameUnsafe.java index d4cbf26a420..dc9a8d30156 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/FqNameUnsafe.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/FqNameUnsafe.java @@ -230,8 +230,7 @@ public class FqNameUnsafe { if (isRoot()) { return false; } - List pathSegments = pathSegments(); - return pathSegments.get(pathSegments.size() - 1).equals(segment); + return shortName().equals(segment); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java index e971843d3e1..cb1e794bf8c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java @@ -36,6 +36,7 @@ import javax.inject.Inject; import java.util.*; import static org.jetbrains.jet.lang.diagnostics.Errors.*; +import static org.jetbrains.jet.lang.resolve.BindingContext.DECLARATION_TO_DESCRIPTOR; import static org.jetbrains.jet.lang.resolve.BindingContext.DELEGATED; /** @@ -418,10 +419,10 @@ public class OverrideResolver { private void resolveUnknownVisibilityForMembers(@NotNull Set fakeOverrides) { for (CallableMemberDescriptor override : fakeOverrides) { - resolveUnknownVisibilityForMember(override); + resolveUnknownVisibilityForMember(null, override); } - for (CallableMemberDescriptor memberDescriptor : context.getMembers().values()) { - resolveUnknownVisibilityForMember(memberDescriptor); + for (Map.Entry entry : context.getMembers().entrySet()) { + resolveUnknownVisibilityForMember(entry.getKey(), entry.getValue()); } for (PropertyDescriptor propertyDescriptor : context.getProperties().values()) { for (PropertyAccessorDescriptor accessor : propertyDescriptor.getAccessors()) { @@ -432,13 +433,19 @@ public class OverrideResolver { } } - private void resolveUnknownVisibilityForMember(@NotNull CallableMemberDescriptor memberDescriptor) { + private void resolveUnknownVisibilityForMember(@Nullable JetDeclaration member, @NotNull CallableMemberDescriptor memberDescriptor) { resolveUnknownVisibilityForOverriddenDescriptors(memberDescriptor.getOverriddenDescriptors()); if (memberDescriptor.getVisibility() != Visibilities.INHERITED) { return; } Visibility visibility = findMaxVisibility(memberDescriptor.getOverriddenDescriptors()); + if (visibility == null) { + if (member != null) { + trace.report(CANNOT_INFER_VISIBILITY.on(member)); + } + visibility = Visibilities.PUBLIC; + } if (memberDescriptor instanceof PropertyDescriptor) { ((PropertyDescriptor)memberDescriptor).setVisibility(visibility); @@ -465,12 +472,14 @@ public class OverrideResolver { private void resolveUnknownVisibilityForOverriddenDescriptors(@NotNull Collection descriptors) { for (CallableMemberDescriptor descriptor : descriptors) { if (descriptor.getVisibility() == Visibilities.INHERITED) { - resolveUnknownVisibilityForMember(descriptor); + PsiElement element = BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), descriptor); + JetDeclaration declaration = (element instanceof JetDeclaration) ? (JetDeclaration) element : null; + resolveUnknownVisibilityForMember(declaration, descriptor); } } } - @NotNull + @Nullable private Visibility findMaxVisibility(@NotNull Collection descriptors) { if (descriptors.isEmpty()) { return Visibilities.INTERNAL; @@ -483,16 +492,23 @@ public class OverrideResolver { maxVisibility = visibility; continue; } - Integer compare = Visibilities.compare(visibility, maxVisibility); - if (compare == null) { - maxVisibility = Visibilities.PUBLIC; //todo error or warning when inference only from incomparable visibilities - continue; + Integer compareResult = Visibilities.compare(visibility, maxVisibility); + if (compareResult == null) { + maxVisibility = null; } - if (compare > 0) { + else if (compareResult > 0) { maxVisibility = visibility; } } - assert maxVisibility != null; + if (maxVisibility == null) { + return null; + } + for (CallableMemberDescriptor descriptor : descriptors) { + Integer compareResult = Visibilities.compare(maxVisibility, descriptor.getVisibility()); + if (compareResult == null || compareResult < 0) { + return null; + } + } return maxVisibility; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java index 66059c490fe..bc932755159 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java @@ -950,9 +950,16 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { context.trace.report(EQUALITY_NOT_APPLICABLE.on(expression, operationSign, leftType, rightType)); } } + if (isSenselessComparisonWithNull(leftType, right) || isSenselessComparisonWithNull(rightType, left)) { + context.trace.report(SENSELESS_COMPARISON.on(expression, expression, operationSign.getReferencedNameElementType() == JetTokens.EXCLEQ)); + } } } + private boolean isSenselessComparisonWithNull(JetType firstType, JetExpression secondExpression) { + return !firstType.isNullable() && secondExpression instanceof JetConstantExpression && secondExpression.getNode().getElementType() == JetNodeTypes.NULL; + } + protected JetType visitAssignmentOperation(JetBinaryExpression expression, ExpressionTypingContext context) { return assignmentIsNotAnExpressionError(expression, context); } diff --git a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JetLightClass.java b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JetLightClass.java index 8a89bb36ab0..0108405be00 100644 --- a/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JetLightClass.java +++ b/compiler/jet.as.java.psi/src/org/jetbrains/jet/asJava/JetLightClass.java @@ -165,6 +165,10 @@ public class JetLightClass extends AbstractLightClass implements JetJavaMirrorMa // TODO: wrong environment // stepan.koltsov@ 2012-04-09 CompilerSpecialMode.REGULAR, CompilerDependencies.compilerDependenciesForProduction(CompilerSpecialMode.REGULAR)); + if (context.isError()) { + throw new IllegalStateException("failed to analyze: " + context.getError(), context.getError()); + } + final GenerationState state = new GenerationState(project, builderFactory, context, Collections.singletonList(file)) { @Override protected void generateNamespace(JetFile namespace) { diff --git a/compiler/testData/diagnostics/tests/nullabilityAndAutoCasts/kt1680.jet b/compiler/testData/diagnostics/tests/nullabilityAndAutoCasts/kt1680.jet new file mode 100644 index 00000000000..8b1a7a42ebc --- /dev/null +++ b/compiler/testData/diagnostics/tests/nullabilityAndAutoCasts/kt1680.jet @@ -0,0 +1,14 @@ +//KT-1680 Warn if non-null variable is compared to null +package kt1680 + +fun foo() { + val x = 1 + if (x != null) {} // <-- need a warning here! + if (x == null) {} + if (null != x) {} + if (null == x) {} + + val y : Int? = 1 + if (y != null) {} + if (y == null) {} +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/scopes/kt151.jet b/compiler/testData/diagnostics/tests/scopes/kt151.jet index 6387a2b3810..e50bbf6526d 100644 --- a/compiler/testData/diagnostics/tests/scopes/kt151.jet +++ b/compiler/testData/diagnostics/tests/scopes/kt151.jet @@ -36,5 +36,5 @@ class F : C(), T { } class G : C(), T { - override fun foo() {} + public override fun foo() {} } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/scopes/kt1822.jet b/compiler/testData/diagnostics/tests/scopes/kt1822.jet new file mode 100644 index 00000000000..77031e1edf5 --- /dev/null +++ b/compiler/testData/diagnostics/tests/scopes/kt1822.jet @@ -0,0 +1,30 @@ +//KT-1822 Error 'cannot infer visibility' required +package kt1822 + +open class C { + internal open fun foo() {} +} + +trait T { + protected fun foo() {} +} + +class G : C(), T { + override fun foo() {} //should be an error "cannot infer visibility"; for now 'public' is inferred in such cases +} + +open class A { + internal open fun foo() {} +} + +trait B { + protected fun foo() {} +} + +trait D { + public fun foo() {} +} + +class E : A(), B, D { + override fun foo() {} +} \ No newline at end of file diff --git a/compiler/testData/psi/FunctionLiterals_ERR.jet b/compiler/testData/psi/FunctionLiterals_ERR.jet index d275d6711a6..e3d82032282 100644 --- a/compiler/testData/psi/FunctionLiterals_ERR.jet +++ b/compiler/testData/psi/FunctionLiterals_ERR.jet @@ -15,4 +15,8 @@ fun foo() { {a : b -> f} {T.a : b -> f} + + {(a, b) } + {T.(a, b) } + {a, } } \ No newline at end of file diff --git a/compiler/testData/psi/FunctionLiterals_ERR.txt b/compiler/testData/psi/FunctionLiterals_ERR.txt index baa260581ae..3f4b7b3bb28 100644 --- a/compiler/testData/psi/FunctionLiterals_ERR.txt +++ b/compiler/testData/psi/FunctionLiterals_ERR.txt @@ -326,7 +326,66 @@ JetFile: FunctionLiterals_ERR.jet REFERENCE_EXPRESSION PsiElement(IDENTIFIER)('f') PsiElement(RBRACE)('}') - PsiWhiteSpace('\n') - PsiElement(RBRACE)('}') - PsiErrorElement:Expecting '}' - \ No newline at end of file + PsiWhiteSpace('\n\n ') + FUNCTION_LITERAL_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('a') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiErrorElement:An -> is expected + + PsiWhiteSpace(' ') + BLOCK + + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + FUNCTION_LITERAL_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('T') + PsiElement(DOT)('.') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('a') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('b') + PsiElement(RPAR)(')') + PsiErrorElement:An -> is expected + + PsiWhiteSpace(' ') + BLOCK + + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + FUNCTION_LITERAL_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + VALUE_PARAMETER_LIST + VALUE_PARAMETER + PsiElement(IDENTIFIER)('a') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + VALUE_PARAMETER + PsiErrorElement:Expecting parameter name + PsiElement(RBRACE)('}') + PsiErrorElement:Expecting '->' or ',' + + PsiWhiteSpace('\n') + BLOCK + + PsiElement(RBRACE)('}') + PsiErrorElement:Expecting '}' + \ No newline at end of file diff --git a/compiler/testData/readJavaBinaryClass/InnerClassesInGeneric.java b/compiler/testData/readJavaBinaryClass/InnerClassesInGeneric.java new file mode 100644 index 00000000000..f322543204f --- /dev/null +++ b/compiler/testData/readJavaBinaryClass/InnerClassesInGeneric.java @@ -0,0 +1,12 @@ +package test; + +interface Trait

{ +} + +class Outer { + class Inner { + } + + class Inner2 extends Inner implements Trait

{ + } +} diff --git a/compiler/testData/readJavaBinaryClass/InnerClassesInGeneric.kt b/compiler/testData/readJavaBinaryClass/InnerClassesInGeneric.kt new file mode 100644 index 00000000000..f7aecfe1b5a --- /dev/null +++ b/compiler/testData/readJavaBinaryClass/InnerClassesInGeneric.kt @@ -0,0 +1,11 @@ +package test + +trait Trait + +open class Outer() { + open class Inner() { + } + + open class Inner2() : Inner(), Trait

{ + } +} diff --git a/compiler/testData/readJavaBinaryClass/InnerClassesInGeneric.txt b/compiler/testData/readJavaBinaryClass/InnerClassesInGeneric.txt new file mode 100644 index 00000000000..e662ea177e8 --- /dev/null +++ b/compiler/testData/readJavaBinaryClass/InnerClassesInGeneric.txt @@ -0,0 +1,13 @@ +namespace test + +open class test.Outer : jet.Any { + final /*constructor*/ fun (): test.Outer + open class test.Outer.Inner : jet.Any { + final /*constructor*/ fun (): test.Outer.Inner + } + open class test.Outer.Inner2 : test.Outer.Inner, test.Trait

{ + final /*constructor*/ fun (): test.Outer.Inner2 + } +} +abstract trait test.Trait : jet.Any { +} diff --git a/compiler/testData/readJavaBinaryClass/annotation/AnnotatedAnnotation.java b/compiler/testData/readJavaBinaryClass/annotation/AnnotatedAnnotation.java new file mode 100644 index 00000000000..066f2fc29bf --- /dev/null +++ b/compiler/testData/readJavaBinaryClass/annotation/AnnotatedAnnotation.java @@ -0,0 +1,6 @@ +package test; + +@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) +@AnnotatedAnnotation +@interface AnnotatedAnnotation { +} diff --git a/compiler/testData/readJavaBinaryClass/annotation/AnnotatedAnnotation.kt b/compiler/testData/readJavaBinaryClass/annotation/AnnotatedAnnotation.kt new file mode 100644 index 00000000000..99dc9324970 --- /dev/null +++ b/compiler/testData/readJavaBinaryClass/annotation/AnnotatedAnnotation.kt @@ -0,0 +1,4 @@ +package test + +[AnnotatedAnnotation] +annotation class AnnotatedAnnotation diff --git a/compiler/testData/readJavaBinaryClass/annotation/AnnotatedAnnotation.txt b/compiler/testData/readJavaBinaryClass/annotation/AnnotatedAnnotation.txt new file mode 100644 index 00000000000..4d95c1d5fd0 --- /dev/null +++ b/compiler/testData/readJavaBinaryClass/annotation/AnnotatedAnnotation.txt @@ -0,0 +1,5 @@ +namespace test + +test.AnnotatedAnnotation() final annotation class test.AnnotatedAnnotation : jet.Any { + final /*constructor*/ fun (): test.AnnotatedAnnotation +} diff --git a/compiler/testData/readKotlinBinaryClass/class/InnerClassExtendInnerClass.kt b/compiler/testData/readKotlinBinaryClass/class/InnerClassExtendInnerClass.kt new file mode 100644 index 00000000000..85a4f6c29cc --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/class/InnerClassExtendInnerClass.kt @@ -0,0 +1,7 @@ +package test + +class Outer() { + open class Inner1() + + class Inner2() : Inner1() +} diff --git a/compiler/testData/readKotlinBinaryClass/class/InnerClassExtendInnerClass.txt b/compiler/testData/readKotlinBinaryClass/class/InnerClassExtendInnerClass.txt new file mode 100644 index 00000000000..fef91cbe9b3 --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/class/InnerClassExtendInnerClass.txt @@ -0,0 +1,11 @@ +namespace test + +final class test.Outer : jet.Any { + final /*constructor*/ fun (): test.Outer + open class test.Outer.Inner1 : jet.Any { + final /*constructor*/ fun (): test.Outer.Inner1 + } + final class test.Outer.Inner2 : test.Outer.Inner1 { + final /*constructor*/ fun (): test.Outer.Inner2 + } +} diff --git a/compiler/tests/org/jetbrains/jet/JetTestUtils.java b/compiler/tests/org/jetbrains/jet/JetTestUtils.java index 7ce129cc6d8..654499ce4d5 100644 --- a/compiler/tests/org/jetbrains/jet/JetTestUtils.java +++ b/compiler/tests/org/jetbrains/jet/JetTestUtils.java @@ -163,9 +163,12 @@ public class JetTestUtils { CompileCompilerDependenciesTest.compilerDependenciesForTests(CompilerSpecialMode.REGULAR)); } - public static JetCoreEnvironment createEnvironmentWithMockJdk(Disposable disposable) { - JetCoreEnvironment environment = new JetCoreEnvironment(disposable, CompileCompilerDependenciesTest.compilerDependenciesForTests(CompilerSpecialMode.REGULAR)); + return createEnvironmentWithMockJdk(disposable, CompilerSpecialMode.REGULAR); + } + + public static JetCoreEnvironment createEnvironmentWithMockJdk(Disposable disposable, @NotNull CompilerSpecialMode compilerSpecialMode) { + JetCoreEnvironment environment = new JetCoreEnvironment(disposable, CompileCompilerDependenciesTest.compilerDependenciesForTests(compilerSpecialMode)); final File rtJar = new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/rt.jar"); environment.addToClasspath(rtJar); environment.addToClasspath(getAnnotationsJar()); diff --git a/compiler/tests/org/jetbrains/jet/TimeUtils.java b/compiler/tests/org/jetbrains/jet/TimeUtils.java new file mode 100644 index 00000000000..646ee9eaf96 --- /dev/null +++ b/compiler/tests/org/jetbrains/jet/TimeUtils.java @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet; + +/** + * @author Stepan Koltsov + */ +public class TimeUtils { + + public static String millisecondsToSecondsString(long millis) { + return millis / 1000 + "." + String.format("%03d", millis % 1000); + } +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java b/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java index 842f18efc63..c9f64026018 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java +++ b/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java @@ -128,6 +128,7 @@ public abstract class CodegenTestCase extends JetLiteFixture { final AnalyzeExhaust analyzeExhaust = AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegrationAndCheckForErrors( myFile, JetControlFlowDataTraceFactory.EMPTY, CompileCompilerDependenciesTest.compilerDependenciesForTests(CompilerSpecialMode.REGULAR)); + analyzeExhaust.throwIfError(); GenerationState state = new GenerationState(getProject(), classBuilderFactory, analyzeExhaust, Collections.singletonList(myFile)); state.compileCorrectFiles(CompilationErrorHandler.THROW_EXCEPTION); return state; diff --git a/compiler/tests/org/jetbrains/jet/codegen/GenerationUtils.java b/compiler/tests/org/jetbrains/jet/codegen/GenerationUtils.java index bc50c0f4246..63f3b2c796c 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/GenerationUtils.java +++ b/compiler/tests/org/jetbrains/jet/codegen/GenerationUtils.java @@ -31,14 +31,15 @@ import java.util.Collections; */ public class GenerationUtils { - public static ClassFileFactory compileFileGetClassFileFactoryForTest(@NotNull JetFile psiFile) { - return compileFileGetGenerationStateForTest(psiFile).getFactory(); + public static ClassFileFactory compileFileGetClassFileFactoryForTest(@NotNull JetFile psiFile, @NotNull CompilerSpecialMode compilerSpecialMode) { + return compileFileGetGenerationStateForTest(psiFile, compilerSpecialMode).getFactory(); } - public static GenerationState compileFileGetGenerationStateForTest(JetFile psiFile) { + public static GenerationState compileFileGetGenerationStateForTest(JetFile psiFile, @NotNull CompilerSpecialMode compilerSpecialMode) { final AnalyzeExhaust analyzeExhaust = AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegrationAndCheckForErrors( psiFile, JetControlFlowDataTraceFactory.EMPTY, - CompileCompilerDependenciesTest.compilerDependenciesForTests(CompilerSpecialMode.REGULAR)); + CompileCompilerDependenciesTest.compilerDependenciesForTests(compilerSpecialMode)); + analyzeExhaust.throwIfError(); GenerationState state = new GenerationState(psiFile.getProject(), ClassBuilderFactories.binaries(false), analyzeExhaust, Collections.singletonList(psiFile)); state.compileCorrectFiles(CompilationErrorHandler.THROW_EXCEPTION); return state; diff --git a/compiler/tests/org/jetbrains/jet/codegen/forTestCompile/ForTestCompileSomething.java b/compiler/tests/org/jetbrains/jet/codegen/forTestCompile/ForTestCompileSomething.java index db89557f1c6..174ffe669dc 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/forTestCompile/ForTestCompileSomething.java +++ b/compiler/tests/org/jetbrains/jet/codegen/forTestCompile/ForTestCompileSomething.java @@ -21,6 +21,7 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.JetTestUtils; +import org.jetbrains.jet.TimeUtils; import java.io.File; import java.io.FileOutputStream; @@ -40,6 +41,8 @@ abstract class ForTestCompileSomething { private File jarFile; ForTestCompileSomething(@NotNull String jarName) { + System.out.println("Compiling " + jarName + "..."); + long start = System.currentTimeMillis(); this.jarName = jarName; try { File tmpDir = JetTestUtils.tmpDir("runtimejar"); @@ -67,6 +70,8 @@ abstract class ForTestCompileSomething { } FileUtil.delete(classesDir); + long end = System.currentTimeMillis(); + System.out.println("Compiling " + jarName + " done in " + TimeUtils.millisecondsToSecondsString(end - start) + "s"); } catch (Throwable e) { error = e; } diff --git a/compiler/tests/org/jetbrains/jet/compiler/CompileJavaAgainstKotlinTest.java b/compiler/tests/org/jetbrains/jet/compiler/CompileJavaAgainstKotlinTest.java index 5f3d17e046f..7834b4ead9d 100644 --- a/compiler/tests/org/jetbrains/jet/compiler/CompileJavaAgainstKotlinTest.java +++ b/compiler/tests/org/jetbrains/jet/compiler/CompileJavaAgainstKotlinTest.java @@ -28,6 +28,7 @@ import org.jetbrains.jet.JetTestCaseBuilder; import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.codegen.*; import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.resolve.java.CompilerSpecialMode; import org.jetbrains.jet.plugin.JetLanguage; import org.junit.Assert; @@ -75,7 +76,7 @@ public class CompileJavaAgainstKotlinTest extends TestCaseWithTmpdir { virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET); JetFile psiFile = (JetFile) ((PsiFileFactoryImpl) PsiFileFactory.getInstance(jetCoreEnvironment.getProject())).trySetupPsiForFile(virtualFile, JetLanguage.INSTANCE, true, false); - ClassFileFactory classFileFactory = GenerationUtils.compileFileGetClassFileFactoryForTest(psiFile); + ClassFileFactory classFileFactory = GenerationUtils.compileFileGetClassFileFactoryForTest(psiFile, CompilerSpecialMode.REGULAR); CompileEnvironmentUtil.writeToOutputDirectory(classFileFactory, tmpdir.getPath()); diff --git a/compiler/tests/org/jetbrains/jet/compiler/CompileKotlinAgainstKotlinTest.java b/compiler/tests/org/jetbrains/jet/compiler/CompileKotlinAgainstKotlinTest.java index a3e56c4eeb3..7eddece3513 100644 --- a/compiler/tests/org/jetbrains/jet/compiler/CompileKotlinAgainstKotlinTest.java +++ b/compiler/tests/org/jetbrains/jet/compiler/CompileKotlinAgainstKotlinTest.java @@ -29,6 +29,7 @@ import org.jetbrains.jet.JetTestCaseBuilder; import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.codegen.*; import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.resolve.java.CompilerSpecialMode; import org.jetbrains.jet.plugin.JetLanguage; import java.io.File; @@ -89,7 +90,7 @@ public class CompileKotlinAgainstKotlinTest extends TestCaseWithTmpdir { virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET); JetFile psiFile = (JetFile) ((PsiFileFactoryImpl) PsiFileFactory.getInstance(jetCoreEnvironment.getProject())).trySetupPsiForFile(virtualFile, JetLanguage.INSTANCE, true, false); - ClassFileFactory classFileFactory = GenerationUtils.compileFileGetClassFileFactoryForTest(psiFile); + ClassFileFactory classFileFactory = GenerationUtils.compileFileGetClassFileFactoryForTest(psiFile, CompilerSpecialMode.REGULAR); CompileEnvironmentUtil.writeToOutputDirectory(classFileFactory, aDir.getPath()); @@ -107,7 +108,7 @@ public class CompileKotlinAgainstKotlinTest extends TestCaseWithTmpdir { virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET); JetFile psiFile = (JetFile) ((PsiFileFactoryImpl) PsiFileFactory.getInstance(jetCoreEnvironment.getProject())).trySetupPsiForFile(virtualFile, JetLanguage.INSTANCE, true, false); - ClassFileFactory classFileFactory = GenerationUtils.compileFileGetClassFileFactoryForTest(psiFile); + ClassFileFactory classFileFactory = GenerationUtils.compileFileGetClassFileFactoryForTest(psiFile, CompilerSpecialMode.REGULAR); CompileEnvironmentUtil.writeToOutputDirectory(classFileFactory, bDir.getPath()); diff --git a/compiler/tests/org/jetbrains/jet/compiler/ReadJavaBinaryClassTest.java b/compiler/tests/org/jetbrains/jet/compiler/ReadJavaBinaryClassTest.java index f9a41a25b10..251107a40a0 100644 --- a/compiler/tests/org/jetbrains/jet/compiler/ReadJavaBinaryClassTest.java +++ b/compiler/tests/org/jetbrains/jet/compiler/ReadJavaBinaryClassTest.java @@ -76,7 +76,7 @@ public class ReadJavaBinaryClassTest extends TestCaseWithTmpdir { } private NamespaceDescriptor compileKotlin() throws Exception { - JetCoreEnvironment jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdk(myTestRootDisposable); + JetCoreEnvironment jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdk(myTestRootDisposable, CompilerSpecialMode.JDK_HEADERS); String text = FileUtil.loadFile(ktFile); @@ -86,7 +86,7 @@ public class ReadJavaBinaryClassTest extends TestCaseWithTmpdir { BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeOneFileWithJavaIntegrationAndCheckForErrors( psiFile, JetControlFlowDataTraceFactory.EMPTY, - CompileCompilerDependenciesTest.compilerDependenciesForTests(CompilerSpecialMode.REGULAR)) + CompileCompilerDependenciesTest.compilerDependenciesForTests(CompilerSpecialMode.JDK_HEADERS)) .getBindingContext(); return bindingContext.get(BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR, FqName.topLevel("test")); } @@ -108,13 +108,13 @@ public class ReadJavaBinaryClassTest extends TestCaseWithTmpdir { fileManager.close(); } - JetCoreEnvironment jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdk(myTestRootDisposable); + JetCoreEnvironment jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdk(myTestRootDisposable, CompilerSpecialMode.JDK_HEADERS); jetCoreEnvironment.addToClasspath(tmpdir); jetCoreEnvironment.addToClasspath(new File("out/production/runtime")); InjectorForJavaSemanticServices injector = new InjectorForJavaSemanticServices( - CompileCompilerDependenciesTest.compilerDependenciesForTests(CompilerSpecialMode.REGULAR), jetCoreEnvironment.getProject()); + CompileCompilerDependenciesTest.compilerDependenciesForTests(CompilerSpecialMode.JDK_HEADERS), jetCoreEnvironment.getProject()); JavaDescriptorResolver javaDescriptorResolver = injector.getJavaDescriptorResolver(); return javaDescriptorResolver.resolveNamespace(FqName.topLevel("test"), DescriptorSearchRule.ERROR_IF_FOUND_IN_KOTLIN); } diff --git a/compiler/tests/org/jetbrains/jet/compiler/ReadKotlinBinaryClassTest.java b/compiler/tests/org/jetbrains/jet/compiler/ReadKotlinBinaryClassTest.java index ae233c890cd..cd07037c40b 100644 --- a/compiler/tests/org/jetbrains/jet/compiler/ReadKotlinBinaryClassTest.java +++ b/compiler/tests/org/jetbrains/jet/compiler/ReadKotlinBinaryClassTest.java @@ -63,7 +63,7 @@ public class ReadKotlinBinaryClassTest extends TestCaseWithTmpdir { @Override public void runTest() throws Exception { - jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdk(myTestRootDisposable); + jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdk(myTestRootDisposable, CompilerSpecialMode.JDK_HEADERS); String text = FileUtil.loadFile(testFile); @@ -71,7 +71,7 @@ public class ReadKotlinBinaryClassTest extends TestCaseWithTmpdir { virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET); JetFile psiFile = (JetFile) ((PsiFileFactoryImpl) PsiFileFactory.getInstance(jetCoreEnvironment.getProject())).trySetupPsiForFile(virtualFile, JetLanguage.INSTANCE, true, false); - GenerationState state = GenerationUtils.compileFileGetGenerationStateForTest(psiFile); + GenerationState state = GenerationUtils.compileFileGetGenerationStateForTest(psiFile, CompilerSpecialMode.JDK_HEADERS); ClassFileFactory classFileFactory = state.getFactory(); @@ -84,13 +84,13 @@ public class ReadKotlinBinaryClassTest extends TestCaseWithTmpdir { Disposer.dispose(myTestRootDisposable); - jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdk(myTestRootDisposable); + jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdk(myTestRootDisposable, CompilerSpecialMode.JDK_HEADERS); jetCoreEnvironment.addToClasspath(tmpdir); jetCoreEnvironment.addToClasspath(new File("out/production/runtime")); InjectorForJavaSemanticServices injector = new InjectorForJavaSemanticServices( - CompileCompilerDependenciesTest.compilerDependenciesForTests(CompilerSpecialMode.REGULAR), jetCoreEnvironment.getProject()); + CompileCompilerDependenciesTest.compilerDependenciesForTests(CompilerSpecialMode.JDK_HEADERS), jetCoreEnvironment.getProject()); JavaDescriptorResolver javaDescriptorResolver = injector.getJavaDescriptorResolver(); NamespaceDescriptor namespaceFromClass = javaDescriptorResolver.resolveNamespace(FqName.topLevel("test"), DescriptorSearchRule.ERROR_IF_FOUND_IN_KOTLIN); diff --git a/compiler/tests/org/jetbrains/jet/compiler/WriteSignatureTest.java b/compiler/tests/org/jetbrains/jet/compiler/WriteSignatureTest.java index b74d9c7419a..f09a6fa3a0f 100644 --- a/compiler/tests/org/jetbrains/jet/compiler/WriteSignatureTest.java +++ b/compiler/tests/org/jetbrains/jet/compiler/WriteSignatureTest.java @@ -31,6 +31,7 @@ import org.jetbrains.jet.JetTestCaseBuilder; import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.codegen.*; import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.resolve.java.CompilerSpecialMode; import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames; import org.jetbrains.jet.plugin.JetLanguage; import org.junit.Assert; @@ -80,7 +81,7 @@ public class WriteSignatureTest extends TestCaseWithTmpdir { virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET); JetFile psiFile = (JetFile) ((PsiFileFactoryImpl) PsiFileFactory.getInstance(jetCoreEnvironment.getProject())).trySetupPsiForFile(virtualFile, JetLanguage.INSTANCE, true, false); - ClassFileFactory classFileFactory = GenerationUtils.compileFileGetClassFileFactoryForTest(psiFile); + ClassFileFactory classFileFactory = GenerationUtils.compileFileGetClassFileFactoryForTest(psiFile, CompilerSpecialMode.REGULAR); CompileEnvironmentUtil.writeToOutputDirectory(classFileFactory, tmpdir.getPath()); diff --git a/compiler/tests/org/jetbrains/jet/compiler/longTest/LibFromMaven.java b/compiler/tests/org/jetbrains/jet/compiler/longTest/LibFromMaven.java new file mode 100644 index 00000000000..f16c660f1da --- /dev/null +++ b/compiler/tests/org/jetbrains/jet/compiler/longTest/LibFromMaven.java @@ -0,0 +1,57 @@ +/* + * Copyright 2010-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.compiler.longTest; + +import org.jetbrains.annotations.NotNull; + +/** + * @author Stepan Koltsov + */ +public class LibFromMaven { + @NotNull + private final String org; + @NotNull + private final String module; + @NotNull + private final String rev; + + public LibFromMaven(@NotNull String org, @NotNull String module, @NotNull String rev) { + this.org = org; + this.module = module; + this.rev = rev; + } + + @NotNull + public String getOrg() { + return org; + } + + @NotNull + public String getModule() { + return module; + } + + @NotNull + public String getRev() { + return rev; + } + + @Override + public String toString() { + return org + "/" + module + "/" + rev; + } +} diff --git a/compiler/tests/org/jetbrains/jet/compiler/longTest/ResolveDescriptorsFromExternalLibraries.java b/compiler/tests/org/jetbrains/jet/compiler/longTest/ResolveDescriptorsFromExternalLibraries.java new file mode 100644 index 00000000000..a5b9c30a7ba --- /dev/null +++ b/compiler/tests/org/jetbrains/jet/compiler/longTest/ResolveDescriptorsFromExternalLibraries.java @@ -0,0 +1,199 @@ +/* + * Copyright 2010-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.compiler.longTest; + +import com.google.common.io.ByteStreams; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.util.Disposer; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.httpclient.params.HttpMethodParams; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.CompileCompilerDependenciesTest; +import org.jetbrains.jet.JetTestUtils; +import org.jetbrains.jet.TimeUtils; +import org.jetbrains.jet.compiler.JetCoreEnvironment; +import org.jetbrains.jet.di.InjectorForJavaSemanticServices; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.resolve.FqName; +import org.jetbrains.jet.lang.resolve.java.CompilerDependencies; +import org.jetbrains.jet.lang.resolve.java.CompilerSpecialMode; +import org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +/** + * @author Stepan Koltsov + */ +public class ResolveDescriptorsFromExternalLibraries { + + @NotNull + private final CompilerDependencies compilerDependencies; + + + public static void main(String[] args) throws Exception { + new ResolveDescriptorsFromExternalLibraries().run(); + System.out.println("$"); + } + + + public ResolveDescriptorsFromExternalLibraries() { + System.out.println("Getting compiler dependencies"); + compilerDependencies = CompileCompilerDependenciesTest.compilerDependenciesForTests(CompilerSpecialMode.REGULAR); + } + + private void run() throws Exception { + testLibrary("com.google.guava", "guava", "12.0-rc2"); + testLibrary("org.springframework", "spring-core", "3.1.1.RELEASE"); + } + + private void testLibrary(@NotNull String org, @NotNull String module, @NotNull String rev) throws Exception { + LibFromMaven lib = new LibFromMaven(org, module, rev); + File jar = getLibrary(lib); + System.out.println("Testing library " + lib + "..."); + System.out.println("Using file " + jar); + + long start = System.currentTimeMillis(); + + Disposable junk = new Disposable() { + @Override + public void dispose() { } + }; + + JetCoreEnvironment jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdk(junk); + jetCoreEnvironment.addToClasspath(jar); + + + InjectorForJavaSemanticServices injector = new InjectorForJavaSemanticServices(compilerDependencies, jetCoreEnvironment.getProject()); + + FileInputStream is = new FileInputStream(jar); + try { + ZipInputStream zip = new ZipInputStream(is); + for (;;) { + ZipEntry entry = zip.getNextEntry(); + if (entry == null) { + break; + } + String entryName = entry.getName(); + if (!entryName.endsWith(".class")) { + continue; + } + if (entryName.matches("(.*/|)package-info\\.class")) { + continue; + } + if (entryName.contains("$")) { + continue; + } + String className = entryName.substring(0, entryName.length() - ".class".length()).replace("/", "."); + ClassDescriptor clazz = injector.getJavaDescriptorResolver().resolveClass(new FqName(className), DescriptorSearchRule.ERROR_IF_FOUND_IN_KOTLIN); + if (clazz == null) { + throw new IllegalStateException("class not found by name " + className + " in " + lib); + } + clazz.getDefaultType().getMemberScope().getAllDescriptors(); + } + + } finally { + try { + is.close(); + } + catch (Throwable e) {} + + Disposer.dispose(junk); + } + + System.out.println("Testing library " + lib + " done in " + TimeUtils.millisecondsToSecondsString(System.currentTimeMillis() - start) + "s"); + } + + @NotNull + private File getLibrary(@NotNull LibFromMaven lib) throws Exception { + File userHome = new File(System.getProperty("user.home")); + String fileName = lib.getModule() + "-" + lib.getRev() + ".jar"; + + File dir = new File(userHome, ".kotlin-project/resolve-libraries/" + lib.getOrg() + "/" + lib.getModule()); + + File file = new File(dir, fileName); + if (file.exists()) { + return file; + } + + JetTestUtils.mkdirs(dir); + + File tmp = new File(dir, fileName + "~"); + + String uri = url(lib); + GetMethod method = new GetMethod(uri); + + FileOutputStream os = null; + + System.out.println("Downloading library " + lib + " to " + file); + + MultiThreadedHttpConnectionManager connectionManager = null; + try { + connectionManager = new MultiThreadedHttpConnectionManager(); + HttpClient httpClient = new HttpClient(connectionManager); + os = new FileOutputStream(tmp); + String userAgent = ResolveDescriptorsFromExternalLibraries.class.getName() + "/commons-httpclient"; + method.getParams().setParameter(HttpMethodParams.USER_AGENT, userAgent); + int code = httpClient.executeMethod(method); + if (code != 200) { + throw new RuntimeException("failed to execute GET " + uri + ", code is " + code); + } + InputStream responseBodyAsStream = method.getResponseBodyAsStream(); + if (responseBodyAsStream == null) { + throw new RuntimeException("method is executed fine, but response is null"); + } + ByteStreams.copy(responseBodyAsStream, os); + os.close(); + if (!tmp.renameTo(file)) { + throw new RuntimeException("failed to rename file: " + tmp + " to " + file); + } + return file; + } + finally { + if (method != null) { + try { + method.releaseConnection(); + } + catch (Throwable e) {} + } + if (connectionManager != null) { + try { + connectionManager.shutdown(); + } + catch (Throwable e) {} + } + if (os != null) { + try { + os.close(); + } + catch (Throwable e) {} + } + tmp.delete(); + } + } + + private static String url(LibFromMaven lib) { + return "http://repo1.maven.org/maven2/" + lib.getOrg().replace(".", "/") + "/" + lib.getModule() + "/" + lib.getRev() + + "/" + lib.getModule() + "-" + lib.getRev() + ".jar"; + } +} diff --git a/idea/resources/org/jetbrains/jet/plugin/icons/field_value.png b/idea/resources/org/jetbrains/jet/plugin/icons/field_value.png new file mode 100644 index 00000000000..f49d3094c63 Binary files /dev/null and b/idea/resources/org/jetbrains/jet/plugin/icons/field_value.png differ diff --git a/idea/resources/org/jetbrains/jet/plugin/icons/field_variable.png b/idea/resources/org/jetbrains/jet/plugin/icons/field_variable.png new file mode 100644 index 00000000000..dc47319f827 Binary files /dev/null and b/idea/resources/org/jetbrains/jet/plugin/icons/field_variable.png differ diff --git a/idea/resources/org/jetbrains/jet/plugin/icons/kotlin13x13.png b/idea/resources/org/jetbrains/jet/plugin/icons/kotlin13x13.png new file mode 100644 index 00000000000..2510d022cc8 Binary files /dev/null and b/idea/resources/org/jetbrains/jet/plugin/icons/kotlin13x13.png differ diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index e6132530e51..ace5239fa46 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -56,7 +56,7 @@ - + @@ -109,6 +109,7 @@ + @@ -170,7 +171,7 @@ diff --git a/idea/src/org/jetbrains/jet/plugin/JetDescriptorIconProvider.java b/idea/src/org/jetbrains/jet/plugin/JetDescriptorIconProvider.java index 2b6506cfc7c..1317a34b943 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetDescriptorIconProvider.java +++ b/idea/src/org/jetbrains/jet/plugin/JetDescriptorIconProvider.java @@ -76,7 +76,8 @@ public final class JetDescriptorIconProvider { return PlatformIcons.PACKAGE_OPEN_ICON; } if (descriptor instanceof FunctionDescriptor) { - return JetIcons.FUNCTION; + return descriptor.getContainingDeclaration() instanceof ClassDescriptor ? + PlatformIcons.METHOD_ICON : JetIcons.FUNCTION; } if (descriptor instanceof ClassDescriptor) { switch (((ClassDescriptor)descriptor).getKind()) { @@ -97,9 +98,20 @@ public final class JetDescriptorIconProvider { return null; } } + if (descriptor instanceof ValueParameterDescriptor) { + return JetIcons.PARAMETER; + } + + if (descriptor instanceof LocalVariableDescriptor) { + return ((LocalVariableDescriptor)descriptor).isVar() ? JetIcons.VAR : JetIcons.VAL; + } if (descriptor instanceof PropertyDescriptor) { - return ((PropertyDescriptor)descriptor).isVar() ? JetIcons.VAR : JetIcons.VAL; + return ((PropertyDescriptor)descriptor).isVar() ? JetIcons.FIELD_VAR : JetIcons.FIELD_VAL; + } + + if (descriptor instanceof TypeParameterDescriptor) { + return PlatformIcons.CLASS_ICON; } LOG.warn("No icon for descriptor: " + descriptor); diff --git a/idea/src/org/jetbrains/jet/plugin/JetIconProvider.java b/idea/src/org/jetbrains/jet/plugin/JetIconProvider.java index 970a9f2f58a..a237db389ea 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetIconProvider.java +++ b/idea/src/org/jetbrains/jet/plugin/JetIconProvider.java @@ -64,7 +64,7 @@ public class JetIconProvider extends IconProvider { } if (psiElement instanceof JetNamedFunction) { return PsiTreeUtil.getParentOfType(psiElement, JetNamedDeclaration.class) instanceof JetClass - ? JetIcons.LAMBDA + ? PlatformIcons.METHOD_ICON : JetIcons.FUNCTION; } if (psiElement instanceof JetClass) { @@ -90,14 +90,14 @@ public class JetIconProvider extends IconProvider { if (parameter.getValOrVarNode() != null) { JetParameterList parameterList = PsiTreeUtil.getParentOfType(psiElement, JetParameterList.class); if (parameterList != null && parameterList.getParent() instanceof JetClass) { - return parameter.isVarArg() ? JetIcons.VAR : JetIcons.VAL; + return parameter.isMutable() ? JetIcons.FIELD_VAR : JetIcons.FIELD_VAL; } } return JetIcons.PARAMETER; } if (psiElement instanceof JetProperty) { JetProperty property = (JetProperty)psiElement; - return property.isVar() ? JetIcons.VAR : JetIcons.VAL; + return property.isVar() ? JetIcons.FIELD_VAR : JetIcons.FIELD_VAL; } return null; } diff --git a/idea/src/org/jetbrains/jet/plugin/JetIcons.java b/idea/src/org/jetbrains/jet/plugin/JetIcons.java index 79ef34542c1..8e9969cec3f 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetIcons.java +++ b/idea/src/org/jetbrains/jet/plugin/JetIcons.java @@ -34,4 +34,6 @@ public interface JetIcons { Icon VAR = IconLoader.getIcon("/org/jetbrains/jet/plugin/icons/variable.png"); Icon VAL = IconLoader.getIcon("/org/jetbrains/jet/plugin/icons/value.png"); Icon PARAMETER = IconLoader.getIcon("/org/jetbrains/jet/plugin/icons/parameter.png"); + Icon FIELD_VAL = IconLoader.getIcon("/org/jetbrains/jet/plugin/icons/field_value.png"); + Icon FIELD_VAR = IconLoader.getIcon("/org/jetbrains/jet/plugin/icons/field_variable.png"); } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/confidence/UnfocusedPossibleFunctionParameter.java b/idea/src/org/jetbrains/jet/plugin/completion/confidence/UnfocusedPossibleFunctionParameter.java new file mode 100644 index 00000000000..7cc77460e6c --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/completion/confidence/UnfocusedPossibleFunctionParameter.java @@ -0,0 +1,76 @@ +/* + * Copyright 2010-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.plugin.completion.confidence; + +import com.intellij.codeInsight.completion.CompletionConfidence; +import com.intellij.codeInsight.completion.CompletionParameters; +import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.ThreeState; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.psi.*; + +/** + * @author Nikolay Krasko + */ +public class UnfocusedPossibleFunctionParameter extends CompletionConfidence { + @NotNull + @Override + public ThreeState shouldFocusLookup(@NotNull CompletionParameters parameters) { + // 1. Do not automatically insert completion for first reference expression in block inside + // function literal if it has no parameters yet. + + // 2. The same but for the case when first expression is additionally surrounded with brackets + + PsiElement position = parameters.getPosition(); + JetFunctionLiteralExpression functionLiteral = PsiTreeUtil.getParentOfType( + position, JetFunctionLiteralExpression.class); + + if (functionLiteral != null) { + PsiElement expectedReference = position.getParent(); + if (expectedReference instanceof JetSimpleNameExpression) { + if (PsiTreeUtil.findChildOfType(functionLiteral, JetParameterList.class) == null) { + { + // 1. + PsiElement expectedBlock = expectedReference.getParent(); + if (expectedBlock instanceof JetBlockExpression) { + if (expectedReference.getPrevSibling() == null) { + return ThreeState.NO; + } + } + } + + { + // 2. + PsiElement expectedParenthesized = expectedReference.getParent(); + if (expectedParenthesized instanceof JetParenthesizedExpression) { + PsiElement expectedBlock = expectedParenthesized.getParent(); + if (expectedBlock instanceof JetBlockExpression) { + if (expectedParenthesized.getPrevSibling() == null) { + return ThreeState.NO; + } + } + } + } + } + } + } + + return ThreeState.UNSURE; + } +} + diff --git a/idea/src/org/jetbrains/jet/plugin/debugger/JetPositionManager.java b/idea/src/org/jetbrains/jet/plugin/debugger/JetPositionManager.java index 7b53f454aa2..5c2f3d532e5 100644 --- a/idea/src/org/jetbrains/jet/plugin/debugger/JetPositionManager.java +++ b/idea/src/org/jetbrains/jet/plugin/debugger/JetPositionManager.java @@ -155,6 +155,7 @@ public class JetPositionManager implements PositionManager { return mapper; } final AnalyzeExhaust analyzeExhaust = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file); + analyzeExhaust.throwIfError(); JetTypeMapper typeMapper = new InjectorForJetTypeMapper( analyzeExhaust.getStandardLibrary(), analyzeExhaust.getBindingContext(), Collections.singletonList(file)).getJetTypeMapper(); myTypeMappers.put(file, typeMapper); diff --git a/idea/src/org/jetbrains/jet/plugin/internal/codewindow/BytecodeToolwindow.java b/idea/src/org/jetbrains/jet/plugin/internal/codewindow/BytecodeToolwindow.java index b7bfe2551a2..9ea5583e1b3 100644 --- a/idea/src/org/jetbrains/jet/plugin/internal/codewindow/BytecodeToolwindow.java +++ b/idea/src/org/jetbrains/jet/plugin/internal/codewindow/BytecodeToolwindow.java @@ -206,13 +206,14 @@ public class BytecodeToolwindow extends JPanel implements Disposable { try { AnalyzeExhaust binding = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file); // AnalyzingUtils.throwExceptionOnErrors(binding); + if (binding.isError()) { + return printStackTraceToString(binding.getError()); + } state = new GenerationState(myProject, ClassBuilderFactories.TEXT, binding, Collections.singletonList(file)); state.compileCorrectFiles(CompilationErrorHandler.THROW_EXCEPTION); } catch (Exception e) { - StringWriter out = new StringWriter(1024); - e.printStackTrace(new PrintWriter(out)); - return out.toString().replaceAll("\r", ""); + return printStackTraceToString(e); } @@ -229,6 +230,11 @@ public class BytecodeToolwindow extends JPanel implements Disposable { return answer.toString(); } + private static String printStackTraceToString(Throwable e) {StringWriter out = new StringWriter(1024); + e.printStackTrace(new PrintWriter(out)); + return out.toString().replace("\r", ""); + } + @Override public void dispose() { EditorFactory.getInstance().releaseEditor(myEditor); diff --git a/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeWithCache.java b/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeWithCache.java index c5ce3144984..fac916c618c 100644 --- a/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeWithCache.java +++ b/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeWithCache.java @@ -96,7 +96,7 @@ public final class AnalyzerFacadeWithCache { private Result emptyExhaustWithDiagnosticOnFile(Throwable e) { BindingTraceContext bindingTraceContext = new BindingTraceContext(); bindingTraceContext.report(Errors.EXCEPTION_WHILE_ANALYZING.on(file, e)); - AnalyzeExhaust analyzeExhaust = new AnalyzeExhaust(bindingTraceContext.getBindingContext(), null); + AnalyzeExhaust analyzeExhaust = AnalyzeExhaust.error(bindingTraceContext.getBindingContext(), e); return new Result(analyzeExhaust, PsiModificationTracker.MODIFICATION_COUNT); } }, false); diff --git a/idea/src/org/jetbrains/jet/plugin/project/JSAnalyzerFacadeForIDEA.java b/idea/src/org/jetbrains/jet/plugin/project/JSAnalyzerFacadeForIDEA.java index a9b0292b39f..80976459e39 100644 --- a/idea/src/org/jetbrains/jet/plugin/project/JSAnalyzerFacadeForIDEA.java +++ b/idea/src/org/jetbrains/jet/plugin/project/JSAnalyzerFacadeForIDEA.java @@ -47,6 +47,6 @@ public enum JSAnalyzerFacadeForIDEA implements AnalyzerFacade { @NotNull Predicate filesToAnalyzeCompletely, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) { BindingContext context = AnalyzerFacadeForJS.analyzeFiles(files, new IDEAConfig(project)); - return new AnalyzeExhaust(context, JetStandardLibrary.getInstance()); + return AnalyzeExhaust.success(context, JetStandardLibrary.getInstance()); } -} \ No newline at end of file +} diff --git a/idea/src/org/jetbrains/jet/plugin/reporter/KotlinReportSubmitter.java b/idea/src/org/jetbrains/jet/plugin/reporter/KotlinReportSubmitter.java new file mode 100644 index 00000000000..dd158d9404c --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/reporter/KotlinReportSubmitter.java @@ -0,0 +1,49 @@ +/* + * Copyright 2010-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.plugin.reporter; + +import com.intellij.diagnostic.ITNReporter; +import com.intellij.openapi.diagnostic.ErrorReportSubmitter; +import com.intellij.openapi.diagnostic.IdeaLoggingEvent; +import com.intellij.openapi.diagnostic.SubmittedReportInfo; + +import java.awt.*; + +/** + * We need to wrap ITNReporter into this delegating class to work around the following problem: + * + * Kotlin's lifecycle does not align with the one of IDEA, so every now and then we are in the situation when users + * install an unstable build of Kotlin on a released build of IDEA. Since IDEA does not show exceptions from ITNReporter + * in release build, the user doesn't see exceptions from Kotlin in such a situations. Wrapping solves this problem: + * even release builds of IDEA will report Kotlin exceptions to the user (and allow to submit them to Exception Analyzer). + * + * @author abreslav + */ +public class KotlinReportSubmitter extends ErrorReportSubmitter { + + private final ErrorReportSubmitter delegate = new ITNReporter(); + + @Override + public String getReportActionText() { + return delegate.getReportActionText(); + } + + @Override + public SubmittedReportInfo submit(IdeaLoggingEvent[] events, Component parentComponent) { + return delegate.submit(events, parentComponent); + } +} diff --git a/idea/testData/completion/confidence/InBeginningOfFunctionLiteral.kt b/idea/testData/completion/confidence/InBeginningOfFunctionLiteral.kt new file mode 100644 index 00000000000..03898c0f8b1 --- /dev/null +++ b/idea/testData/completion/confidence/InBeginningOfFunctionLiteral.kt @@ -0,0 +1,4 @@ +fun main(args : Array) { + val mmm = 12 + val t = { } +} \ No newline at end of file diff --git a/idea/testData/completion/confidence/InBeginningOfFunctionLiteral.kt.after b/idea/testData/completion/confidence/InBeginningOfFunctionLiteral.kt.after new file mode 100644 index 00000000000..c1079d37611 --- /dev/null +++ b/idea/testData/completion/confidence/InBeginningOfFunctionLiteral.kt.after @@ -0,0 +1,4 @@ +fun main(args : Array) { + val mmm = 12 + val t = { mm } +} \ No newline at end of file diff --git a/idea/testData/completion/confidence/InBeginningOfFunctionLiteralInBrackets.kt b/idea/testData/completion/confidence/InBeginningOfFunctionLiteralInBrackets.kt new file mode 100644 index 00000000000..0fcec1593b2 --- /dev/null +++ b/idea/testData/completion/confidence/InBeginningOfFunctionLiteralInBrackets.kt @@ -0,0 +1,4 @@ +fun main(args : Array) { + val mmm = 12 + val t = { () } +} \ No newline at end of file diff --git a/idea/testData/completion/confidence/InBeginningOfFunctionLiteralInBrackets.kt.after b/idea/testData/completion/confidence/InBeginningOfFunctionLiteralInBrackets.kt.after new file mode 100644 index 00000000000..34d71fc9fe5 --- /dev/null +++ b/idea/testData/completion/confidence/InBeginningOfFunctionLiteralInBrackets.kt.after @@ -0,0 +1,4 @@ +fun main(args : Array) { + val mmm = 12 + val t = { (mm ) } +} \ No newline at end of file diff --git a/idea/testData/completion/confidence/InBlockOfFunctionLiteral.kt b/idea/testData/completion/confidence/InBlockOfFunctionLiteral.kt new file mode 100644 index 00000000000..f438d237441 --- /dev/null +++ b/idea/testData/completion/confidence/InBlockOfFunctionLiteral.kt @@ -0,0 +1,4 @@ +fun main(args : Array) { + val mmm = 12 + val t = { i -> } +} \ No newline at end of file diff --git a/idea/testData/completion/confidence/InBlockOfFunctionLiteral.kt.after b/idea/testData/completion/confidence/InBlockOfFunctionLiteral.kt.after new file mode 100644 index 00000000000..b541c7e8f9f --- /dev/null +++ b/idea/testData/completion/confidence/InBlockOfFunctionLiteral.kt.after @@ -0,0 +1,4 @@ +fun main(args : Array) { + val mmm = 12 + val t = { i -> mmm } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/completion/confidence/JetConfidenceTest.java b/idea/tests/org/jetbrains/jet/completion/confidence/JetConfidenceTest.java index ec19983e491..9c6cd87ab9a 100644 --- a/idea/tests/org/jetbrains/jet/completion/confidence/JetConfidenceTest.java +++ b/idea/tests/org/jetbrains/jet/completion/confidence/JetConfidenceTest.java @@ -16,6 +16,8 @@ package org.jetbrains.jet.completion.confidence; +import com.intellij.codeInsight.completion.CodeCompletionHandlerBase; +import com.intellij.codeInsight.completion.CompletionType; import com.intellij.codeInsight.completion.LightCompletionTestCase; import com.intellij.openapi.projectRoots.JavaSdk; import com.intellij.openapi.projectRoots.Sdk; @@ -37,6 +39,18 @@ public class JetConfidenceTest extends LightCompletionTestCase { doTest("pub"); } + public void testInBeginningOfFunctionLiteral() { + doTest("mm"); + } + + public void testInBeginningOfFunctionLiteralInBrackets() { + doTest("mm"); + } + + public void testInBlockOfFunctionLiteral() { + doTest("mm"); + } + protected void doTest(String completionActivateType) { configureByFile(getBeforeFileName()); type(completionActivateType + " "); @@ -60,4 +74,9 @@ public class JetConfidenceTest extends LightCompletionTestCase { protected Sdk getProjectJDK() { return JavaSdk.getInstance().createJdk("JDK", SystemUtils.getJavaHome().getAbsolutePath()); } + + @Override + protected void complete() { + new CodeCompletionHandlerBase(CompletionType.BASIC, false, true, true).invokeCompletion(getProject(), getEditor(), 0, false); + } } \ No newline at end of file