From 631961e7619fb3d2a7f659b44b1e15fb0a51cfb0 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Mon, 27 Feb 2012 21:35:00 +0400 Subject: [PATCH 1/4] Diagnostics & diagnostic factories refactoring --- .../jet/compiler/CompileSession.java | 4 +- .../jet/compiler/ErrorCollector.java | 2 +- .../jet/checkers/CheckerTestUtil.java | 59 +- .../lang/cfg/JetFlowInformationProvider.java | 12 +- ...iagnostic.java => AbstractDiagnostic.java} | 37 +- .../AbstractDiagnosticFactory.java | 24 +- .../AmbiguousDescriptorDiagnosticFactory.java | 28 +- .../jet/lang/diagnostics/Diagnostic.java | 22 +- .../lang/diagnostics/DiagnosticFactory.java | 36 +- .../lang/diagnostics/DiagnosticFactory1.java | 61 ++ .../lang/diagnostics/DiagnosticFactory2.java | 69 ++ .../lang/diagnostics/DiagnosticFactory3.java | 72 ++ .../DiagnosticFactoryWithMessageFormat.java | 15 +- ...a => DiagnosticFactoryWithPsiElement.java} | 14 +- .../DiagnosticFactoryWithPsiElement1.java | 64 -- .../DiagnosticFactoryWithPsiElement2.java | 61 -- .../DiagnosticFactoryWithPsiElement3.java | 72 -- .../lang/diagnostics/DiagnosticHolder.java | 5 +- .../jet/lang/diagnostics/DiagnosticUtils.java | 6 +- .../DiagnosticWithParameterFactory.java | 43 -- .../diagnostics/DiagnosticWithParameters.java | 48 -- .../diagnostics/DiagnosticWithPsiElement.java | 27 +- .../DiagnosticWithPsiElementImpl.java | 48 -- .../diagnostics/DiagnosticWithTextRange.java | 33 - .../jet/lang/diagnostics/Errors.java | 696 ++++++++---------- .../FunctionSignatureDiagnosticFactory.java | 78 -- .../ParameterizedDiagnosticFactory1.java | 54 -- .../ParameterizedDiagnosticFactory2.java | 55 -- .../ParameterizedDiagnosticFactory3.java | 54 -- .../diagnostics/PositioningStrategies.java | 126 ++++ ...cFactory.java => PositioningStrategy.java} | 32 +- .../PsiElementOnlyDiagnosticFactory.java | 25 - .../PsiElementOnlyDiagnosticFactory1.java | 39 - .../PsiElementOnlyDiagnosticFactory2.java | 40 - .../PsiElementOnlyDiagnosticFactory3.java | 39 - .../diagnostics/RedeclarationDiagnostic.java | 53 +- .../RedeclarationDiagnosticFactory.java | 20 - .../jet/lang/diagnostics/Renderer.java | 17 +- .../jet/lang/diagnostics/Renderers.java | 77 ++ ...SimpleDiagnosticFactoryWithPsiElement.java | 59 -- ...SimplePsiElementOnlyDiagnosticFactory.java | 33 - .../UnresolvedReferenceDiagnostic.java | 23 +- .../UnresolvedReferenceDiagnosticFactory.java | 18 +- .../UnusedElementDiagnosticFactory.java | 22 +- .../src/org/jetbrains/jet/lang/psi/Call.java | 3 - .../jet/lang/resolve/AnalyzingUtils.java | 6 +- .../jet/lang/resolve/BodyResolver.java | 12 +- .../jet/lang/resolve/DeclarationResolver.java | 3 +- .../jet/lang/resolve/DeclarationsChecker.java | 62 +- .../jet/lang/resolve/DescriptorResolver.java | 28 +- .../jet/lang/resolve/OverrideResolver.java | 13 +- .../lang/resolve/TypeHierarchyResolver.java | 12 +- .../jet/lang/resolve/calls/CallMaker.java | 20 +- .../jet/lang/resolve/calls/CallResolver.java | 14 +- .../lang/resolve/calls/DelegatingCall.java | 6 - .../BasicExpressionTypingVisitor.java | 11 +- .../expressions/ExpressionTypingServices.java | 3 +- .../expressions/ExpressionTypingUtils.java | 1 - .../PatternMatchingTypingVisitor.java | 2 +- .../jet/resolve/DescriptorRenderer.java | 7 +- .../diagnostics/tests/AbstractInTrait.jet | 23 +- .../actions/CopyAsDiagnosticTestAction.java | 3 +- .../jet/plugin/annotations/JetPsiChecker.java | 27 +- .../plugin/quickfix/AddFunctionBodyFix.java | 18 +- .../jet/plugin/quickfix/AddModifierFix.java | 17 +- .../jet/plugin/quickfix/AddReturnTypeFix.java | 37 +- .../quickfix/ChangeAccessorTypeFix.java | 57 +- .../quickfix/ChangeToBackingFieldFix.java | 26 +- .../quickfix/ChangeToInvocationFix.java | 14 +- .../quickfix/FakeDiagnosticForQuickFixes.java | 74 ++ .../plugin/quickfix/ImportClassAndFunFix.java | 11 +- .../plugin/quickfix/JetIntentionAction.java | 18 +- .../quickfix/JetIntentionActionFactory.java | 10 +- .../jet/plugin/quickfix/QuickFixUtil.java | 91 +-- .../jet/plugin/quickfix/QuickFixes.java | 149 ++-- .../quickfix/RemoveFunctionBodyFix.java | 13 +- .../plugin/quickfix/RemoveModifierFix.java | 152 ++-- .../quickfix/RemovePartsFromPropertyFix.java | 56 +- .../RemoveRightPartOfBinaryExpressionFix.java | 47 +- ...ReplaceOperationInBinaryExpressionFix.java | 15 +- .../afterRemoveRedundantModifier3.kt | 2 +- 81 files changed, 1486 insertions(+), 1999 deletions(-) rename compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/{GenericDiagnostic.java => AbstractDiagnostic.java} (65%) create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactory1.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactory2.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactory3.java rename compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/{DiagnosticFactoryWithSeverity.java => DiagnosticFactoryWithPsiElement.java} (55%) delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement1.java delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement2.java delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement3.java delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithParameterFactory.java delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithParameters.java delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithPsiElementImpl.java delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithTextRange.java delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/FunctionSignatureDiagnosticFactory.java delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory1.java delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory2.java delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory3.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategies.java rename compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/{SimpleDiagnosticFactory.java => PositioningStrategy.java} (52%) delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PsiElementOnlyDiagnosticFactory.java delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PsiElementOnlyDiagnosticFactory1.java delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PsiElementOnlyDiagnosticFactory2.java delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PsiElementOnlyDiagnosticFactory3.java create mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Renderers.java delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/SimpleDiagnosticFactoryWithPsiElement.java delete mode 100644 compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/SimplePsiElementOnlyDiagnosticFactory.java create mode 100644 idea/src/org/jetbrains/jet/plugin/quickfix/FakeDiagnosticForQuickFixes.java diff --git a/compiler/cli/src/org/jetbrains/jet/compiler/CompileSession.java b/compiler/cli/src/org/jetbrains/jet/compiler/CompileSession.java index 50342a7bc7b..c8f97f02607 100644 --- a/compiler/cli/src/org/jetbrains/jet/compiler/CompileSession.java +++ b/compiler/cli/src/org/jetbrains/jet/compiler/CompileSession.java @@ -35,8 +35,8 @@ import org.jetbrains.jet.lang.descriptors.ClassOrNamespaceDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; import org.jetbrains.jet.lang.diagnostics.Diagnostic; +import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory; import org.jetbrains.jet.lang.diagnostics.Severity; -import org.jetbrains.jet.lang.diagnostics.SimpleDiagnosticFactory; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade; @@ -190,7 +190,7 @@ public class CompileSession { public void visitErrorElement(PsiErrorElement element) { String description = element.getErrorDescription(); String message = StringUtil.isEmpty(description) ? "Syntax error" : description; - Diagnostic diagnostic = SimpleDiagnosticFactory.create(Severity.ERROR, message).on(element); + Diagnostic diagnostic = DiagnosticFactory.create(Severity.ERROR, message).on(element); errorCollector.report(diagnostic); } }); diff --git a/compiler/cli/src/org/jetbrains/jet/compiler/ErrorCollector.java b/compiler/cli/src/org/jetbrains/jet/compiler/ErrorCollector.java index b91b23bc484..8bf506a613b 100644 --- a/compiler/cli/src/org/jetbrains/jet/compiler/ErrorCollector.java +++ b/compiler/cli/src/org/jetbrains/jet/compiler/ErrorCollector.java @@ -39,7 +39,7 @@ class ErrorCollector { public void report(Diagnostic diagnostic) { hasErrors |= diagnostic.getSeverity() == Severity.ERROR; - maps.put(diagnostic.getFactory().getPsiFile(diagnostic), diagnostic); + maps.put(diagnostic.getPsiFile(), diagnostic); } public void flushTo(final PrintStream out) { diff --git a/compiler/frontend/src/org/jetbrains/jet/checkers/CheckerTestUtil.java b/compiler/frontend/src/org/jetbrains/jet/checkers/CheckerTestUtil.java index c18bead3c1b..c3d45723c74 100644 --- a/compiler/frontend/src/org/jetbrains/jet/checkers/CheckerTestUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/checkers/CheckerTestUtil.java @@ -23,12 +23,12 @@ import com.google.common.collect.Lists; import com.google.common.collect.Multiset; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiErrorElement; import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.diagnostics.AbstractDiagnosticFactory; import org.jetbrains.jet.lang.diagnostics.Diagnostic; -import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory; -import org.jetbrains.jet.lang.diagnostics.DiagnosticWithTextRange; import org.jetbrains.jet.lang.diagnostics.Severity; import org.jetbrains.jet.lang.resolve.AnalyzingUtils; import org.jetbrains.jet.lang.resolve.BindingContext; @@ -72,8 +72,8 @@ public class CheckerTestUtil { public static List getDiagnosticsIncludingSyntaxErrors(BindingContext bindingContext, PsiElement root) { ArrayList diagnostics = new ArrayList(); diagnostics.addAll(bindingContext.getDiagnostics()); - for (TextRange textRange : AnalyzingUtils.getSyntaxErrorRanges(root)) { - diagnostics.add(new SyntaxErrorDiagnostic(textRange, root.getContainingFile())); + for (PsiErrorElement errorElement : AnalyzingUtils.getSyntaxErrorRanges(root)) { + diagnostics.add(new SyntaxErrorDiagnostic(errorElement)); } return diagnostics; } @@ -159,7 +159,7 @@ public class CheckerTestUtil { private static void unexpectedDiagnostics(List actual, DiagnosticDiffCallbacks callbacks) { for (Diagnostic diagnostic : actual) { - if (!diagnostic.getFactory().getPsiFile(diagnostic).equals(callbacks.getFile())) continue; + if (!diagnostic.getPsiFile().equals(callbacks.getFile())) continue; List textRanges = getTextRanges(diagnostic); for (TextRange textRange : textRanges) { callbacks.unexpectedDiagnostic(diagnostic.getFactory().getName(), textRange.getStartOffset(), textRange.getEndOffset()); @@ -209,11 +209,11 @@ public class CheckerTestUtil { return matcher.replaceAll(""); } - public static StringBuffer addDiagnosticMarkersToText(PsiFile psiFile, BindingContext bindingContext, List syntaxErrors) { + public static StringBuffer addDiagnosticMarkersToText(PsiFile psiFile, BindingContext bindingContext, List syntaxErrors) { Collection diagnostics = new ArrayList(); diagnostics.addAll(bindingContext.getDiagnostics()); - for (TextRange syntaxError : syntaxErrors) { - diagnostics.add(new SyntaxErrorDiagnostic(syntaxError, psiFile)); + for (PsiErrorElement syntaxError : syntaxErrors) { + diagnostics.add(new SyntaxErrorDiagnostic(syntaxError)); } return addDiagnosticMarkersToText(psiFile, diagnostics); @@ -225,7 +225,7 @@ public class CheckerTestUtil { diagnostics = Collections2.filter(diagnostics, new Predicate() { @Override public boolean apply(@Nullable Diagnostic diagnostic) { - if (diagnostic == null || !psiFile.equals(diagnostic.getFactory().getPsiFile(diagnostic))) return false; + if (diagnostic == null || !psiFile.equals(diagnostic.getPsiFile())) return false; return true; } }); @@ -297,21 +297,9 @@ public class CheckerTestUtil { result.append(""); } - private static class SyntaxErrorDiagnosticFactory implements DiagnosticFactory { + private static class SyntaxErrorDiagnosticFactory extends AbstractDiagnosticFactory { private static final SyntaxErrorDiagnosticFactory instance = new SyntaxErrorDiagnosticFactory(); - @NotNull - @Override - public List getTextRanges(@NotNull Diagnostic diagnostic) { - return Collections.singletonList(((SyntaxErrorDiagnostic) diagnostic).textRange); - } - - @NotNull - @Override - public PsiFile getPsiFile(@NotNull Diagnostic diagnostic) { - return ((SyntaxErrorDiagnostic)diagnostic).getPsiFile(); - } - @NotNull @Override public String getName() { @@ -319,19 +307,16 @@ public class CheckerTestUtil { } } - public static class SyntaxErrorDiagnostic implements DiagnosticWithTextRange { + public static class SyntaxErrorDiagnostic implements Diagnostic { + private final PsiErrorElement errorElement; - private final TextRange textRange; - private final PsiFile psiFile; - - public SyntaxErrorDiagnostic(@NotNull TextRange textRange, @NotNull PsiFile psiFile) { - this.textRange = textRange; - this.psiFile = psiFile; + public SyntaxErrorDiagnostic(@NotNull PsiErrorElement errorElement) { + this.errorElement = errorElement; } @NotNull @Override - public DiagnosticFactory getFactory() { + public AbstractDiagnosticFactory getFactory() { return SyntaxErrorDiagnosticFactory.instance; } @@ -349,14 +334,20 @@ public class CheckerTestUtil { @NotNull @Override - public TextRange getTextRange() { - return textRange; + public PsiErrorElement getPsiElement() { + return errorElement; + } + + @NotNull + @Override + public List getTextRanges() { + return Collections.singletonList(errorElement.getTextRange()); } @NotNull @Override public PsiFile getPsiFile() { - return psiFile; + return errorElement.getContainingFile(); } } @@ -380,7 +371,7 @@ public class CheckerTestUtil { } private static List getTextRanges(Diagnostic currentDiagnostic) { - return currentDiagnostic.getFactory().getTextRanges(currentDiagnostic); + return currentDiagnostic.getTextRanges(); } private static class DiagnosticDescriptor { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java index 8951b9eaa0c..152092a9120 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java @@ -371,10 +371,10 @@ public class JetFlowInformationProvider { JetSimpleNameExpression simpleNameExpression = (JetSimpleNameExpression) variable; if (simpleNameExpression.getReferencedNameElementType() != JetTokens.FIELD_IDENTIFIER) { if (((PropertyDescriptor) variableDescriptor).getModality() != Modality.FINAL) { - trace.report(Errors.INITIALIZATION_USING_BACKING_FIELD_OPEN_SETTER.on(simpleNameExpression, expression, variableDescriptor)); + trace.report(Errors.INITIALIZATION_USING_BACKING_FIELD_OPEN_SETTER.on(expression, variableDescriptor)); } else { - trace.report(Errors.INITIALIZATION_USING_BACKING_FIELD_CUSTOM_SETTER.on(simpleNameExpression, expression, variableDescriptor)); + trace.report(Errors.INITIALIZATION_USING_BACKING_FIELD_CUSTOM_SETTER.on(expression, variableDescriptor)); } return true; } @@ -620,7 +620,7 @@ public class JetFlowInformationProvider { if (nameIdentifier == null) return; if (variableStatus == null || variableStatus == VariableStatus.UNUSED) { if (element instanceof JetProperty) { - trace.report(Errors.UNUSED_VARIABLE.on((JetProperty) element, nameIdentifier, variableDescriptor)); + trace.report(Errors.UNUSED_VARIABLE.on((JetProperty) element, variableDescriptor)); } else if (element instanceof JetParameter) { PsiElement psiElement = element.getParent().getParent(); @@ -630,18 +630,18 @@ public class JetFlowInformationProvider { assert descriptor instanceof FunctionDescriptor; FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor; if (!isMain && !functionDescriptor.getModality().isOverridable() && functionDescriptor.getOverriddenDescriptors().isEmpty()) { - trace.report(Errors.UNUSED_PARAMETER.on((JetParameter) element, nameIdentifier, variableDescriptor)); + trace.report(Errors.UNUSED_PARAMETER.on((JetParameter) element, variableDescriptor)); } } } } else if (variableStatus == VariableStatus.ONLY_WRITTEN && element instanceof JetProperty) { - trace.report(Errors.ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE.on((JetNamedDeclaration) element, nameIdentifier, variableDescriptor)); + trace.report(Errors.ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE.on((JetNamedDeclaration) element, variableDescriptor)); } else if (variableStatus == VariableStatus.WRITTEN && element instanceof JetProperty) { JetExpression initializer = ((JetProperty) element).getInitializer(); if (initializer != null) { - trace.report(Errors.VARIABLE_WITH_REDUNDANT_INITIALIZER.on((JetNamedDeclaration) element, initializer, variableDescriptor)); + trace.report(Errors.VARIABLE_WITH_REDUNDANT_INITIALIZER.on(initializer, variableDescriptor)); } } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/GenericDiagnostic.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/AbstractDiagnostic.java similarity index 65% rename from compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/GenericDiagnostic.java rename to compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/AbstractDiagnostic.java index 6fc9854948e..635893bbf6b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/GenericDiagnostic.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/AbstractDiagnostic.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2012 JetBrains s.r.o. + * Copyright 2000-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. @@ -16,44 +16,36 @@ 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 abreslav -*/ -public class GenericDiagnostic implements DiagnosticWithTextRange { - - private final TextRange textRange; + * @author svtk + */ +public abstract class AbstractDiagnostic

implements Diagnostic

{ + private final P psiElement; private final String message; - private final DiagnosticFactory factory; + private final AbstractDiagnosticFactory factory; private final Severity severity; - private final PsiFile psiFile; - public GenericDiagnostic(DiagnosticFactory factory, Severity severity, String message, @NotNull PsiFile psiFile, @NotNull TextRange textRange) { + public AbstractDiagnostic(@NotNull P psiElement, @NotNull AbstractDiagnosticFactory factory, @NotNull Severity severity, @NotNull String message) { + this.psiElement = psiElement; this.factory = factory; - this.textRange = textRange; this.severity = severity; this.message = message; - this.psiFile = psiFile; } @NotNull @Override - public DiagnosticFactory getFactory() { + public AbstractDiagnosticFactory getFactory() { return factory; } - @NotNull - public TextRange getTextRange() { - return textRange; - } - @NotNull @Override public PsiFile getPsiFile() { - return psiFile; + return psiElement.getContainingFile(); } @NotNull @@ -67,4 +59,11 @@ public class GenericDiagnostic implements DiagnosticWithTextRange { public Severity getSeverity() { return severity; } + + + @Override + @NotNull + public P getPsiElement() { + return psiElement; + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/AbstractDiagnosticFactory.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/AbstractDiagnosticFactory.java index 9e41d02e0a4..8d6198a8a58 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/AbstractDiagnosticFactory.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/AbstractDiagnosticFactory.java @@ -16,41 +16,21 @@ package org.jetbrains.jet.lang.diagnostics; -import com.intellij.openapi.util.TextRange; -import com.intellij.psi.PsiFile; -import org.jetbrains.annotations.NotNull; - -import java.util.Collections; -import java.util.List; - /** * @author abreslav */ -public class AbstractDiagnosticFactory implements DiagnosticFactory { - +public class AbstractDiagnosticFactory { + private String name = null; /*package*/ void setName(String name) { this.name = name; } - @Override public String getName() { return name; } - @NotNull - @Override - public List getTextRanges(@NotNull Diagnostic diagnostic) { - return Collections.singletonList(((DiagnosticWithTextRange) diagnostic).getTextRange()); - } - - @NotNull - @Override - public PsiFile getPsiFile(@NotNull Diagnostic diagnostic) { - return ((DiagnosticWithTextRange) diagnostic).getPsiFile(); - } - @Override public String toString() { return getName(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/AmbiguousDescriptorDiagnosticFactory.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/AmbiguousDescriptorDiagnosticFactory.java index 13f082abdb0..57cf016fdb4 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/AmbiguousDescriptorDiagnosticFactory.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/AmbiguousDescriptorDiagnosticFactory.java @@ -16,7 +16,9 @@ package org.jetbrains.jet.lang.diagnostics; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.resolve.calls.ResolvedCall; import org.jetbrains.jet.resolve.DescriptorRenderer; @@ -24,23 +26,27 @@ import org.jetbrains.jet.resolve.DescriptorRenderer; import java.util.Collection; /** -* @author abreslav -*/ -public class AmbiguousDescriptorDiagnosticFactory extends ParameterizedDiagnosticFactory1>> { + * @author abreslav + */ +public class AmbiguousDescriptorDiagnosticFactory extends DiagnosticFactory1>> { public static AmbiguousDescriptorDiagnosticFactory create(String messageTemplate) { return new AmbiguousDescriptorDiagnosticFactory(messageTemplate); } public AmbiguousDescriptorDiagnosticFactory(String messageTemplate) { - super(Severity.ERROR, messageTemplate); + super(Severity.ERROR, messageTemplate, PositioningStrategies.DEFAULT, AMBIGUOUS_DESCRIPTOR_RENDERER); } - @Override - protected String makeMessageFor(@NotNull Collection> argument) { - StringBuilder stringBuilder = new StringBuilder("\n"); - for (ResolvedCall call : argument) { - stringBuilder.append(DescriptorRenderer.TEXT.render(call.getResultingDescriptor())).append("\n"); + private static Renderer>> AMBIGUOUS_DESCRIPTOR_RENDERER = + new Renderer>>() { + @NotNull + @Override + public String render(@Nullable Collection> argument) { + StringBuilder stringBuilder = new StringBuilder("\n"); + for (ResolvedCall call : argument) { + stringBuilder.append(DescriptorRenderer.TEXT.render(call.getResultingDescriptor())).append("\n"); + } + return stringBuilder.toString(); } - return stringBuilder.toString(); - } + }; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Diagnostic.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Diagnostic.java index d38a42cb9ef..0aa0a399cf6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Diagnostic.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Diagnostic.java @@ -16,19 +16,33 @@ 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 java.util.List; + /** -* @author abreslav -*/ -public interface Diagnostic { + * @author abreslav + */ +public interface Diagnostic {//todo @NotNull - DiagnosticFactory getFactory(); + AbstractDiagnosticFactory getFactory(); @NotNull String getMessage(); @NotNull Severity getSeverity(); + + @NotNull + E getPsiElement(); + + @NotNull + List getTextRanges(); + + @NotNull + PsiFile getPsiFile(); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactory.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactory.java index 6ea4e673a78..a27ef4576c7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactory.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactory.java @@ -16,22 +16,30 @@ 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 java.util.List; - /** -* @author abreslav -*/ -public interface DiagnosticFactory { - @NotNull - List getTextRanges(@NotNull Diagnostic diagnostic); + * @author svtk + */ +public class DiagnosticFactory

extends DiagnosticFactoryWithPsiElement

{ + protected final String message; + + protected DiagnosticFactory(Severity severity, String message, PositioningStrategy positioningStrategy) { + super(severity, positioningStrategy); + this.message = message; + } + + public static DiagnosticFactory create(Severity severity, String message) { + return create(severity, message, PositioningStrategies.DEFAULT); + } + + public static DiagnosticFactory create(Severity severity, String message, PositioningStrategy positioningStrategy) { + return new DiagnosticFactory(severity, message, positioningStrategy); + } @NotNull - PsiFile getPsiFile(@NotNull Diagnostic diagnostic); - - @NotNull - String getName(); -} + public Diagnostic

on(@NotNull P element) { + return new DiagnosticWithPsiElement

(element, this, severity, message); + } +} \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactory1.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactory1.java new file mode 100644 index 00000000000..0c29562cfb8 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactory1.java @@ -0,0 +1,61 @@ +/* + * Copyright 2010-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.diagnostics; + +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; + +/** + * @author svtk + */ +public class DiagnosticFactory1

extends DiagnosticFactoryWithMessageFormat

{ + private final Renderer renderer; + + protected String makeMessage(@NotNull A argument) { + return messageFormat.format(new Object[]{makeMessageFor(argument)}); + } + + protected String makeMessageFor(@NotNull A argument) { + return renderer.render(argument); + } + + @NotNull + public DiagnosticWithPsiElement

on(@NotNull P element, @NotNull A argument) { + return new DiagnosticWithPsiElement

(element, this, severity, makeMessage(argument)); + } + + protected DiagnosticFactory1(Severity severity, String message, PositioningStrategy positioningStrategy, Renderer renderer) { + super(severity, message, positioningStrategy); + this.renderer = renderer; + } + + public static DiagnosticFactory1 create(Severity severity, String message, PositioningStrategy positioningStrategy, Renderer renderer) { + return new DiagnosticFactory1(severity, message, positioningStrategy, renderer); + } + + public static DiagnosticFactory1 create(Severity severity, String message, PositioningStrategy positioningStrategy) { + return create(severity, message, positioningStrategy, Renderers.TO_STRING); + } + + public static DiagnosticFactory1 create(Severity severity, String message, Renderer renderer) { + return create(severity, message, PositioningStrategies.DEFAULT, renderer); + } + + public static DiagnosticFactory1 create(Severity severity, String message) { + return create(severity, message, PositioningStrategies.DEFAULT, Renderers.TO_STRING); + } +} \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactory2.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactory2.java new file mode 100644 index 00000000000..3dfc7b23b2f --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactory2.java @@ -0,0 +1,69 @@ +/* + * Copyright 2010-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.diagnostics; + +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; + +/** + * @author abreslav + */ +public class DiagnosticFactory2

extends DiagnosticFactoryWithMessageFormat

{ + private final Renderer rendererForA; + private final Renderer rendererForB; + + private String makeMessage(@NotNull A a, @NotNull B b) { + return messageFormat.format(new Object[] {makeMessageForA(a), makeMessageForB(b)}); + } + + private String makeMessageForA(@NotNull A a) { + return rendererForA.render(a); + } + + private String makeMessageForB(@NotNull B b) { + return rendererForB.render(b); + } + + @NotNull + public Diagnostic

on(@NotNull P element, @NotNull A a, @NotNull B b) { + return new DiagnosticWithPsiElement

(element, this, severity, makeMessage(a, b)); + } + + + private DiagnosticFactory2(Severity severity, String message, PositioningStrategy positioningStrategy, Renderer rendererForA, Renderer rendererForB) { + super(severity, message, positioningStrategy); + this.rendererForA = rendererForA; + this.rendererForB = rendererForB; + } + + public static DiagnosticFactory2 create(Severity severity, String messageStub, PositioningStrategy positioningStrategy, Renderer rendererForA, Renderer rendererForB) { + return new DiagnosticFactory2(severity, messageStub, positioningStrategy, rendererForA, rendererForB); + } + + public static DiagnosticFactory2 create(Severity severity, String messageStub, PositioningStrategy positioningStrategy) { + return new DiagnosticFactory2(severity, messageStub, positioningStrategy, Renderers.TO_STRING, Renderers.TO_STRING); + } + + public static DiagnosticFactory2 create(Severity severity, String messageStub, Renderer rendererForA, Renderer rendererForB) { + return new DiagnosticFactory2(severity, messageStub, PositioningStrategies.DEFAULT, rendererForA, rendererForB); + } + + public static DiagnosticFactory2 create(Severity severity, String messageStub) { + return new DiagnosticFactory2(severity, messageStub, PositioningStrategies.DEFAULT, Renderers.TO_STRING, Renderers.TO_STRING); + } + +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactory3.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactory3.java new file mode 100644 index 00000000000..92c46568cc2 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactory3.java @@ -0,0 +1,72 @@ +/* + * Copyright 2010-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.diagnostics; + +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; + +/** + * @author svtk + */ +public class DiagnosticFactory3

extends DiagnosticFactoryWithMessageFormat

{ + private final Renderer rendererForA; + private final Renderer rendererForB; + private final Renderer rendererForC; + + protected DiagnosticFactory3(Severity severity, String messageStub, PositioningStrategy positioningStrategy, Renderer rendererForA, Renderer rendererForB, Renderer rendererForC) { + super(severity, messageStub, positioningStrategy); + this.rendererForA = rendererForA; + this.rendererForB = rendererForB; + this.rendererForC = rendererForC; + } + + public static DiagnosticFactory3 create(Severity severity, String messageStub) { + return create(severity, messageStub, PositioningStrategies.DEFAULT); + } + + public static DiagnosticFactory3 create(Severity severity, String messageStub, PositioningStrategy positioningStrategy) { + return create(severity, messageStub, positioningStrategy, Renderers.TO_STRING, Renderers.TO_STRING, Renderers.TO_STRING); + } + + public static DiagnosticFactory3 create(Severity severity, String messageStub, Renderer rendererForA, Renderer rendererForB, Renderer rendererForC) { + return create(severity, messageStub, PositioningStrategies.DEFAULT, rendererForA, rendererForB, rendererForC); + } + + public static DiagnosticFactory3 create(Severity severity, String messageStub, PositioningStrategy positioningStrategy, Renderer rendererForA, Renderer rendererForB, Renderer rendererForC) { + return new DiagnosticFactory3(severity, messageStub, positioningStrategy, rendererForA, rendererForB, rendererForC); + } + + private String makeMessage(@NotNull A a, @NotNull B b, @NotNull C c) { + return messageFormat.format(new Object[]{makeMessageForA(a), makeMessageForB(b), makeMessageForC(c)}); + } + + private String makeMessageForA(@NotNull A a) { + return rendererForA.render(a); + } + + private String makeMessageForB(@NotNull B b) { + return rendererForB.render(b); + } + + private String makeMessageForC(@NotNull C c) { + return rendererForC.render(c); + } + @NotNull + public DiagnosticWithPsiElement

on(@NotNull P element, @NotNull A a, @NotNull B b, @NotNull C c) { + return new DiagnosticWithPsiElement

(element, this, severity, makeMessage(a, b, c)); + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithMessageFormat.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithMessageFormat.java index ec1e7d89030..67cd381b850 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithMessageFormat.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithMessageFormat.java @@ -16,23 +16,22 @@ package org.jetbrains.jet.lang.diagnostics; +import com.intellij.psi.PsiElement; + import java.text.MessageFormat; /** * @author abreslav */ -public abstract class DiagnosticFactoryWithMessageFormat extends DiagnosticFactoryWithSeverity { +public abstract class DiagnosticFactoryWithMessageFormat

extends DiagnosticFactoryWithPsiElement

{ protected final MessageFormat messageFormat; - protected final Renderer renderer; public DiagnosticFactoryWithMessageFormat(Severity severity, String message) { - this(severity, message, Renderer.TO_STRING); + this(severity, message, PositioningStrategies.DEFAULT); } - - public DiagnosticFactoryWithMessageFormat(Severity severity, String message, Renderer renderer) { - super(severity); + + public DiagnosticFactoryWithMessageFormat(Severity severity, String message, PositioningStrategy positioningStrategy) { + super(severity, positioningStrategy); this.messageFormat = new MessageFormat(message); - this.renderer = renderer; } - } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithSeverity.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement.java similarity index 55% rename from compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithSeverity.java rename to compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement.java index da3e7e0aa6e..8d304b48266 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithSeverity.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement.java @@ -16,14 +16,24 @@ package org.jetbrains.jet.lang.diagnostics; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; + +import java.util.List; + /** * @author abreslav */ -public abstract class DiagnosticFactoryWithSeverity extends AbstractDiagnosticFactory { +public abstract class DiagnosticFactoryWithPsiElement

extends AbstractDiagnosticFactory { protected final Severity severity; + protected final PositioningStrategy positioningStrategy; - public DiagnosticFactoryWithSeverity(Severity severity) { + public DiagnosticFactoryWithPsiElement(Severity severity, PositioningStrategy positioningStrategy) { this.severity = severity; + this.positioningStrategy = positioningStrategy; } + protected List getTextRanges(Diagnostic

diagnostic) { + return positioningStrategy.mark(diagnostic.getPsiElement()); + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement1.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement1.java deleted file mode 100644 index c22241cbf74..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement1.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2010-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.jet.lang.diagnostics; - -import com.intellij.lang.ASTNode; -import com.intellij.openapi.util.TextRange; -import com.intellij.psi.PsiElement; -import org.jetbrains.annotations.NotNull; - -/** - * @author svtk - */ -public abstract class DiagnosticFactoryWithPsiElement1 extends DiagnosticFactoryWithMessageFormat { - - protected DiagnosticFactoryWithPsiElement1(Severity severity, String message, Renderer renderer) { - super(severity, message, renderer); - } - - protected DiagnosticFactoryWithPsiElement1(Severity severity, String message) { - super(severity, message); - } - - protected String makeMessage(@NotNull A argument) { - return messageFormat.format(new Object[]{makeMessageFor(argument)}); - } - - protected String makeMessageFor(A argument) { - return renderer.render(argument); - } - - @NotNull - public DiagnosticWithPsiElement on(@NotNull T elementToMark, @NotNull A argument) { - return on(elementToMark, elementToMark.getTextRange(), argument); - } - - @NotNull - public DiagnosticWithPsiElement on(@NotNull T elementToBlame, @NotNull ASTNode nodeToMark, @NotNull A argument) { - return on(elementToBlame, nodeToMark.getTextRange(), argument); - } - - @NotNull - public DiagnosticWithPsiElement on(@NotNull T elementToBlame, @NotNull PsiElement elementToMark, @NotNull A argument) { - return on(elementToBlame, elementToMark.getTextRange(), argument); - } - - @NotNull - protected DiagnosticWithPsiElement on(@NotNull T elementToBlame, @NotNull TextRange textRangeToMark, @NotNull A argument) { - return new DiagnosticWithPsiElementImpl(this, severity, makeMessage(argument), elementToBlame, textRangeToMark); - } -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement2.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement2.java deleted file mode 100644 index c8f098a9437..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement2.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2010-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.jet.lang.diagnostics; - -import com.intellij.lang.ASTNode; -import com.intellij.psi.PsiElement; -import org.jetbrains.annotations.NotNull; - -/** - * @author abreslav - */ -public abstract class DiagnosticFactoryWithPsiElement2 extends DiagnosticFactoryWithMessageFormat { - - protected DiagnosticFactoryWithPsiElement2(Severity severity, String message, Renderer renderer) { - super(severity, message, renderer); - } - - protected DiagnosticFactoryWithPsiElement2(Severity severity, String message) { - super(severity, message); - } - - protected String makeMessage(@NotNull A a, @NotNull B b) { - return messageFormat.format(new Object[] {makeMessageForA(a), makeMessageForB(b)}); - } - - protected String makeMessageForA(@NotNull A a) { - return renderer.render(a); - } - - protected String makeMessageForB(@NotNull B b) { - return renderer.render(b); - } - - @NotNull - public DiagnosticWithPsiElement on(@NotNull T elementToMark, @NotNull A a, @NotNull B b) { - return on(elementToMark, elementToMark.getNode(), a, b); - } - - @NotNull - public DiagnosticWithPsiElement on(@NotNull T elementToBlame, @NotNull ASTNode nodeToMark, @NotNull A a, @NotNull B b) { - return makeDiagnostic(new DiagnosticWithPsiElementImpl(this, severity, makeMessage(a, b), elementToBlame, nodeToMark.getTextRange())); - } - - public DiagnosticWithPsiElement makeDiagnostic(DiagnosticWithPsiElement diagnostic) { - return diagnostic; - } -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement3.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement3.java deleted file mode 100644 index 7f97962f4d5..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement3.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2010-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.jet.lang.diagnostics; - -import com.intellij.lang.ASTNode; -import com.intellij.openapi.util.TextRange; -import com.intellij.psi.PsiElement; -import org.jetbrains.annotations.NotNull; - -/** - * @author svtk - */ -public abstract class DiagnosticFactoryWithPsiElement3 extends DiagnosticFactoryWithMessageFormat { - protected DiagnosticFactoryWithPsiElement3(Severity severity, String messageStub, Renderer renderer) { - super(severity, messageStub, renderer); - } - - protected DiagnosticFactoryWithPsiElement3(Severity severity, String message) { - super(severity, message); - } - - protected String makeMessage(@NotNull A a, @NotNull B b, @NotNull C c) { - return messageFormat.format(new Object[]{makeMessageForA(a), makeMessageForB(b), makeMessageForC(c)}); - } - - protected String makeMessageForA(@NotNull A a) { - return renderer.render(a); - } - - protected String makeMessageForB(@NotNull B b) { - return renderer.render(b); - } - - protected String makeMessageForC(@NotNull C c) { - return renderer.render(c); - } - - @NotNull - public DiagnosticWithPsiElement on(@NotNull T elementToMark, @NotNull A a, @NotNull B b, @NotNull C c) { - return on(elementToMark, elementToMark, a, b, c); - } - - @NotNull - public DiagnosticWithPsiElement on(@NotNull T elementToBlame, @NotNull PsiElement elementToMark, @NotNull A a, @NotNull B b, @NotNull C c) { - return on(elementToBlame, elementToMark.getTextRange(), a, b, c); - } - - @NotNull - public DiagnosticWithPsiElement on(@NotNull T elementToBlame, @NotNull ASTNode nodeToMark, @NotNull A a, @NotNull B b, @NotNull C c) { - return on(elementToBlame, nodeToMark.getTextRange(), a, b, c); - } - - @NotNull - protected DiagnosticWithPsiElement on(@NotNull T elementToBlame, @NotNull TextRange textRangeToMark, @NotNull A a, @NotNull B b, @NotNull C c) { - return new DiagnosticWithPsiElementImpl(this, severity, makeMessage(a, b, c), elementToBlame, textRangeToMark); - } - -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticHolder.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticHolder.java index 58638553197..f0c110e14bd 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticHolder.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticHolder.java @@ -17,6 +17,7 @@ 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; @@ -35,8 +36,8 @@ public interface DiagnosticHolder { @Override public void report(@NotNull Diagnostic diagnostic) { if (diagnostic.getSeverity() == Severity.ERROR) { - PsiFile psiFile = diagnostic.getFactory().getPsiFile(diagnostic); - List textRanges = diagnostic.getFactory().getTextRanges(diagnostic); + PsiFile psiFile = diagnostic.getPsiFile(); + List textRanges = diagnostic.getTextRanges(); throw new IllegalStateException(diagnostic.getMessage() + DiagnosticUtils.atLocation(psiFile, textRanges.get(0))); } } 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 d91b8481b50..a06b0c9a3a0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticUtils.java @@ -84,10 +84,10 @@ public class DiagnosticUtils { } } - public static String formatPosition(Diagnostic diagnostic) { - PsiFile file = diagnostic.getFactory().getPsiFile(diagnostic); + public static String formatPosition(Diagnostic diagnostic) { + PsiFile file = diagnostic.getPsiFile(); Document document = file.getViewProvider().getDocument(); - TextRange firstRange = diagnostic.getFactory().getTextRanges(diagnostic).iterator().next(); + TextRange firstRange = diagnostic.getTextRanges().iterator().next(); int offset = firstRange.getStartOffset(); if (document != null) { int lineNumber = document.getLineNumber(offset); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithParameterFactory.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithParameterFactory.java deleted file mode 100644 index 2c968e2b12f..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithParameterFactory.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2010-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.jet.lang.diagnostics; - -import com.intellij.openapi.util.TextRange; -import com.intellij.psi.PsiElement; -import org.jetbrains.annotations.NotNull; - -/** - * @author svtk - */ -public class DiagnosticWithParameterFactory extends PsiElementOnlyDiagnosticFactory1 { - public static DiagnosticWithParameterFactory create(Severity severity, String messageStub, DiagnosticParameter diagnosticParameter) { - return new DiagnosticWithParameterFactory(severity, messageStub, diagnosticParameter); - } - - private final DiagnosticParameter diagnosticParameter; - - protected DiagnosticWithParameterFactory(Severity severity, String message, DiagnosticParameter diagnosticParameter) { - super(severity, message); - this.diagnosticParameter = diagnosticParameter; - } - - @NotNull - @Override - protected DiagnosticWithPsiElement on(@NotNull T elementToBlame, @NotNull TextRange textRangeToMark, @NotNull A argument) { - return super.on(elementToBlame, textRangeToMark, argument).add(diagnosticParameter, argument); - } -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithParameters.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithParameters.java deleted file mode 100644 index a92e868e33e..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithParameters.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2010-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.jet.lang.diagnostics; - -import com.google.common.collect.Maps; -import com.intellij.psi.PsiElement; - -import java.util.Map; - -/** - * @author svtk - */ -public class DiagnosticWithParameters extends DiagnosticWithPsiElementImpl { - - private final Map map = Maps.newHashMap(); - - public DiagnosticWithParameters(DiagnosticWithPsiElement diagnostic) { - super(diagnostic.getFactory(), diagnostic.getSeverity(), diagnostic.getMessage(), diagnostic.getPsiElement(), diagnostic.getTextRange()); - } - - @Override - public

DiagnosticWithPsiElement add(DiagnosticParameter

parameterType, P parameter) { - map.put(parameterType, parameter); - return this; - } - - public

P getParameter(DiagnosticParameter

parameterType) { - return (P) map.get(parameterType); - } - - public

boolean hasParameter(DiagnosticParameter

parameterType) { - return getParameter(parameterType) != null; - } -} 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 41ec665c12a..45aeb8f45f9 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithPsiElement.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithPsiElement.java @@ -16,15 +16,28 @@ package org.jetbrains.jet.lang.diagnostics; +import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; -/** - * @author abreslav - */ -public interface DiagnosticWithPsiElement extends DiagnosticWithTextRange { - @NotNull - T getPsiElement(); +import java.util.List; -

DiagnosticWithPsiElement add(DiagnosticParameter

parameterType, P parameter); +/** + * @author svtk + */ +public class DiagnosticWithPsiElement

extends AbstractDiagnostic

{ + public DiagnosticWithPsiElement(@NotNull P psiElement, @NotNull DiagnosticFactoryWithPsiElement

factory, @NotNull Severity severity, @NotNull String message) { + super(psiElement, factory, severity, message); + } + + @NotNull + @Override + public DiagnosticFactoryWithPsiElement

getFactory() { + return (DiagnosticFactoryWithPsiElement

)super.getFactory(); + } + + @NotNull + public List getTextRanges() { + return getFactory().getTextRanges(this); + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithPsiElementImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithPsiElementImpl.java deleted file mode 100644 index d9334b4b7ba..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithPsiElementImpl.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2010-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.jet.lang.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; - } - - @Override - public

DiagnosticWithPsiElement add(DiagnosticParameter

parameterType, P parameter) { - return (new DiagnosticWithParameters(this)).add(parameterType, parameter); - } -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithTextRange.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithTextRange.java deleted file mode 100644 index 01e6080fb32..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithTextRange.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2010-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.jet.lang.diagnostics; - -import com.intellij.openapi.util.TextRange; -import com.intellij.psi.PsiFile; -import org.jetbrains.annotations.NotNull; - -/** - * @author abreslav - */ -public interface DiagnosticWithTextRange extends Diagnostic { - @NotNull - TextRange getTextRange(); - - @NotNull - PsiFile getPsiFile(); - -} 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 fe4144bf623..4e3faeac91b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -16,9 +16,9 @@ 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.PsiNameIdentifierOwner; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; @@ -26,475 +26,430 @@ import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.calls.inference.SolutionStatus; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lexer.JetKeywordToken; +import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.resolve.DescriptorRenderer; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.Collection; -import java.util.Collections; import java.util.Iterator; import java.util.List; import static org.jetbrains.jet.lang.diagnostics.Severity.ERROR; import static org.jetbrains.jet.lang.diagnostics.Severity.WARNING; +import static org.jetbrains.jet.lang.diagnostics.Renderers.*; + /** * @author abreslav */ public interface Errors { - Renderer NAME = new Renderer() { + DiagnosticFactory1 EXCEPTION_WHILE_ANALYZING = DiagnosticFactory1.create(ERROR, "{0}", new Renderer() { @NotNull @Override - public String render(@Nullable Object object) { - if (object == null) return "null"; - if (object instanceof Named) { - return ((Named) object).getName(); - } - return object.toString(); - } - }; - - ParameterizedDiagnosticFactory1 EXCEPTION_WHILE_ANALYZING = new ParameterizedDiagnosticFactory1(ERROR, "{0}") { - @Override - protected String makeMessageFor(@NotNull Throwable e) { + public String render(@Nullable Throwable e) { return e.getClass().getSimpleName() + ": " + e.getMessage(); } - }; + }); - UnresolvedReferenceDiagnosticFactory UNRESOLVED_REFERENCE = new UnresolvedReferenceDiagnosticFactory("Unresolved reference"); + UnresolvedReferenceDiagnosticFactory UNRESOLVED_REFERENCE = UnresolvedReferenceDiagnosticFactory.create("Unresolved reference"); RedeclarationDiagnosticFactory REDECLARATION = RedeclarationDiagnosticFactory.REDECLARATION; RedeclarationDiagnosticFactory NAME_SHADOWING = RedeclarationDiagnosticFactory.NAME_SHADOWING; - PsiElementOnlyDiagnosticFactory2 TYPE_MISMATCH = PsiElementOnlyDiagnosticFactory2.create(ERROR, "Type mismatch: inferred type is {1} but {0} was expected"); - ParameterizedDiagnosticFactory1> INCOMPATIBLE_MODIFIERS = new ParameterizedDiagnosticFactory1>(ERROR, "Incompatible modifiers: ''{0}''") { - @Override - protected String makeMessageFor(Collection argument) { - StringBuilder sb = new StringBuilder(); - for (Iterator iterator = argument.iterator(); iterator.hasNext(); ) { - JetKeywordToken modifier = iterator.next(); - sb.append(modifier.getValue()); - if (iterator.hasNext()) { - sb.append(" "); - } - } - return sb.toString(); - } - }; - DiagnosticWithParameterFactory ILLEGAL_MODIFIER = DiagnosticWithParameterFactory.create(ERROR, "Illegal modifier ''{0}''", DiagnosticParameters.MODIFIER); + DiagnosticFactory2 TYPE_MISMATCH = DiagnosticFactory2.create(ERROR, "Type mismatch: inferred type is {1} but {0} was expected"); + DiagnosticFactory1> INCOMPATIBLE_MODIFIERS = + DiagnosticFactory1.create(ERROR, "Incompatible modifiers: ''{0}''", + new Renderer>() { + @NotNull + @Override + public String render(@Nullable Collection element) { + assert element != null; + StringBuilder sb = new StringBuilder(); + for (Iterator iterator = element.iterator(); iterator.hasNext(); ) { + JetKeywordToken modifier = iterator.next(); + sb.append(modifier.getValue()); + if (iterator.hasNext()) { + sb.append(" "); + } + } + return sb.toString(); + } + }); + DiagnosticFactory1 ILLEGAL_MODIFIER = DiagnosticFactory1.create(ERROR, "Illegal modifier ''{0}''"); - PsiElementOnlyDiagnosticFactory2 REDUNDANT_MODIFIER = new PsiElementOnlyDiagnosticFactory2(Severity.WARNING, "Modifier {0} is redundant because {1} is present") { + DiagnosticFactory2 REDUNDANT_MODIFIER = DiagnosticFactory2.create(Severity.WARNING, "Modifier {0} is redundant because {1} is present"); + DiagnosticFactory ABSTRACT_MODIFIER_IN_TRAIT = DiagnosticFactory.create(WARNING, "Modifier ''{0}'' is redundant in trait", PositioningStrategies.POSITION_ABSTRACT_MODIFIER); + DiagnosticFactory OPEN_MODIFIER_IN_TRAIT = DiagnosticFactory.create(WARNING, "Modifier ''{0}'' is redundant in trait", PositioningStrategies.positionModifier(JetTokens.OPEN_KEYWORD)); + DiagnosticFactory REDUNDANT_MODIFIER_IN_GETTER = DiagnosticFactory.create(WARNING, "Visibility modifiers are redundant in getter"); + DiagnosticFactory TRAIT_CAN_NOT_BE_FINAL = DiagnosticFactory.create(ERROR, "Trait can not be final"); + DiagnosticFactory TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM = DiagnosticFactory.create(ERROR, "Type checking has run into a recursive problem. Easiest workaround: specify types of your declarations explicitly"); // TODO: message + DiagnosticFactory RETURN_NOT_ALLOWED = DiagnosticFactory.create(ERROR, "'return' is not allowed here"); + DiagnosticFactory PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE = DiagnosticFactory.create(ERROR, "Projections are not allowed for immediate arguments of a supertype", new PositioningStrategy() { @NotNull @Override - public DiagnosticWithPsiElement on(@NotNull JetModifierList elementToBlame, @NotNull ASTNode nodeToMark, @NotNull JetKeywordToken redundantModifier, @NotNull JetKeywordToken presentModifier) { - return super.on(elementToBlame, nodeToMark, redundantModifier, presentModifier).add(DiagnosticParameters.MODIFIER, redundantModifier); + public List mark(@NotNull JetTypeProjection element) { + return markNode(element.getProjectionNode()); } - }; - DiagnosticWithParameterFactory REDUNDANT_MODIFIER_IN_TRAIT = DiagnosticWithParameterFactory.create(WARNING, "Modifier ''{0}'' is redundant in trait", DiagnosticParameters.MODIFIER); - DiagnosticWithParameterFactory REDUNDANT_MODIFIER_IN_GETTER = DiagnosticWithParameterFactory.create(WARNING, "Visibility modifiers are redundant in getter", DiagnosticParameters.MODIFIER); - SimplePsiElementOnlyDiagnosticFactory TRAIT_CAN_NOT_BE_FINAL = SimplePsiElementOnlyDiagnosticFactory.create(ERROR, "Trait can not be final"); - SimpleDiagnosticFactory SAFE_CALLS_ARE_NOT_ALLOWED_ON_NAMESPACES = SimpleDiagnosticFactory.create(ERROR, "Safe calls are not allowed on namespaces"); - SimpleDiagnosticFactory TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM = SimpleDiagnosticFactory.create(ERROR, "Type checking has run into a recursive problem. Easiest workaround: specify types of your declarations explicitly"); // TODO: message - SimpleDiagnosticFactory RETURN_NOT_ALLOWED = SimpleDiagnosticFactory.create(ERROR, "'return' is not allowed here"); - SimpleDiagnosticFactory PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE = SimpleDiagnosticFactory.create(ERROR, "Projections are not allowed for immediate arguments of a supertype"); - SimpleDiagnosticFactory LABEL_NAME_CLASH = SimpleDiagnosticFactory.create(WARNING, "There is more than one label with such a name in this scope"); - SimpleDiagnosticFactory EXPRESSION_EXPECTED_NAMESPACE_FOUND = SimpleDiagnosticFactory.create(ERROR, "Expression expected, but a namespace name found"); + }); + DiagnosticFactory LABEL_NAME_CLASH = DiagnosticFactory.create(WARNING, "There is more than one label with such a name in this scope"); + DiagnosticFactory EXPRESSION_EXPECTED_NAMESPACE_FOUND = DiagnosticFactory.create(ERROR, "Expression expected, but a namespace name found"); - ParameterizedDiagnosticFactory1 CANNOT_IMPORT_FROM_ELEMENT = ParameterizedDiagnosticFactory1.create(ERROR, "Cannot import from ''{0}''", NAME); - ParameterizedDiagnosticFactory1 CANNOT_BE_IMPORTED = ParameterizedDiagnosticFactory1.create(ERROR, "Cannot import ''{0}'', functions and properties can be imported only from packages", NAME); - SimpleDiagnosticFactory USELESS_HIDDEN_IMPORT = SimpleDiagnosticFactory.create(WARNING, "Useless import, it is hidden further"); - SimpleDiagnosticFactory USELESS_SIMPLE_IMPORT = SimpleDiagnosticFactory.create(WARNING, "Useless import, does nothing"); + DiagnosticFactory1 CANNOT_IMPORT_FROM_ELEMENT = DiagnosticFactory1.create(ERROR, "Cannot import from ''{0}''", NAME); + DiagnosticFactory1 CANNOT_BE_IMPORTED = DiagnosticFactory1.create(ERROR, "Cannot import ''{0}'', functions and properties can be imported only from packages", NAME); + DiagnosticFactory USELESS_HIDDEN_IMPORT = DiagnosticFactory.create(WARNING, "Useless import, it is hidden further"); + DiagnosticFactory USELESS_SIMPLE_IMPORT = DiagnosticFactory.create(WARNING, "Useless import, does nothing"); - SimpleDiagnosticFactory CANNOT_INFER_PARAMETER_TYPE = SimpleDiagnosticFactory.create(ERROR, "Cannot infer a type for this parameter. To specify it explicitly use the {(p : Type) => ...} notation"); + DiagnosticFactory CANNOT_INFER_PARAMETER_TYPE = DiagnosticFactory.create(ERROR, "Cannot infer a type for this parameter. To specify it explicitly use the {(p : Type) => ...} notation"); - SimpleDiagnosticFactory NO_BACKING_FIELD_ABSTRACT_PROPERTY = SimpleDiagnosticFactory.create(ERROR, "This property doesn't have a backing field, because it's abstract"); - SimpleDiagnosticFactory NO_BACKING_FIELD_CUSTOM_ACCESSORS = SimpleDiagnosticFactory.create(ERROR, "This property doesn't have a backing field, because it has custom accessors without reference to the backing field"); - SimpleDiagnosticFactory INACCESSIBLE_BACKING_FIELD = SimpleDiagnosticFactory.create(ERROR, "The backing field is not accessible here"); - SimpleDiagnosticFactory NOT_PROPERTY_BACKING_FIELD = SimpleDiagnosticFactory.create(ERROR, "The referenced variable is not a property and doesn't have backing field"); + DiagnosticFactory NO_BACKING_FIELD_ABSTRACT_PROPERTY = DiagnosticFactory.create(ERROR, "This property doesn't have a backing field, because it's abstract"); + DiagnosticFactory NO_BACKING_FIELD_CUSTOM_ACCESSORS = DiagnosticFactory.create(ERROR, "This property doesn't have a backing field, because it has custom accessors without reference to the backing field"); + DiagnosticFactory INACCESSIBLE_BACKING_FIELD = DiagnosticFactory.create(ERROR, "The backing field is not accessible here"); + DiagnosticFactory NOT_PROPERTY_BACKING_FIELD = DiagnosticFactory.create(ERROR, "The referenced variable is not a property and doesn't have backing field"); - SimpleDiagnosticFactory MIXING_NAMED_AND_POSITIONED_ARGUMENTS = SimpleDiagnosticFactory.create(ERROR, "Mixing named and positioned arguments in not allowed"); - SimpleDiagnosticFactory ARGUMENT_PASSED_TWICE = SimpleDiagnosticFactory.create(ERROR, "An argument is already passed for this parameter"); - UnresolvedReferenceDiagnosticFactory NAMED_PARAMETER_NOT_FOUND = new UnresolvedReferenceDiagnosticFactory("Cannot find a parameter with this name");//SimpleDiagnosticFactory.create(ERROR, "Cannot find a parameter with this name"); - SimpleDiagnosticFactory VARARG_OUTSIDE_PARENTHESES = SimpleDiagnosticFactory.create(ERROR, "Passing value as a vararg is only allowed inside a parenthesized argument list"); + DiagnosticFactory MIXING_NAMED_AND_POSITIONED_ARGUMENTS = DiagnosticFactory.create(ERROR, "Mixing named and positioned arguments in not allowed"); + DiagnosticFactory ARGUMENT_PASSED_TWICE = DiagnosticFactory.create(ERROR, "An argument is already passed for this parameter"); + UnresolvedReferenceDiagnosticFactory NAMED_PARAMETER_NOT_FOUND = UnresolvedReferenceDiagnosticFactory.create("Cannot find a parameter with this name"); + DiagnosticFactory VARARG_OUTSIDE_PARENTHESES = DiagnosticFactory.create(ERROR, "Passing value as a vararg is only allowed inside a parenthesized argument list"); - SimpleDiagnosticFactory MANY_FUNCTION_LITERAL_ARGUMENTS = SimpleDiagnosticFactory.create(ERROR, "Only one function literal is allowed outside a parenthesized argument list"); - SimpleDiagnosticFactory PROPERTY_WITH_NO_TYPE_NO_INITIALIZER = SimpleDiagnosticFactory.create(ERROR, "This property must either have a type annotation or be initialized"); + DiagnosticFactory MANY_FUNCTION_LITERAL_ARGUMENTS = DiagnosticFactory.create(ERROR, "Only one function literal is allowed outside a parenthesized argument list"); + DiagnosticFactory PROPERTY_WITH_NO_TYPE_NO_INITIALIZER = DiagnosticFactory.create(ERROR, "This property must either have a type annotation or be initialized"); - SimpleDiagnosticFactory FUNCTION_WITH_NO_TYPE_NO_BODY = SimpleDiagnosticFactory.create(ERROR, "This function must either declare a return type or have a body element"); - SimplePsiElementOnlyDiagnosticFactory ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS = SimplePsiElementOnlyDiagnosticFactory.create(ERROR, "This property cannot be declared abstract"); - SimplePsiElementOnlyDiagnosticFactory ABSTRACT_PROPERTY_NOT_IN_CLASS = SimplePsiElementOnlyDiagnosticFactory.create(ERROR, "A property may be abstract only when defined in a class or trait"); - DiagnosticWithParameterFactory ABSTRACT_PROPERTY_WITH_INITIALIZER = DiagnosticWithParameterFactory.create(ERROR, "Property with initializer cannot be abstract", DiagnosticParameters.TYPE); - DiagnosticWithParameterFactory ABSTRACT_PROPERTY_WITH_GETTER = DiagnosticWithParameterFactory.create(ERROR, "Property with getter implementation cannot be abstract", DiagnosticParameters.TYPE); - DiagnosticWithParameterFactory ABSTRACT_PROPERTY_WITH_SETTER = DiagnosticWithParameterFactory.create(ERROR, "Property with setter implementation cannot be abstract", DiagnosticParameters.TYPE); + DiagnosticFactory FUNCTION_WITH_NO_TYPE_NO_BODY = DiagnosticFactory.create(ERROR, "This function must either declare a return type or have a body element"); + DiagnosticFactory ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS = DiagnosticFactory.create(ERROR, "This property cannot be declared abstract", PositioningStrategies.POSITION_ABSTRACT_MODIFIER); + DiagnosticFactory ABSTRACT_PROPERTY_NOT_IN_CLASS = DiagnosticFactory.create(ERROR, "A property may be abstract only when defined in a class or trait", PositioningStrategies.POSITION_ABSTRACT_MODIFIER); + DiagnosticFactory ABSTRACT_PROPERTY_WITH_INITIALIZER = DiagnosticFactory.create(ERROR, "Property with initializer cannot be abstract"); + DiagnosticFactory ABSTRACT_PROPERTY_WITH_GETTER = DiagnosticFactory.create(ERROR, "Property with getter implementation cannot be abstract"); + DiagnosticFactory ABSTRACT_PROPERTY_WITH_SETTER = DiagnosticFactory.create(ERROR, "Property with setter implementation cannot be abstract"); - DiagnosticWithParameterFactory GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY = DiagnosticWithParameterFactory.create(ERROR, "Getter visibility must be the same as property visibility", DiagnosticParameters.MODIFIER); - SimpleDiagnosticFactory BACKING_FIELD_IN_TRAIT = SimpleDiagnosticFactory.create(ERROR, "Property in a trait cannot have a backing field"); - SimpleDiagnosticFactory MUST_BE_INITIALIZED = SimpleDiagnosticFactory.create(ERROR, "Property must be initialized"); - SimplePsiElementOnlyDiagnosticFactory MUST_BE_INITIALIZED_OR_BE_ABSTRACT = SimplePsiElementOnlyDiagnosticFactory.create(ERROR, "Property must be initialized or be abstract"); - DiagnosticWithParameterFactory PROPERTY_INITIALIZER_IN_TRAIT = DiagnosticWithParameterFactory.create(ERROR, "Property initializers are not allowed in traits", DiagnosticParameters.TYPE); - SimpleDiagnosticFactory PROPERTY_INITIALIZER_NO_BACKING_FIELD = SimpleDiagnosticFactory.create(ERROR, "Initializer is not allowed here because this property has no backing field"); - PsiElementOnlyDiagnosticFactory3 ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS = new PsiElementOnlyDiagnosticFactory3(ERROR, "Abstract property {0} in non-abstract class {1}") { + DiagnosticFactory GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY = DiagnosticFactory.create(ERROR, "Getter visibility must be the same as property visibility"); + DiagnosticFactory BACKING_FIELD_IN_TRAIT = DiagnosticFactory.create(ERROR, "Property in a trait cannot have a backing field"); + DiagnosticFactory MUST_BE_INITIALIZED = DiagnosticFactory.create(ERROR, "Property must be initialized"); + DiagnosticFactory MUST_BE_INITIALIZED_OR_BE_ABSTRACT = DiagnosticFactory.create(ERROR, "Property must be initialized or be abstract"); + DiagnosticFactory PROPERTY_INITIALIZER_IN_TRAIT = DiagnosticFactory.create(ERROR, "Property initializers are not allowed in traits"); + DiagnosticFactory PROPERTY_INITIALIZER_NO_BACKING_FIELD = DiagnosticFactory.create(ERROR, "Initializer is not allowed here because this property has no backing field"); + DiagnosticFactory3 ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS = DiagnosticFactory3.create(ERROR, "Abstract property {0} in non-abstract class {1}", PositioningStrategies.POSITION_ABSTRACT_MODIFIER); + DiagnosticFactory3 ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS = DiagnosticFactory3.create(ERROR, "Abstract function {0} in non-abstract class {1}", PositioningStrategies.POSITION_ABSTRACT_MODIFIER); + DiagnosticFactory1 ABSTRACT_FUNCTION_WITH_BODY = DiagnosticFactory1.create(ERROR, "A function {0} with body cannot be abstract"); + DiagnosticFactory1 NON_ABSTRACT_FUNCTION_WITH_NO_BODY = DiagnosticFactory1.create(ERROR, "Method {0} without a body must be abstract", PositioningStrategies.POSITION_NAME_IDENTIFIER); + DiagnosticFactory1 NON_MEMBER_ABSTRACT_FUNCTION = DiagnosticFactory1.create(ERROR, "Function {0} is not a class or trait member and cannot be abstract", PositioningStrategies.POSITION_ABSTRACT_MODIFIER); + + DiagnosticFactory1 NON_MEMBER_FUNCTION_NO_BODY = DiagnosticFactory1.create(ERROR, "Function {0} must have a body", PositioningStrategies.POSITION_NAME_IDENTIFIER); + DiagnosticFactory NON_FINAL_MEMBER_IN_FINAL_CLASS = DiagnosticFactory.create(ERROR, "Non final member in a final class"); + + DiagnosticFactory PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE = DiagnosticFactory.create(ERROR, "Public or protected member should specify a type"); + + DiagnosticFactory PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT = DiagnosticFactory.create(ERROR, "Projections are not allowed on type arguments of functions and properties"); // TODO : better positioning + DiagnosticFactory SUPERTYPE_NOT_INITIALIZED = DiagnosticFactory.create(ERROR, "This type has a constructor, and thus must be initialized here"); + DiagnosticFactory SUPERTYPE_NOT_INITIALIZED_DEFAULT = DiagnosticFactory.create(ERROR, "Constructor invocation should be explicitly specified"); + DiagnosticFactory SECONDARY_CONSTRUCTOR_BUT_NO_PRIMARY = DiagnosticFactory.create(ERROR, "A secondary constructor may appear only in a class that has a primary constructor"); + DiagnosticFactory SECONDARY_CONSTRUCTOR_NO_INITIALIZER_LIST = DiagnosticFactory.create(ERROR, "Secondary constructors must have an initializer list"); + 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); + 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); + + 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); + + DiagnosticFactory1 UNINITIALIZED_VARIABLE = DiagnosticFactory1.create(ERROR, "Variable ''{0}'' must be initialized", NAME); + DiagnosticFactory1 UNINITIALIZED_PARAMETER = DiagnosticFactory1.create(ERROR, "Parameter ''{0}'' is uninitialized here", NAME); + UnusedElementDiagnosticFactory UNUSED_VARIABLE = UnusedElementDiagnosticFactory.create(WARNING, "Variable ''{0}'' is never used", PositioningStrategies.POSITION_NAME_IDENTIFIER, NAME); + UnusedElementDiagnosticFactory UNUSED_PARAMETER = UnusedElementDiagnosticFactory.create(WARNING, "Parameter ''{0}'' is never used", PositioningStrategies.POSITION_NAME_IDENTIFIER, NAME); + UnusedElementDiagnosticFactory ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE = UnusedElementDiagnosticFactory.create(WARNING, "Variable ''{0}'' is assigned but never accessed", PositioningStrategies.POSITION_NAME_IDENTIFIER, NAME); + DiagnosticFactory1 VARIABLE_WITH_REDUNDANT_INITIALIZER = DiagnosticFactory1.create(WARNING, "Variable ''{0}'' initializer is redundant", NAME); + DiagnosticFactory2 UNUSED_VALUE = DiagnosticFactory2.create(WARNING, "The value ''{0}'' assigned to ''{1}'' is never used", ELEMENT_TEXT, TO_STRING); + DiagnosticFactory1 UNUSED_CHANGED_VALUE = DiagnosticFactory1.create(WARNING, "The value changed at ''{0}'' is never used", ELEMENT_TEXT); + DiagnosticFactory UNUSED_EXPRESSION = DiagnosticFactory.create(WARNING, "The expression is unused"); + DiagnosticFactory UNUSED_FUNCTION_LITERAL = DiagnosticFactory.create(WARNING, "The function literal is unused. If you mean block, you can use 'run { ... }'"); + + DiagnosticFactory1 VAL_REASSIGNMENT = DiagnosticFactory1.create(ERROR, "Val can not be reassigned", NAME); + DiagnosticFactory1 INITIALIZATION_BEFORE_DECLARATION = DiagnosticFactory1.create(ERROR, "Variable cannot be initialized before declaration", NAME); + DiagnosticFactory VARIABLE_EXPECTED = DiagnosticFactory.create(ERROR, "Variable expected"); + + DiagnosticFactory1 INITIALIZATION_USING_BACKING_FIELD_CUSTOM_SETTER = DiagnosticFactory1.create(ERROR, "This property has a custom setter, so initialization using backing field required", NAME); + DiagnosticFactory1 INITIALIZATION_USING_BACKING_FIELD_OPEN_SETTER = DiagnosticFactory1.create(ERROR, "Setter of this property can be overridden, so initialization using backing field required", NAME); + + DiagnosticFactory1 FUNCTION_PARAMETERS_OF_INLINE_FUNCTION = DiagnosticFactory1.create(ERROR, "Function parameters of inline function can only be invoked", NAME); + + DiagnosticFactory UNREACHABLE_CODE = DiagnosticFactory.create(ERROR, "Unreachable code"); + + DiagnosticFactory MANY_CLASS_OBJECTS = DiagnosticFactory.create(ERROR, "Only one class object is allowed per class"); + DiagnosticFactory CLASS_OBJECT_NOT_ALLOWED = DiagnosticFactory.create(ERROR, "A class object is not allowed here"); + DiagnosticFactory DELEGATION_IN_TRAIT = DiagnosticFactory.create(ERROR, "Traits cannot use delegation"); + DiagnosticFactory DELEGATION_NOT_TO_TRAIT = DiagnosticFactory.create(ERROR, "Only traits can be delegated to"); + DiagnosticFactory NO_CONSTRUCTOR = DiagnosticFactory.create(ERROR, "This class does not have a constructor"); + DiagnosticFactory NOT_A_CLASS = DiagnosticFactory.create(ERROR, "Not a class"); + DiagnosticFactory ILLEGAL_ESCAPE_SEQUENCE = DiagnosticFactory.create(ERROR, "Illegal escape sequence"); + + DiagnosticFactory LOCAL_EXTENSION_PROPERTY = DiagnosticFactory.create(ERROR, "Local extension properties are not allowed"); + DiagnosticFactory LOCAL_VARIABLE_WITH_GETTER = DiagnosticFactory.create(ERROR, "Local variables are not allowed to have getters"); + DiagnosticFactory LOCAL_VARIABLE_WITH_SETTER = DiagnosticFactory.create(ERROR, "Local variables are not allowed to have setters"); + DiagnosticFactory VAL_WITH_SETTER = DiagnosticFactory.create(ERROR, "A 'val'-property cannot have a setter"); + + DiagnosticFactory NO_GET_METHOD = DiagnosticFactory.create(ERROR, "No get method providing array access", new PositioningStrategy() { @NotNull - protected DiagnosticWithPsiElement on(@NotNull JetModifierListOwner elementToBlame, @NotNull TextRange textRangeToMark, @NotNull String s, @NotNull ClassDescriptor classDescriptor, @NotNull JetClass aClass) { - return super.on(elementToBlame, textRangeToMark, s, classDescriptor, aClass).add(DiagnosticParameters.CLASS, aClass); + @Override + public List mark(@NotNull JetArrayAccessExpression element) { + return markElement(element.getIndicesNode()); } - }; - PsiElementOnlyDiagnosticFactory3 ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS = new PsiElementOnlyDiagnosticFactory3(ERROR, "Abstract function {0} in non-abstract class {1}") { + }); + DiagnosticFactory NO_SET_METHOD = DiagnosticFactory.create(ERROR, "No set method providing array access", new PositioningStrategy() { @NotNull - public DiagnosticWithPsiElement on(@NotNull JetFunction elementToBlame, @NotNull ASTNode nodeToMark, @NotNull String s, @NotNull ClassDescriptor classDescriptor, @NotNull JetClass modifierListOwner) { - return super.on(elementToBlame, nodeToMark, s, classDescriptor, modifierListOwner).add(DiagnosticParameters.CLASS, modifierListOwner); - } - }; - PsiElementOnlyDiagnosticFactory1 ABSTRACT_FUNCTION_WITH_BODY = PsiElementOnlyDiagnosticFactory1.create(ERROR, "A function {0} with body cannot be abstract"); - PsiElementOnlyDiagnosticFactory1 NON_ABSTRACT_FUNCTION_WITH_NO_BODY = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Method {0} without a body must be abstract"); - PsiElementOnlyDiagnosticFactory1 NON_MEMBER_ABSTRACT_FUNCTION = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Function {0} is not a class or trait member and cannot be abstract"); - - PsiElementOnlyDiagnosticFactory1 NON_MEMBER_FUNCTION_NO_BODY = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Function {0} must have a body"); - - DiagnosticWithParameterFactory NON_FINAL_MEMBER_IN_FINAL_CLASS = DiagnosticWithParameterFactory.create(ERROR, "Non final member in a final class", DiagnosticParameters.CLASS); - - DiagnosticWithParameterFactory PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE = DiagnosticWithParameterFactory.create(ERROR, "Public or protected member should specify a type", DiagnosticParameters.TYPE); - - SimpleDiagnosticFactory PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT = SimpleDiagnosticFactory.create(ERROR, "Projections are not allowed on type arguments of functions and properties"); // TODO : better positioning - SimpleDiagnosticFactory SUPERTYPE_NOT_INITIALIZED = SimpleDiagnosticFactory.create(ERROR, "This type has a constructor, and thus must be initialized here"); - SimplePsiElementOnlyDiagnosticFactory SUPERTYPE_NOT_INITIALIZED_DEFAULT = SimplePsiElementOnlyDiagnosticFactory.create(ERROR, "Constructor invocation should be explicitly specified"); - SimpleDiagnosticFactory SECONDARY_CONSTRUCTOR_BUT_NO_PRIMARY = SimpleDiagnosticFactory.create(ERROR, "A secondary constructor may appear only in a class that has a primary constructor"); - SimpleDiagnosticFactory SECONDARY_CONSTRUCTOR_NO_INITIALIZER_LIST = SimpleDiagnosticFactory.create(ERROR, "Secondary constructors must have an initializer list"); - SimpleDiagnosticFactory BY_IN_SECONDARY_CONSTRUCTOR = SimpleDiagnosticFactory.create(ERROR, "'by'-clause is only supported for primary constructors"); - SimpleDiagnosticFactory INITIALIZER_WITH_NO_ARGUMENTS = SimpleDiagnosticFactory.create(ERROR, "Constructor arguments required"); - SimpleDiagnosticFactory MANY_CALLS_TO_THIS = SimpleDiagnosticFactory.create(ERROR, "Only one call to 'this(...)' is allowed"); - PsiElementOnlyDiagnosticFactory1 NOTHING_TO_OVERRIDE = PsiElementOnlyDiagnosticFactory1.create(ERROR, "{0} overrides nothing", DescriptorRenderer.TEXT); - PsiElementOnlyDiagnosticFactory3 VIRTUAL_MEMBER_HIDDEN = PsiElementOnlyDiagnosticFactory3.create(ERROR, "''{0}'' hides ''{1}'' in class {2} and needs 'override' modifier", DescriptorRenderer.TEXT); - - ParameterizedDiagnosticFactory1 ENUM_ENTRY_SHOULD_BE_INITIALIZED = ParameterizedDiagnosticFactory1.create(ERROR, "Missing delegation specifier ''{0}''", NAME); - ParameterizedDiagnosticFactory1 ENUM_ENTRY_ILLEGAL_TYPE = ParameterizedDiagnosticFactory1.create(ERROR, "The type constructor of enum entry should be ''{0}''", NAME); - - PsiElementOnlyDiagnosticFactory1 UNINITIALIZED_VARIABLE = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Variable ''{0}'' must be initialized", NAME); - PsiElementOnlyDiagnosticFactory1 UNINITIALIZED_PARAMETER = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Parameter ''{0}'' is uninitialized here", NAME); - UnusedElementDiagnosticFactory UNUSED_VARIABLE = UnusedElementDiagnosticFactory.create(WARNING, "Variable ''{0}'' is never used", NAME); - UnusedElementDiagnosticFactory UNUSED_PARAMETER = UnusedElementDiagnosticFactory.create(WARNING, "Parameter ''{0}'' is never used", NAME); - UnusedElementDiagnosticFactory ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE = UnusedElementDiagnosticFactory.create(WARNING, "Variable ''{0}'' is assigned but never accessed", NAME); - PsiElementOnlyDiagnosticFactory1 VARIABLE_WITH_REDUNDANT_INITIALIZER = PsiElementOnlyDiagnosticFactory1.create(WARNING, "Variable ''{0}'' initializer is redundant", NAME); - PsiElementOnlyDiagnosticFactory2 UNUSED_VALUE = new PsiElementOnlyDiagnosticFactory2(WARNING, "The value ''{0}'' assigned to ''{1}'' is never used", NAME) { @Override - protected String makeMessageForA(@NotNull JetElement element) { - return element.getText(); + public List mark(@NotNull JetArrayAccessExpression element) { + return markElement(element.getIndicesNode()); } - }; - PsiElementOnlyDiagnosticFactory1 UNUSED_CHANGED_VALUE = new PsiElementOnlyDiagnosticFactory1(WARNING, "The value changed at ''{0}'' is never used", NAME) { - @Override - protected String makeMessageFor(JetElement argument) { - return argument.getText(); - } - }; - SimpleDiagnosticFactory UNUSED_EXPRESSION = SimpleDiagnosticFactory.create(WARNING, "The expression is unused"); - SimplePsiElementOnlyDiagnosticFactory UNUSED_FUNCTION_LITERAL = SimplePsiElementOnlyDiagnosticFactory.create(WARNING, "The function literal is unused. If you mean block, you can use 'run { ... }'"); + }); - PsiElementOnlyDiagnosticFactory1 VAL_REASSIGNMENT = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Val can not be reassigned", NAME); - PsiElementOnlyDiagnosticFactory1 INITIALIZATION_BEFORE_DECLARATION = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Variable cannot be initialized before declaration", NAME); - SimplePsiElementOnlyDiagnosticFactory VARIABLE_EXPECTED = new SimplePsiElementOnlyDiagnosticFactory(ERROR, "Variable expected"); - - PsiElementOnlyDiagnosticFactory1 INITIALIZATION_USING_BACKING_FIELD_CUSTOM_SETTER = PsiElementOnlyDiagnosticFactory1.create(ERROR, "This property has a custom setter, so initialization using backing field required", NAME); - PsiElementOnlyDiagnosticFactory1 INITIALIZATION_USING_BACKING_FIELD_OPEN_SETTER = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Setter of this property can be overridden, so initialization using backing field required", NAME); - - PsiElementOnlyDiagnosticFactory1 FUNCTION_PARAMETERS_OF_INLINE_FUNCTION = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Function parameters of inline function can only be invoked", NAME); - - SimpleDiagnosticFactory UNREACHABLE_CODE = SimpleDiagnosticFactory.create(ERROR, "Unreachable code"); - - SimpleDiagnosticFactory MANY_CLASS_OBJECTS = SimpleDiagnosticFactory.create(ERROR, "Only one class object is allowed per class"); - SimpleDiagnosticFactory CLASS_OBJECT_NOT_ALLOWED = SimpleDiagnosticFactory.create(ERROR, "A class object is not allowed here"); - SimpleDiagnosticFactory DELEGATION_IN_TRAIT = SimpleDiagnosticFactory.create(ERROR, "Traits cannot use delegation"); - SimpleDiagnosticFactory DELEGATION_NOT_TO_TRAIT = SimpleDiagnosticFactory.create(ERROR, "Only traits can be delegated to"); - SimpleDiagnosticFactory NO_CONSTRUCTOR = SimpleDiagnosticFactory.create(ERROR, "This class does not have a constructor"); - SimpleDiagnosticFactory NOT_A_CLASS = SimpleDiagnosticFactory.create(ERROR, "Not a class"); - SimpleDiagnosticFactory ILLEGAL_ESCAPE_SEQUENCE = SimpleDiagnosticFactory.create(ERROR, "Illegal escape sequence"); - - SimpleDiagnosticFactory LOCAL_EXTENSION_PROPERTY = SimpleDiagnosticFactory.create(ERROR, "Local extension properties are not allowed"); - SimpleDiagnosticFactory LOCAL_VARIABLE_WITH_GETTER = SimpleDiagnosticFactory.create(ERROR, "Local variables are not allowed to have getters"); - SimpleDiagnosticFactory LOCAL_VARIABLE_WITH_SETTER = SimpleDiagnosticFactory.create(ERROR, "Local variables are not allowed to have setters"); - SimplePsiElementOnlyDiagnosticFactory VAL_WITH_SETTER = SimplePsiElementOnlyDiagnosticFactory.create(ERROR, "A 'val'-property cannot have a setter"); - - SimpleDiagnosticFactory NO_GET_METHOD = SimpleDiagnosticFactory.create(ERROR, "No get method providing array access"); - SimpleDiagnosticFactory NO_SET_METHOD = SimpleDiagnosticFactory.create(ERROR, "No set method providing array access"); - - SimpleDiagnosticFactory INC_DEC_SHOULD_NOT_RETURN_UNIT = SimpleDiagnosticFactory.create(ERROR, "Functions inc(), dec() shouldn't return Unit to be used by operators ++, --"); - ParameterizedDiagnosticFactory2 ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT = new ParameterizedDiagnosticFactory2(ERROR, "Function ''{0}'' should return Unit to be used by corresponding operator ''{1}''", NAME) { - @Override - protected String makeMessageForB(@NotNull JetSimpleNameExpression expression) { - return expression.getText(); - } - }; + DiagnosticFactory INC_DEC_SHOULD_NOT_RETURN_UNIT = DiagnosticFactory.create(ERROR, "Functions inc(), dec() shouldn't return Unit to be used by operators ++, --"); + DiagnosticFactory2 ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT = + DiagnosticFactory2.create(ERROR, "Function ''{0}'' should return Unit to be used by corresponding operator ''{1}''", NAME, ELEMENT_TEXT); AmbiguousDescriptorDiagnosticFactory ASSIGN_OPERATOR_AMBIGUITY = AmbiguousDescriptorDiagnosticFactory.create("Assignment operators ambiguity: {0}"); - SimpleDiagnosticFactory EQUALS_MISSING = SimpleDiagnosticFactory.create(ERROR, "No method 'equals(Any?) : Boolean' available"); - SimpleDiagnosticFactory ASSIGNMENT_IN_EXPRESSION_CONTEXT = SimpleDiagnosticFactory.create(ERROR, "Assignments are not expressions, and only expressions are allowed in this context"); - SimpleDiagnosticFactory NAMESPACE_IS_NOT_AN_EXPRESSION = SimpleDiagnosticFactory.create(ERROR, "'namespace' is not an expression, it can only be used on the left-hand side of a dot ('.')"); - ParameterizedDiagnosticFactory1 SUPER_IS_NOT_AN_EXPRESSION = ParameterizedDiagnosticFactory1.create(ERROR, "{0} is not an expression, it can only be used on the left-hand side of a dot ('.')"); - SimpleDiagnosticFactory DECLARATION_IN_ILLEGAL_CONTEXT = SimpleDiagnosticFactory.create(ERROR, "Declarations are not allowed in this position"); - SimpleDiagnosticFactory SETTER_PARAMETER_WITH_DEFAULT_VALUE = SimpleDiagnosticFactory.create(ERROR, "Setter parameters can not have default values"); - SimpleDiagnosticFactory NO_THIS = SimpleDiagnosticFactory.create(ERROR, "'this' is not defined in this context"); - SimpleDiagnosticFactory SUPER_NOT_AVAILABLE = SimpleDiagnosticFactory.create(ERROR, "No supertypes are accessible in this context"); - SimpleDiagnosticFactory AMBIGUOUS_SUPER = SimpleDiagnosticFactory.create(ERROR, "Many supertypes available, please specify the one you mean in angle brackets, e.g. 'super'"); - SimpleDiagnosticFactory ABSTRACT_SUPER_CALL = SimpleDiagnosticFactory.create(ERROR, "Abstarct member cannot be accessed directly"); - SimpleDiagnosticFactory NOT_A_SUPERTYPE = SimpleDiagnosticFactory.create(ERROR, "Not a supertype"); - SimpleDiagnosticFactory TYPE_ARGUMENTS_REDUNDANT_IN_SUPER_QUALIFIER = SimpleDiagnosticFactory.create(WARNING, "Type arguments do not need to be specified in a 'super' qualifier"); - SimpleDiagnosticFactory NO_WHEN_ENTRIES = SimpleDiagnosticFactory.create(ERROR, "Entries are required for when-expression"); // TODO : Scope, and maybe this should not be an error - SimplePsiElementOnlyDiagnosticFactory USELESS_CAST_STATIC_ASSERT_IS_FINE = SimplePsiElementOnlyDiagnosticFactory.create(WARNING, "No cast needed, use ':' instead"); - SimplePsiElementOnlyDiagnosticFactory USELESS_CAST = SimplePsiElementOnlyDiagnosticFactory.create(WARNING, "No cast needed"); - SimpleDiagnosticFactory CAST_NEVER_SUCCEEDS = SimpleDiagnosticFactory.create(WARNING, "This cast can never succeed"); - DiagnosticWithParameterFactory WRONG_SETTER_PARAMETER_TYPE = DiagnosticWithParameterFactory.create(ERROR, "Setter parameter type must be equal to the type of the property, i.e. {0}", DiagnosticParameters.TYPE); - DiagnosticWithParameterFactory WRONG_GETTER_RETURN_TYPE = DiagnosticWithParameterFactory.create(ERROR, "Getter return type must be equal to the type of the property, i.e. {0}", DiagnosticParameters.TYPE); - ParameterizedDiagnosticFactory1 NO_CLASS_OBJECT = ParameterizedDiagnosticFactory1.create(ERROR, "Please specify constructor invocation; classifier {0} does not have a class object", NAME); - SimpleDiagnosticFactory NO_GENERICS_IN_SUPERTYPE_SPECIFIER = SimpleDiagnosticFactory.create(ERROR, "Generic arguments of the base type must be specified"); + DiagnosticFactory EQUALS_MISSING = DiagnosticFactory.create(ERROR, "No method 'equals(Any?) : Boolean' available"); + DiagnosticFactory ASSIGNMENT_IN_EXPRESSION_CONTEXT = DiagnosticFactory.create(ERROR, "Assignments are not expressions, and only expressions are allowed in this context"); + DiagnosticFactory NAMESPACE_IS_NOT_AN_EXPRESSION = DiagnosticFactory.create(ERROR, "'namespace' is not an expression, it can only be used on the left-hand side of a dot ('.')"); + DiagnosticFactory1 SUPER_IS_NOT_AN_EXPRESSION = DiagnosticFactory1.create(ERROR, "{0} is not an expression, it can only be used on the left-hand side of a dot ('.')"); + DiagnosticFactory DECLARATION_IN_ILLEGAL_CONTEXT = DiagnosticFactory.create(ERROR, "Declarations are not allowed in this position"); + DiagnosticFactory SETTER_PARAMETER_WITH_DEFAULT_VALUE = DiagnosticFactory.create(ERROR, "Setter parameters can not have default values"); + DiagnosticFactory NO_THIS = DiagnosticFactory.create(ERROR, "'this' is not defined in this context"); + DiagnosticFactory SUPER_NOT_AVAILABLE = DiagnosticFactory.create(ERROR, "No supertypes are accessible in this context"); + DiagnosticFactory AMBIGUOUS_SUPER = DiagnosticFactory.create(ERROR, "Many supertypes available, please specify the one you mean in angle brackets, e.g. 'super'"); + DiagnosticFactory ABSTRACT_SUPER_CALL = DiagnosticFactory.create(ERROR, "Abstarct member cannot be accessed directly"); + DiagnosticFactory NOT_A_SUPERTYPE = DiagnosticFactory.create(ERROR, "Not a supertype"); + DiagnosticFactory TYPE_ARGUMENTS_REDUNDANT_IN_SUPER_QUALIFIER = DiagnosticFactory.create(WARNING, "Type arguments do not need to be specified in a 'super' qualifier"); + DiagnosticFactory NO_WHEN_ENTRIES = DiagnosticFactory.create(ERROR, "Entries are required for when-expression"); // TODO : Scope, and maybe this should not be an error + DiagnosticFactory USELESS_CAST_STATIC_ASSERT_IS_FINE = DiagnosticFactory.create(WARNING, "No cast needed, use ':' instead"); + DiagnosticFactory USELESS_CAST = DiagnosticFactory.create(WARNING, "No cast needed"); + DiagnosticFactory CAST_NEVER_SUCCEEDS = DiagnosticFactory.create(WARNING, "This cast can never succeed"); + DiagnosticFactory1 WRONG_SETTER_PARAMETER_TYPE = DiagnosticFactory1.create(ERROR, "Setter parameter type must be equal to the type of the property, i.e. {0}");//, DiagnosticParameters.TYPE); + DiagnosticFactory1 WRONG_GETTER_RETURN_TYPE = DiagnosticFactory1.create(ERROR, "Getter return type must be equal to the type of the property, i.e. {0}");//, DiagnosticParameters.TYPE); + DiagnosticFactory1 NO_CLASS_OBJECT = DiagnosticFactory1.create(ERROR, "Please specify constructor invocation; classifier {0} does not have a class object", NAME); + DiagnosticFactory NO_GENERICS_IN_SUPERTYPE_SPECIFIER = DiagnosticFactory.create(ERROR, "Generic arguments of the base type must be specified"); - SimpleDiagnosticFactory HAS_NEXT_PROPERTY_AND_FUNCTION_AMBIGUITY = SimpleDiagnosticFactory.create(ERROR, "An ambiguity between 'iterator().hasNext()' function and 'iterator().hasNext' property"); - SimpleDiagnosticFactory HAS_NEXT_MISSING = SimpleDiagnosticFactory.create(ERROR, "Loop range must have an 'iterator().hasNext()' function or an 'iterator().hasNext' property"); - SimpleDiagnosticFactory HAS_NEXT_FUNCTION_AMBIGUITY = SimpleDiagnosticFactory.create(ERROR, "Function 'iterator().hasNext()' is ambiguous for this expression"); - SimpleDiagnosticFactory HAS_NEXT_MUST_BE_READABLE = SimpleDiagnosticFactory.create(ERROR, "The 'iterator().hasNext' property of the loop range must be readable"); - ParameterizedDiagnosticFactory1 HAS_NEXT_PROPERTY_TYPE_MISMATCH = ParameterizedDiagnosticFactory1.create(ERROR, "The 'iterator().hasNext' property of the loop range must return Boolean, but returns {0}"); - ParameterizedDiagnosticFactory1 HAS_NEXT_FUNCTION_TYPE_MISMATCH = ParameterizedDiagnosticFactory1.create(ERROR, "The 'iterator().hasNext()' function of the loop range must return Boolean, but returns {0}"); - SimpleDiagnosticFactory NEXT_AMBIGUITY = SimpleDiagnosticFactory.create(ERROR, "Function 'iterator().next()' is ambiguous for this expression"); - SimpleDiagnosticFactory NEXT_MISSING = SimpleDiagnosticFactory.create(ERROR, "Loop range must have an 'iterator().next()' function"); - SimpleDiagnosticFactory ITERATOR_MISSING = SimpleDiagnosticFactory.create(ERROR, "For-loop range must have an iterator() method"); + DiagnosticFactory HAS_NEXT_PROPERTY_AND_FUNCTION_AMBIGUITY = DiagnosticFactory.create(ERROR, "An ambiguity between 'iterator().hasNext()' function and 'iterator().hasNext' property"); + DiagnosticFactory HAS_NEXT_MISSING = DiagnosticFactory.create(ERROR, "Loop range must have an 'iterator().hasNext()' function or an 'iterator().hasNext' property"); + DiagnosticFactory HAS_NEXT_FUNCTION_AMBIGUITY = DiagnosticFactory.create(ERROR, "Function 'iterator().hasNext()' is ambiguous for this expression"); + DiagnosticFactory HAS_NEXT_MUST_BE_READABLE = DiagnosticFactory.create(ERROR, "The 'iterator().hasNext' property of the loop range must be readable"); + DiagnosticFactory1 HAS_NEXT_PROPERTY_TYPE_MISMATCH = DiagnosticFactory1.create(ERROR, "The 'iterator().hasNext' property of the loop range must return Boolean, but returns {0}"); + DiagnosticFactory1 HAS_NEXT_FUNCTION_TYPE_MISMATCH = DiagnosticFactory1.create(ERROR, "The 'iterator().hasNext()' function of the loop range must return Boolean, but returns {0}"); + DiagnosticFactory NEXT_AMBIGUITY = DiagnosticFactory.create(ERROR, "Function 'iterator().next()' is ambiguous for this expression"); + DiagnosticFactory NEXT_MISSING = DiagnosticFactory.create(ERROR, "Loop range must have an 'iterator().next()' function"); + DiagnosticFactory ITERATOR_MISSING = DiagnosticFactory.create(ERROR, "For-loop range must have an iterator() method"); AmbiguousDescriptorDiagnosticFactory ITERATOR_AMBIGUITY = AmbiguousDescriptorDiagnosticFactory.create("Method 'iterator()' is ambiguous for this expression: {0}"); - ParameterizedDiagnosticFactory1 COMPARE_TO_TYPE_MISMATCH = ParameterizedDiagnosticFactory1.create(ERROR, "compareTo() must return Int, but returns {0}"); - ParameterizedDiagnosticFactory1 CALLEE_NOT_A_FUNCTION = ParameterizedDiagnosticFactory1.create(ERROR, "Expecting a function type, but found {0}"); + DiagnosticFactory1 COMPARE_TO_TYPE_MISMATCH = DiagnosticFactory1.create(ERROR, "compareTo() must return Int, but returns {0}"); + DiagnosticFactory1 CALLEE_NOT_A_FUNCTION = DiagnosticFactory1.create(ERROR, "Expecting a function type, but found {0}"); - SimpleDiagnosticFactory RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY = SimpleDiagnosticFactory.create(ERROR, "Returns are not allowed for functions with expression body. Use block body in '{...}'"); - SimpleDiagnosticFactory NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY = SimpleDiagnosticFactory.create(ERROR, "A 'return' expression required in a function with a block body ('{...}')"); - ParameterizedDiagnosticFactory1 RETURN_TYPE_MISMATCH = ParameterizedDiagnosticFactory1.create(ERROR, "This function must return a value of type {0}"); - ParameterizedDiagnosticFactory1 EXPECTED_TYPE_MISMATCH = ParameterizedDiagnosticFactory1.create(ERROR, "Expected a value of type {0}"); - ParameterizedDiagnosticFactory1 ASSIGNMENT_TYPE_MISMATCH = ParameterizedDiagnosticFactory1.create(ERROR, "Expected a value of type {0}. Assignment operation is not an expression, so it does not return any value"); - ParameterizedDiagnosticFactory1 IMPLICIT_CAST_TO_UNIT_OR_ANY = ParameterizedDiagnosticFactory1.create(WARNING, "Type was casted to ''{0}''. Please specify ''{0}'' as expected type, if you mean such cast"); - ParameterizedDiagnosticFactory1 EXPRESSION_EXPECTED = new ParameterizedDiagnosticFactory1(ERROR, "{0} is not an expression, and only expression are allowed here") { + DiagnosticFactory RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY = DiagnosticFactory.create(ERROR, "Returns are not allowed for functions with expression body. Use block body in '{...}'"); + DiagnosticFactory NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY = DiagnosticFactory.create(ERROR, "A 'return' expression required in a function with a block body ('{...}')"); + DiagnosticFactory1 RETURN_TYPE_MISMATCH = DiagnosticFactory1.create(ERROR, "This function must return a value of type {0}"); + DiagnosticFactory1 EXPECTED_TYPE_MISMATCH = DiagnosticFactory1.create(ERROR, "Expected a value of type {0}"); + DiagnosticFactory1 ASSIGNMENT_TYPE_MISMATCH = DiagnosticFactory1.create(ERROR, "Expected a value of type {0}. Assignment operation is not an expression, so it does not return any value"); + DiagnosticFactory1 IMPLICIT_CAST_TO_UNIT_OR_ANY = DiagnosticFactory1.create(WARNING, "Type was casted to ''{0}''. Please specify ''{0}'' as expected type, if you mean such cast"); + DiagnosticFactory1 EXPRESSION_EXPECTED = DiagnosticFactory1.create(ERROR, "{0} is not an expression, and only expression are allowed here", new Renderer() { + @NotNull @Override - protected String makeMessageFor(JetExpression expression) { + public String render(@Nullable JetExpression expression) { + assert expression != null; String expressionType = expression.toString(); return expressionType.substring(0, 1) + expressionType.substring(1).toLowerCase(); } - }; + }); - ParameterizedDiagnosticFactory1 UPPER_BOUND_VIOLATED = ParameterizedDiagnosticFactory1.create(ERROR, "An upper bound {0} is violated"); // TODO : Message - ParameterizedDiagnosticFactory1 FINAL_CLASS_OBJECT_UPPER_BOUND = ParameterizedDiagnosticFactory1.create(ERROR, "{0} is a final type, and thus a class object cannot extend it"); - ParameterizedDiagnosticFactory1 FINAL_UPPER_BOUND = ParameterizedDiagnosticFactory1.create(WARNING, "{0} is a final type, and thus a value of the type parameter is predetermined"); - PsiElementOnlyDiagnosticFactory1 USELESS_ELVIS = PsiElementOnlyDiagnosticFactory1.create(WARNING, "Elvis operator (?:) always returns the left operand of non-nullable type {0}"); - ParameterizedDiagnosticFactory1 CONFLICTING_UPPER_BOUNDS = new ParameterizedDiagnosticFactory1(ERROR, "Upper bounds of {0} have empty intersection") { - @Override - protected String makeMessageFor(@NotNull TypeParameterDescriptor argument) { - return argument.getName(); - } - }; - ParameterizedDiagnosticFactory1 CONFLICTING_CLASS_OBJECT_UPPER_BOUNDS = ParameterizedDiagnosticFactory1.create(ERROR, "Class object upper bounds of {0} have empty intersection", NAME); + DiagnosticFactory1 UPPER_BOUND_VIOLATED = DiagnosticFactory1.create(ERROR, "An upper bound {0} is violated"); // TODO : Message + DiagnosticFactory1 FINAL_CLASS_OBJECT_UPPER_BOUND = DiagnosticFactory1.create(ERROR, "{0} is a final type, and thus a class object cannot extend it"); + DiagnosticFactory1 FINAL_UPPER_BOUND = DiagnosticFactory1.create(WARNING, "{0} is a final type, and thus a value of the type parameter is predetermined"); + DiagnosticFactory1 USELESS_ELVIS = DiagnosticFactory1.create(WARNING, "Elvis operator (?:) always returns the left operand of non-nullable type {0}"); + DiagnosticFactory1 CONFLICTING_UPPER_BOUNDS = DiagnosticFactory1.create(ERROR, "Upper bounds of {0} have empty intersection", NAME); + DiagnosticFactory1 CONFLICTING_CLASS_OBJECT_UPPER_BOUNDS = DiagnosticFactory1.create(ERROR, "Class object upper bounds of {0} have empty intersection", NAME); - ParameterizedDiagnosticFactory1 TOO_MANY_ARGUMENTS = ParameterizedDiagnosticFactory1.create(ERROR, "Too many arguments for {0}"); - ParameterizedDiagnosticFactory1 ERROR_COMPILE_TIME_VALUE = ParameterizedDiagnosticFactory1.create(ERROR, "{0}"); + DiagnosticFactory1 TOO_MANY_ARGUMENTS = DiagnosticFactory1.create(ERROR, "Too many arguments for {0}"); + DiagnosticFactory1 ERROR_COMPILE_TIME_VALUE = DiagnosticFactory1.create(ERROR, "{0}"); - SimpleDiagnosticFactoryWithPsiElement ELSE_MISPLACED_IN_WHEN = new SimpleDiagnosticFactoryWithPsiElement(ERROR, "'else' entry must be the last one in a when-expression") { + DiagnosticFactory ELSE_MISPLACED_IN_WHEN = DiagnosticFactory.create( + ERROR, "'else' entry must be the last one in a when-expression", new PositioningStrategy() { @NotNull @Override - public TextRange getTextRange(@NotNull JetWhenEntry entry) { + public List mark(@NotNull JetWhenEntry entry) { PsiElement elseKeywordElement = entry.getElseKeywordElement(); assert elseKeywordElement != null; - return elseKeywordElement.getTextRange(); + return markElement(elseKeywordElement); } - }; - SimpleDiagnosticFactoryWithPsiElement NO_ELSE_IN_WHEN = new SimpleDiagnosticFactoryWithPsiElement(ERROR, "'when' expression must contain 'else' branch") { + }); + + DiagnosticFactory NO_ELSE_IN_WHEN = new DiagnosticFactory(ERROR, "'when' expression must contain 'else' branch", new PositioningStrategy() { @NotNull @Override - public TextRange getTextRange(@NotNull JetWhenExpression element) { - return element.getWhenKeywordElement().getTextRange(); + public List mark(@NotNull JetWhenExpression element) { + return markElement(element.getWhenKeywordElement()); } - }; - SimpleDiagnosticFactoryWithPsiElement TYPE_MISMATCH_IN_RANGE = new SimpleDiagnosticFactoryWithPsiElement(ERROR, "Type mismatch: incompatible types of range and element checked in it") { + }); + DiagnosticFactory TYPE_MISMATCH_IN_RANGE = new DiagnosticFactory(ERROR, "Type mismatch: incompatible types of range and element checked in it", new PositioningStrategy() { @NotNull @Override - public TextRange getTextRange(@NotNull JetWhenConditionInRange condition) { - return condition.getOperationReference().getTextRange(); + public List mark(@NotNull JetWhenConditionInRange condition) { + return markElement(condition.getOperationReference()); } - }; - SimpleDiagnosticFactory CYCLIC_INHERITANCE_HIERARCHY = SimpleDiagnosticFactory.create(ERROR, "There's a cycle in the inheritance hierarchy for this type"); + }); + DiagnosticFactory CYCLIC_INHERITANCE_HIERARCHY = DiagnosticFactory.create(ERROR, "There's a cycle in the inheritance hierarchy for this type"); - SimpleDiagnosticFactory MANY_CLASSES_IN_SUPERTYPE_LIST = SimpleDiagnosticFactory.create(ERROR, "Only one class may appear in a supertype list"); - SimpleDiagnosticFactory SUPERTYPE_NOT_A_CLASS_OR_TRAIT = SimpleDiagnosticFactory.create(ERROR, "Only classes and traits may serve as supertypes"); - SimpleDiagnosticFactory SUPERTYPE_INITIALIZED_IN_TRAIT = SimpleDiagnosticFactory.create(ERROR, "Traits cannot initialize supertypes"); - SimpleDiagnosticFactory CONSTRUCTOR_IN_TRAIT = SimpleDiagnosticFactory.create(ERROR, "A trait may not have a constructor"); - SimpleDiagnosticFactory SUPERTYPE_APPEARS_TWICE = SimpleDiagnosticFactory.create(ERROR, "A supertype appears twice"); - SimpleDiagnosticFactory FINAL_SUPERTYPE = SimpleDiagnosticFactory.create(ERROR, "This type is final, so it cannot be inherited from"); + DiagnosticFactory MANY_CLASSES_IN_SUPERTYPE_LIST = DiagnosticFactory.create(ERROR, "Only one class may appear in a supertype list"); + DiagnosticFactory SUPERTYPE_NOT_A_CLASS_OR_TRAIT = DiagnosticFactory.create(ERROR, "Only classes and traits may serve as supertypes"); + DiagnosticFactory SUPERTYPE_INITIALIZED_IN_TRAIT = DiagnosticFactory.create(ERROR, "Traits cannot initialize supertypes"); + DiagnosticFactory CONSTRUCTOR_IN_TRAIT = DiagnosticFactory.create(ERROR, "A trait may not have a constructor"); + DiagnosticFactory SUPERTYPE_APPEARS_TWICE = DiagnosticFactory.create(ERROR, "A supertype appears twice"); + DiagnosticFactory FINAL_SUPERTYPE = DiagnosticFactory.create(ERROR, "This type is final, so it cannot be inherited from"); - ParameterizedDiagnosticFactory1 ILLEGAL_SELECTOR = ParameterizedDiagnosticFactory1.create(ERROR, "Expression ''{0}'' cannot be a selector (occur after a dot)"); + DiagnosticFactory1 ILLEGAL_SELECTOR = DiagnosticFactory1.create(ERROR, "Expression ''{0}'' cannot be a selector (occur after a dot)"); - SimpleDiagnosticFactory VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION = SimpleDiagnosticFactory.create(ERROR, "A type annotation is required on a value parameter"); - SimpleDiagnosticFactory BREAK_OR_CONTINUE_OUTSIDE_A_LOOP = SimpleDiagnosticFactory.create(ERROR, "'break' and 'continue' are only allowed inside a loop"); - ParameterizedDiagnosticFactory1 NOT_A_LOOP_LABEL = ParameterizedDiagnosticFactory1.create(ERROR, "The label ''{0}'' does not denote a loop"); - ParameterizedDiagnosticFactory1 NOT_A_RETURN_LABEL = ParameterizedDiagnosticFactory1.create(ERROR, "The label ''{0}'' does not reference to a context from which we can return"); + DiagnosticFactory VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION = DiagnosticFactory.create(ERROR, "A type annotation is required on a value parameter"); + DiagnosticFactory BREAK_OR_CONTINUE_OUTSIDE_A_LOOP = DiagnosticFactory.create(ERROR, "'break' and 'continue' are only allowed inside a loop"); + DiagnosticFactory1 NOT_A_LOOP_LABEL = DiagnosticFactory1.create(ERROR, "The label ''{0}'' does not denote a loop"); + DiagnosticFactory1 NOT_A_RETURN_LABEL = DiagnosticFactory1.create(ERROR, "The label ''{0}'' does not reference to a context from which we can return"); - SimpleDiagnosticFactory ANONYMOUS_INITIALIZER_WITHOUT_CONSTRUCTOR = SimpleDiagnosticFactory.create(ERROR, "Anonymous initializers are only allowed in the presence of a primary constructor"); - SimpleDiagnosticFactory NULLABLE_SUPERTYPE = SimpleDiagnosticFactory.create(ERROR, "A supertype cannot be nullable"); - ParameterizedDiagnosticFactory1 UNSAFE_CALL = ParameterizedDiagnosticFactory1.create(ERROR, "Only safe calls (?.) are allowed on a nullable receiver of type {0}"); - SimpleDiagnosticFactory AMBIGUOUS_LABEL = SimpleDiagnosticFactory.create(ERROR, "Ambiguous label"); - ParameterizedDiagnosticFactory1 UNSUPPORTED = ParameterizedDiagnosticFactory1.create(ERROR, "Unsupported [{0}]"); - ParameterizedDiagnosticFactory1 UNNECESSARY_SAFE_CALL = ParameterizedDiagnosticFactory1.create(WARNING, "Unnecessary safe call on a non-null receiver of type {0}"); - ParameterizedDiagnosticFactory2 NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER = new ParameterizedDiagnosticFactory2(ERROR, "{0} does not refer to a type parameter of {1}") { + DiagnosticFactory ANONYMOUS_INITIALIZER_WITHOUT_CONSTRUCTOR = DiagnosticFactory.create(ERROR, "Anonymous initializers are only allowed in the presence of a primary constructor"); + DiagnosticFactory NULLABLE_SUPERTYPE = DiagnosticFactory.create(ERROR, "A supertype cannot be nullable", new PositioningStrategy() { + @NotNull @Override - protected String makeMessageForA(@NotNull JetTypeConstraint jetTypeConstraint) { - return jetTypeConstraint.getSubjectTypeParameterName().getReferencedName(); + public List mark(@NotNull JetNullableType element) { + return markNode(element.getQuestionMarkNode()); } - + }); + DiagnosticFactory1 UNSAFE_CALL = DiagnosticFactory1.create(ERROR, "Only safe calls (?.) are allowed on a nullable receiver of type {0}"); + DiagnosticFactory AMBIGUOUS_LABEL = DiagnosticFactory.create(ERROR, "Ambiguous label"); + DiagnosticFactory1 UNSUPPORTED = DiagnosticFactory1.create(ERROR, "Unsupported [{0}]"); + DiagnosticFactory1 UNNECESSARY_SAFE_CALL = DiagnosticFactory1.create(WARNING, "Unnecessary safe call on a non-null receiver of type {0}"); + DiagnosticFactory2 NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER = DiagnosticFactory2.create(ERROR, "{0} does not refer to a type parameter of {1}", new Renderer() { + @NotNull @Override - protected String makeMessageForB(@NotNull JetTypeParameterListOwner constraintOwner) { - return constraintOwner.getName(); + public String render(@Nullable JetTypeConstraint typeConstraint) { + assert typeConstraint != null; + return typeConstraint.getSubjectTypeParameterName().getReferencedName(); } - }; - ParameterizedDiagnosticFactory2 AUTOCAST_IMPOSSIBLE = ParameterizedDiagnosticFactory2.create(ERROR, "Automatic cast to {0} is impossible, because {1} could have changed since the is-check"); + }, NAME); + DiagnosticFactory2 AUTOCAST_IMPOSSIBLE = DiagnosticFactory2.create(ERROR, "Automatic cast to {0} is impossible, because {1} could have changed since the is-check"); - ParameterizedDiagnosticFactory2 TYPE_MISMATCH_IN_FOR_LOOP = ParameterizedDiagnosticFactory2.create(ERROR, "The loop iterates over values of type {0} but the parameter is declared to be {1}"); - ParameterizedDiagnosticFactory1 TYPE_MISMATCH_IN_CONDITION = ParameterizedDiagnosticFactory1.create(ERROR, "Condition must be of type Boolean, but was of type {0}"); - ParameterizedDiagnosticFactory2 TYPE_MISMATCH_IN_TUPLE_PATTERN = ParameterizedDiagnosticFactory2.create(ERROR, "Type mismatch: subject is of type {0} but the pattern is of type Tuple{1}"); // TODO: message - ParameterizedDiagnosticFactory2 TYPE_MISMATCH_IN_BINDING_PATTERN = ParameterizedDiagnosticFactory2.create(ERROR, "{0} must be a supertype of {1}. Use 'is' to match against {0}"); - ParameterizedDiagnosticFactory2 INCOMPATIBLE_TYPES = ParameterizedDiagnosticFactory2.create(ERROR, "Incompatible types: {0} and {1}"); - SimpleDiagnosticFactory EXPECTED_CONDITION = SimpleDiagnosticFactory.create(ERROR, "Expected condition of Boolean type"); + DiagnosticFactory2 TYPE_MISMATCH_IN_FOR_LOOP = DiagnosticFactory2.create(ERROR, "The loop iterates over values of type {0} but the parameter is declared to be {1}"); + DiagnosticFactory1 TYPE_MISMATCH_IN_CONDITION = DiagnosticFactory1.create(ERROR, "Condition must be of type Boolean, but was of type {0}"); + DiagnosticFactory2 TYPE_MISMATCH_IN_TUPLE_PATTERN = DiagnosticFactory2.create(ERROR, "Type mismatch: subject is of type {0} but the pattern is of type Tuple{1}"); // TODO: message + DiagnosticFactory2 TYPE_MISMATCH_IN_BINDING_PATTERN = DiagnosticFactory2.create(ERROR, "{0} must be a supertype of {1}. Use 'is' to match against {0}"); + DiagnosticFactory2 INCOMPATIBLE_TYPES = DiagnosticFactory2.create(ERROR, "Incompatible types: {0} and {1}"); + DiagnosticFactory EXPECTED_CONDITION = DiagnosticFactory.create(ERROR, "Expected condition of Boolean type"); - ParameterizedDiagnosticFactory1 CANNOT_CHECK_FOR_ERASED = ParameterizedDiagnosticFactory1.create(ERROR, "Cannot check for instance of erased type: {0}"); - ParameterizedDiagnosticFactory2 UNCHECKED_CAST = ParameterizedDiagnosticFactory2.create(WARNING, "Unchecked cast: {0} to {1}"); + DiagnosticFactory1 CANNOT_CHECK_FOR_ERASED = DiagnosticFactory1.create(ERROR, "Cannot check for instance of erased type: {0}"); + DiagnosticFactory2 UNCHECKED_CAST = DiagnosticFactory2.create(WARNING, "Unchecked cast: {0} to {1}"); - ParameterizedDiagnosticFactory3> INCONSISTENT_TYPE_PARAMETER_VALUES = new ParameterizedDiagnosticFactory3>(ERROR, "Type parameter {0} of {1} has inconsistent values: {2}") { - @Override - protected String makeMessageForA(@NotNull TypeParameterDescriptor typeParameterDescriptor) { - return typeParameterDescriptor.getName(); - } - - @Override - protected String makeMessageForB(@NotNull ClassDescriptor classDescriptor) { - return DescriptorRenderer.TEXT.render(classDescriptor); - } - - @Override - protected String makeMessageForC(@NotNull Collection jetTypes) { - StringBuilder builder = new StringBuilder(); - for (Iterator iterator = jetTypes.iterator(); iterator.hasNext(); ) { - JetType jetType = iterator.next(); - builder.append(jetType); - if (iterator.hasNext()) { - builder.append(", "); + DiagnosticFactory3> INCONSISTENT_TYPE_PARAMETER_VALUES = + DiagnosticFactory3.create(ERROR, "Type parameter {0} of {1} has inconsistent values: {2}", NAME, DescriptorRenderer.TEXT, new Renderer>() { + @NotNull + @Override + public String render(@Nullable Collection types) { + StringBuilder builder = new StringBuilder(); + for (Iterator iterator = types.iterator(); iterator.hasNext(); ) { + JetType jetType = iterator.next(); + builder.append(jetType); + if (iterator.hasNext()) { + builder.append(", "); + } + } + return builder.toString(); } - } - return builder.toString(); - } - }; - - ParameterizedDiagnosticFactory3 EQUALITY_NOT_APPLICABLE = new ParameterizedDiagnosticFactory3(ERROR, "Operator {0} cannot be applied to {1} and {2}") { + }); + + DiagnosticFactory3 EQUALITY_NOT_APPLICABLE = DiagnosticFactory3.create(ERROR, "Operator {0} cannot be applied to {1} and {2}", new Renderer() { + @NotNull @Override - protected String makeMessageForA(@NotNull JetSimpleNameExpression nameExpression) { + public String render(@Nullable JetSimpleNameExpression nameExpression) { return nameExpression.getReferencedName(); } - }; - ParameterizedDiagnosticFactory2 OVERRIDING_FINAL_MEMBER = ParameterizedDiagnosticFactory2.create(ERROR, "{0} in {1} is final and cannot be overridden", NAME); + }, TO_STRING, TO_STRING); - ParameterizedDiagnosticFactory2 RETURN_TYPE_MISMATCH_ON_OVERRIDE = new ParameterizedDiagnosticFactory2(ERROR, "Return type of {0} is not a subtype of the return type overridden member {1}") { + DiagnosticFactory2 OVERRIDING_FINAL_MEMBER = DiagnosticFactory2.create(ERROR, "{0} in {1} is final and cannot be overridden", NAME, NAME); + + DiagnosticFactory2 RETURN_TYPE_MISMATCH_ON_OVERRIDE = + DiagnosticFactory2.create(ERROR, "Return type of {0} is not a subtype of the return type overridden member {1}", PositioningStrategies.POSITION_DECLARATION, DescriptorRenderer.TEXT, DescriptorRenderer.TEXT); + + DiagnosticFactory2 VAR_OVERRIDDEN_BY_VAL = DiagnosticFactory2.create(ERROR, "Var-property {0} cannot be overridden by val-property {1}", new PositioningStrategy() { @NotNull @Override - public List getTextRanges(@NotNull Diagnostic diagnostic) { - PsiElement psiElement = ((DiagnosticWithPsiElement) diagnostic).getPsiElement(); - JetTypeReference returnTypeRef = null; - ASTNode nameNode = null; - if (psiElement instanceof JetNamedFunction) { - JetFunction function = (JetNamedFunction) psiElement; - returnTypeRef = function.getReturnTypeRef(); - nameNode = getNameNode(function); + public List mark(@NotNull JetProperty property) { + return markNode(property.getValOrVarNode()); + } + }, DescriptorRenderer.TEXT, DescriptorRenderer.TEXT); + + DiagnosticFactory2 ABSTRACT_MEMBER_NOT_IMPLEMENTED = DiagnosticFactory2.create(ERROR, "{0} must be declared abstract or implement abstract member {1}", RENDER_CLASS_OR_OBJECT, DescriptorRenderer.TEXT); + + DiagnosticFactory2 MANY_IMPL_MEMBER_NOT_IMPLEMENTED = DiagnosticFactory2.create(ERROR, "{0} must override {1} because it inherits many implementations of it", RENDER_CLASS_OR_OBJECT, DescriptorRenderer.TEXT); + + DiagnosticFactory2 CONFLICTING_OVERLOADS = DiagnosticFactory2.create(ERROR, "{1} is already defined in ''{0}''", new PositioningStrategy() { + @NotNull + @Override + public List mark(@NotNull JetDeclaration jetDeclaration) { + if (jetDeclaration instanceof JetNamedFunction) { + JetNamedFunction functionElement = (JetNamedFunction) jetDeclaration; + return markRange(new TextRange( + functionElement.getStartOfSignatureElement().getTextRange().getStartOffset(), + functionElement.getEndOfSignatureElement().getTextRange().getEndOffset() + )); } - else if (psiElement instanceof JetProperty) { - JetProperty property = (JetProperty) psiElement; - returnTypeRef = property.getPropertyTypeRef(); - nameNode = getNameNode(property); + else if (jetDeclaration instanceof JetClass) { + // primary constructor + JetClass klass = (JetClass) jetDeclaration; + PsiElement nameAsDeclaration = klass.getNameIdentifier(); + if (nameAsDeclaration == null) { + return markRange(klass.getTextRange()); + } + PsiElement primaryConstructorParameterList = klass.getPrimaryConstructorParameterList(); + if (primaryConstructorParameterList == null) { + return markRange(nameAsDeclaration.getTextRange()); + } + return markRange(new TextRange( + nameAsDeclaration.getTextRange().getStartOffset(), + primaryConstructorParameterList.getTextRange().getEndOffset() + )); } - else if (psiElement instanceof JetPropertyAccessor) { - JetPropertyAccessor accessor = (JetPropertyAccessor) psiElement; - returnTypeRef = accessor.getReturnTypeReference(); - nameNode = accessor.getNamePlaceholder().getNode(); + else { + // safe way + return markRange(jetDeclaration.getTextRange()); } - if (returnTypeRef != null) return Collections.singletonList(returnTypeRef.getTextRange()); - if (nameNode != null) return Collections.singletonList(nameNode.getTextRange()); - return super.getTextRanges(diagnostic); } - - private ASTNode getNameNode(JetNamedDeclaration function) { - PsiElement nameIdentifier = function.getNameIdentifier(); - return nameIdentifier == null ? null : nameIdentifier.getNode(); - } - - @Override - protected String makeMessageForA(@NotNull CallableMemberDescriptor callableMemberDescriptor) { - return DescriptorRenderer.TEXT.render(callableMemberDescriptor); - } - - @Override - protected String makeMessageForB(@NotNull CallableMemberDescriptor callableMemberDescriptor) { - return DescriptorRenderer.TEXT.render(callableMemberDescriptor); - } - }; - - ParameterizedDiagnosticFactory2 VAR_OVERRIDDEN_BY_VAL = new ParameterizedDiagnosticFactory2(ERROR, "Var-property {0} cannot be overridden by val-property {1}", DescriptorRenderer.TEXT); - - ParameterizedDiagnosticFactory2 ABSTRACT_MEMBER_NOT_IMPLEMENTED = new ParameterizedDiagnosticFactory2(ERROR, "{0} must be declared abstract or implement abstract member {1}") { - @Override - protected String makeMessageForA(@NotNull JetClassOrObject jetClassOrObject) { - String name = jetClassOrObject.getName() != null ? " '" + jetClassOrObject.getName() + "'" : ""; - if (jetClassOrObject instanceof JetClass) { - return "Class" + name; - } - return "Object" + name; - } - - @Override - protected String makeMessageForB(@NotNull CallableMemberDescriptor memberDescriptor) { - return DescriptorRenderer.TEXT.render(memberDescriptor); - } - }; - - ParameterizedDiagnosticFactory2 MANY_IMPL_MEMBER_NOT_IMPLEMENTED = new ParameterizedDiagnosticFactory2(ERROR, "Class ''{0}'' must override {1} because it inherits many implementations of it") { - @Override - protected String makeMessageForA(@NotNull JetClassOrObject jetClassOrObject) { - return jetClassOrObject.getName(); - } - - @Override - protected String makeMessageForB(@NotNull CallableMemberDescriptor memberDescriptor) { - return DescriptorRenderer.TEXT.render(memberDescriptor); - } - }; - - FunctionSignatureDiagnosticFactory CONFLICTING_OVERLOADS = new FunctionSignatureDiagnosticFactory(ERROR, "{1} is already defined in ''{0}''"); + }, DescriptorRenderer.TEXT, TO_STRING); - ParameterizedDiagnosticFactory3 RESULT_TYPE_MISMATCH = ParameterizedDiagnosticFactory3.create(ERROR, "{0} must return {1} but returns {2}"); - ParameterizedDiagnosticFactory3 UNSAFE_INFIX_CALL = ParameterizedDiagnosticFactory3.create(ERROR, "Infix call corresponds to a dot-qualified call ''{0}.{1}({2})'' which is not allowed on a nullable receiver ''{0}''. Use '?.'-qualified call instead"); + DiagnosticFactory3 RESULT_TYPE_MISMATCH = DiagnosticFactory3.create(ERROR, "{0} must return {1} but returns {2}"); + DiagnosticFactory3 UNSAFE_INFIX_CALL = DiagnosticFactory3.create(ERROR, "Infix call corresponds to a dot-qualified call ''{0}.{1}({2})'' which is not allowed on a nullable receiver ''{0}''. Use '?.'-qualified call instead"); AmbiguousDescriptorDiagnosticFactory OVERLOAD_RESOLUTION_AMBIGUITY = new AmbiguousDescriptorDiagnosticFactory("Overload resolution ambiguity: {0}"); AmbiguousDescriptorDiagnosticFactory NONE_APPLICABLE = new AmbiguousDescriptorDiagnosticFactory("None of the following functions can be called with the arguments supplied: {0}"); - ParameterizedDiagnosticFactory1 NO_VALUE_FOR_PARAMETER = ParameterizedDiagnosticFactory1.create(ERROR, "No value passed for parameter {0}", DescriptorRenderer.TEXT); - ParameterizedDiagnosticFactory1 MISSING_RECEIVER = ParameterizedDiagnosticFactory1.create(ERROR, "A receiver of type {0} is required"); - SimpleDiagnosticFactory NO_RECEIVER_ADMITTED = SimpleDiagnosticFactory.create(ERROR, "No receiver can be passed to this function or property"); + DiagnosticFactory1 NO_VALUE_FOR_PARAMETER = DiagnosticFactory1.create(ERROR, "No value passed for parameter {0}", DescriptorRenderer.TEXT); + DiagnosticFactory1 MISSING_RECEIVER = DiagnosticFactory1.create(ERROR, "A receiver of type {0} is required"); + DiagnosticFactory NO_RECEIVER_ADMITTED = DiagnosticFactory.create(ERROR, "No receiver can be passed to this function or property"); - SimpleDiagnosticFactory CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS = SimpleDiagnosticFactory.create(ERROR, "Can not create an instance of an abstract class"); - ParameterizedDiagnosticFactory1 TYPE_INFERENCE_FAILED = ParameterizedDiagnosticFactory1.create(ERROR, "Type inference failed: {0}"); - ParameterizedDiagnosticFactory1 WRONG_NUMBER_OF_TYPE_ARGUMENTS = new ParameterizedDiagnosticFactory1(ERROR, "{0} type arguments expected") { + DiagnosticFactory CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS = DiagnosticFactory.create(ERROR, "Can not create an instance of an abstract class"); + DiagnosticFactory1 TYPE_INFERENCE_FAILED = DiagnosticFactory1.create(ERROR, "Type inference failed: {0}"); + DiagnosticFactory1 WRONG_NUMBER_OF_TYPE_ARGUMENTS = DiagnosticFactory1.create(ERROR, "{0} type arguments expected", new Renderer() { + @NotNull @Override - protected String makeMessageFor(@NotNull Integer argument) { + public String render(@Nullable Integer argument) { + assert argument != null; return argument == 0 ? "No" : argument.toString(); } - }; + }); - ParameterizedDiagnosticFactory1 UNRESOLVED_IDE_TEMPLATE = new ParameterizedDiagnosticFactory1(ERROR, "Unresolved IDE template: {0}"); + DiagnosticFactory1 UNRESOLVED_IDE_TEMPLATE = DiagnosticFactory1.create(ERROR, "Unresolved IDE template: {0}"); - SimpleDiagnosticFactory DANGLING_FUNCTION_LITERAL_ARGUMENT_SUSPECTED = SimpleDiagnosticFactory.create(WARNING, "This expression is treated as an argument to the function call on the previous line. " + - "Separate it with a semicolon (;) if it is not intended to be an argument."); + DiagnosticFactory DANGLING_FUNCTION_LITERAL_ARGUMENT_SUSPECTED = DiagnosticFactory.create(WARNING, "This expression is treated as an argument to the function call on the previous line. " + + "Separate it with a semicolon (;) if it is not intended to be an argument."); // This field is needed to make the Initializer class load (interfaces cannot have static initializers) @SuppressWarnings("UnusedDeclaration") Initializer __initializer = Initializer.INSTANCE; + class Initializer { static { for (Field field : Errors.class.getFields()) { @@ -505,15 +460,16 @@ public interface Errors { AbstractDiagnosticFactory factory = (AbstractDiagnosticFactory) value; factory.setName(field.getName()); } - } - catch (IllegalAccessException e) { + } catch (IllegalAccessException e) { throw new IllegalStateException(e); } } } } + private static final Initializer INSTANCE = new Initializer(); - private Initializer() {}; + + private Initializer() { + } } - } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/FunctionSignatureDiagnosticFactory.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/FunctionSignatureDiagnosticFactory.java deleted file mode 100644 index e4a9dcdfe4c..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/FunctionSignatureDiagnosticFactory.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2010-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.jet.lang.diagnostics; - -import com.intellij.openapi.util.TextRange; -import com.intellij.psi.PsiElement; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor; -import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; -import org.jetbrains.jet.lang.psi.JetClass; -import org.jetbrains.jet.lang.psi.JetDeclaration; -import org.jetbrains.jet.lang.psi.JetNamedFunction; -import org.jetbrains.jet.resolve.DescriptorRenderer; - -/** - * @author Stepan Koltsov - */ -public class FunctionSignatureDiagnosticFactory extends DiagnosticFactoryWithMessageFormat { - - public FunctionSignatureDiagnosticFactory(Severity severity, String messageTemplate) { - super(severity, messageTemplate); - } - - private TextRange rangeToMark(JetDeclaration jetDeclaration) { - if (jetDeclaration instanceof JetNamedFunction) { - JetNamedFunction functionElement = (JetNamedFunction) jetDeclaration; - return new TextRange( - functionElement.getStartOfSignatureElement().getTextRange().getStartOffset(), - functionElement.getEndOfSignatureElement().getTextRange().getEndOffset() - ); - } else if (jetDeclaration instanceof JetClass) { - // primary constructor - JetClass klass = (JetClass) jetDeclaration; - PsiElement nameAsDeclaration = klass.getNameIdentifier(); - if (nameAsDeclaration == null){ - return klass.getTextRange(); - } - PsiElement primaryConstructorParameterList = klass.getPrimaryConstructorParameterList(); - if (primaryConstructorParameterList == null) { - return nameAsDeclaration.getTextRange(); - } - return new TextRange( - nameAsDeclaration.getTextRange().getStartOffset(), - primaryConstructorParameterList.getTextRange().getEndOffset() - ); - } else { - // safe way - return jetDeclaration.getTextRange(); - } - } - - @NotNull - public Diagnostic on(@NotNull JetDeclaration declaration, @NotNull CallableMemberDescriptor functionDescriptor, - @NotNull String functionContainer) - { - TextRange rangeToMark = rangeToMark(declaration); - - String message = messageFormat.format(new Object[]{ - functionContainer, - DescriptorRenderer.TEXT.render(functionDescriptor)}); - return new GenericDiagnostic(this, severity, message, declaration.getContainingFile(), rangeToMark); - } - -} //~ diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory1.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory1.java deleted file mode 100644 index 400496565c2..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory1.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2010-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.jet.lang.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; - -/** -* @author abreslav -*/ -public class ParameterizedDiagnosticFactory1 extends DiagnosticFactoryWithPsiElement1 { - public static ParameterizedDiagnosticFactory1 create(Severity severity, String messageStub) { - return new ParameterizedDiagnosticFactory1(severity, messageStub); - } - - public static ParameterizedDiagnosticFactory1 create(Severity severity, String messageStub, Renderer renderer) { - return new ParameterizedDiagnosticFactory1(severity, messageStub, renderer); - } - - public ParameterizedDiagnosticFactory1(Severity severity, String message, Renderer renderer) { - super(severity, message, renderer); - } - - public ParameterizedDiagnosticFactory1(Severity severity, String message) { - super(severity, message); - } - - @NotNull - public Diagnostic on(@NotNull PsiFile psiFile, @NotNull TextRange rangeToMark, @NotNull A argument) { - return new GenericDiagnostic(this, severity, makeMessage(argument), psiFile, rangeToMark); - } - - @NotNull - public Diagnostic on(@NotNull ASTNode nodeToMark, @NotNull A argument) { - return on(DiagnosticUtils.getContainingFile(nodeToMark), nodeToMark.getTextRange(), argument); - } -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory2.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory2.java deleted file mode 100644 index f270869183a..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory2.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2010-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.jet.lang.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; - -/** -* @author abreslav -*/ -public class ParameterizedDiagnosticFactory2 extends DiagnosticFactoryWithPsiElement2 { - public static ParameterizedDiagnosticFactory2 create(Severity severity, String messageStub) { - return new ParameterizedDiagnosticFactory2(severity, messageStub); - } - - public static ParameterizedDiagnosticFactory2 create(Severity severity, String messageStub, Renderer renderer) { - return new ParameterizedDiagnosticFactory2(severity, messageStub, renderer); - } - - public ParameterizedDiagnosticFactory2(Severity severity, String message, Renderer renderer) { - super(severity, message, renderer); - } - - public ParameterizedDiagnosticFactory2(Severity severity, String messageStub) { - super(severity, messageStub); - } - - @NotNull - public Diagnostic on(@NotNull PsiFile psiFile, @NotNull TextRange rangeToMark, @NotNull A a, @NotNull B b) { - return new GenericDiagnostic(this, severity, makeMessage(a, b), psiFile, rangeToMark); - } - - @NotNull - public Diagnostic on(@NotNull ASTNode nodeToMark, @NotNull A a, @NotNull B b) { - return on(DiagnosticUtils.getContainingFile(nodeToMark), nodeToMark.getTextRange(), a, b); - } - -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory3.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory3.java deleted file mode 100644 index 6d9983fc40a..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory3.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2010-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.jet.lang.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; - -/** -* @author abreslav -*/ -public class ParameterizedDiagnosticFactory3 extends DiagnosticFactoryWithPsiElement3 { - public static ParameterizedDiagnosticFactory3 create(Severity severity, String messageStub) { - return new ParameterizedDiagnosticFactory3(severity, messageStub); - } - - public static ParameterizedDiagnosticFactory3 create(Severity severity, String messageStub, Renderer renderer) { - return new ParameterizedDiagnosticFactory3(severity, messageStub, renderer); - } - - public ParameterizedDiagnosticFactory3(Severity severity, String messageStub, Renderer renderer) { - super(severity, messageStub, renderer); - } - - protected ParameterizedDiagnosticFactory3(Severity severity, String messageStub) { - super(severity, messageStub); - } - - @NotNull - public Diagnostic on(@NotNull PsiFile psiFile, @NotNull TextRange rangeToMark, @NotNull A a, @NotNull B b, @NotNull C c) { - return new GenericDiagnostic(this, severity, makeMessage(a, b, c), psiFile, rangeToMark); - } - - @NotNull - public Diagnostic on(@NotNull ASTNode nodeToMark, @NotNull A a, @NotNull B b, @NotNull C c) { - return on(DiagnosticUtils.getContainingFile(nodeToMark), nodeToMark.getTextRange(), a, b, c); - } -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategies.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategies.java new file mode 100644 index 00000000000..79c4b015cd3 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategies.java @@ -0,0 +1,126 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.diagnostics; + + +import com.intellij.lang.ASTNode; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiNameIdentifierOwner; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lexer.JetKeywordToken; +import org.jetbrains.jet.lexer.JetTokens; + +import java.util.Collections; +import java.util.List; + +/** + * @author svtk + */ +public class PositioningStrategies { + + public static final PositioningStrategy DEFAULT = new PositioningStrategy(); + + public static final PositioningStrategy MARK_FUNCTION = new PositioningStrategy() { + @NotNull + @Override + public List mark(@NotNull JetFunction function) { + TextRange textRange; + PsiElement nameIdentifier = function.getNameIdentifier(); + JetTypeReference returnTypeRef = function.getReturnTypeRef(); + JetParameterList valueParameterList = function.getValueParameterList(); + if (nameIdentifier == null) { + textRange = TextRange.from(function.getTextRange().getEndOffset(), 0); + } + else if (returnTypeRef != null) { + textRange = TextRange.from(returnTypeRef.getTextRange().getEndOffset(), 1); + } + else if (valueParameterList != null) { + textRange = TextRange.from(valueParameterList.getTextRange().getEndOffset(), 1); + } + else { + textRange = TextRange.from(nameIdentifier.getTextRange().getEndOffset(), 1); + } + return markRange(textRange); + + } + }; + + public static final PositioningStrategy POSITION_DECLARATION = new PositioningStrategy() { + @NotNull + @Override + public List mark(@NotNull JetDeclaration declaration) { + JetTypeReference returnTypeRef = null; + ASTNode nameNode = null; + if (declaration instanceof JetNamedFunction) { + JetFunction function = (JetNamedFunction) declaration; + returnTypeRef = function.getReturnTypeRef(); + nameNode = getNameNode(function); + } + else if (declaration instanceof JetProperty) { + JetProperty property = (JetProperty) declaration; + returnTypeRef = property.getPropertyTypeRef(); + nameNode = getNameNode(property); + } + else if (declaration instanceof JetPropertyAccessor) { + JetPropertyAccessor accessor = (JetPropertyAccessor) declaration; + returnTypeRef = accessor.getReturnTypeReference(); + nameNode = accessor.getNamePlaceholder().getNode(); + } + if (returnTypeRef != null) return Collections.singletonList(returnTypeRef.getTextRange()); + if (nameNode != null) return Collections.singletonList(nameNode.getTextRange()); + return super.mark(declaration); + + } + private ASTNode getNameNode(JetNamedDeclaration function) { + PsiElement nameIdentifier = function.getNameIdentifier(); + return nameIdentifier == null ? null : nameIdentifier.getNode(); + } + }; + + public static final PositioningStrategy POSITION_NAME_IDENTIFIER = new PositioningStrategy() { + @NotNull + @Override + public List mark(@NotNull PsiNameIdentifierOwner element) { + PsiElement nameIdentifier = element.getNameIdentifier(); + if (nameIdentifier != null) { + return markElement(nameIdentifier); + } + return Collections.emptyList(); + } + }; + + public static final PositioningStrategy POSITION_ABSTRACT_MODIFIER = positionModifier(JetTokens.ABSTRACT_KEYWORD); + + public static PositioningStrategy positionModifier(final JetKeywordToken token) { + return new PositioningStrategy() { + @NotNull + @Override + public List mark(@NotNull JetModifierListOwner modifierListOwner) { + if (modifierListOwner.hasModifier(token)) { + JetModifierList modifierList = modifierListOwner.getModifierList(); + assert modifierList != null; + ASTNode node = modifierList.getModifierNode(token); + assert node != null; + return Collections.singletonList(node.getTextRange()); + } + return Collections.emptyList(); + } + }; + } +} \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/SimpleDiagnosticFactory.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategy.java similarity index 52% rename from compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/SimpleDiagnosticFactory.java rename to compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategy.java index e81794949b9..4e371dbbee8 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/SimpleDiagnosticFactory.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PositioningStrategy.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2012 JetBrains s.r.o. + * Copyright 2000-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. @@ -19,28 +19,32 @@ 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; +import java.util.Collections; +import java.util.List; + /** -* @author abreslav +* @author svtk */ -public class SimpleDiagnosticFactory extends SimpleDiagnosticFactoryWithPsiElement { - public static SimpleDiagnosticFactory create(Severity severity, String message) { - return new SimpleDiagnosticFactory(severity, message); - } - - protected SimpleDiagnosticFactory(Severity severity, String message) { - super(severity, message); +public class PositioningStrategy

{ + @NotNull + public List mark(@NotNull P element) { + return markElement(element); } @NotNull - public Diagnostic on(@NotNull PsiFile psiFile, @NotNull TextRange range) { - return new GenericDiagnostic(this, severity, message, psiFile, range); + protected static List markElement(@NotNull PsiElement element) { + return Collections.singletonList(element.getTextRange()); } @NotNull - public Diagnostic on(@NotNull ASTNode node) { - return on(DiagnosticUtils.getContainingFile(node), node.getTextRange()); + protected static List markNode(@NotNull ASTNode node) { + return Collections.singletonList(node.getTextRange()); + } + + @NotNull + protected static List markRange(@NotNull TextRange range) { + return Collections.singletonList(range); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PsiElementOnlyDiagnosticFactory.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PsiElementOnlyDiagnosticFactory.java deleted file mode 100644 index c14dd58c219..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PsiElementOnlyDiagnosticFactory.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2010-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.jet.lang.diagnostics; - -import com.intellij.psi.PsiElement; - -/** - * @author svtk - */ -public interface PsiElementOnlyDiagnosticFactory extends DiagnosticFactory { -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PsiElementOnlyDiagnosticFactory1.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PsiElementOnlyDiagnosticFactory1.java deleted file mode 100644 index 3510eea45ea..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PsiElementOnlyDiagnosticFactory1.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2010-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.jet.lang.diagnostics; - -import com.intellij.psi.PsiElement; -/** - * @author svtk - */ -public class PsiElementOnlyDiagnosticFactory1 extends DiagnosticFactoryWithPsiElement1 implements PsiElementOnlyDiagnosticFactory { - public static PsiElementOnlyDiagnosticFactory1 create(Severity severity, String messageStub) { - return new PsiElementOnlyDiagnosticFactory1(severity, messageStub); - } - - public static PsiElementOnlyDiagnosticFactory1 create(Severity severity, String messageStub, Renderer renderer) { - return new PsiElementOnlyDiagnosticFactory1(severity, messageStub, renderer); - } - - public PsiElementOnlyDiagnosticFactory1(Severity severity, String message, Renderer renderer) { - super(severity, message, renderer); - } - - protected PsiElementOnlyDiagnosticFactory1(Severity severity, String message) { - super(severity, message); - } -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PsiElementOnlyDiagnosticFactory2.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PsiElementOnlyDiagnosticFactory2.java deleted file mode 100644 index a9d35c3e731..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PsiElementOnlyDiagnosticFactory2.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2010-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.jet.lang.diagnostics; - -import com.intellij.psi.PsiElement; - -/** - * @author svtk - */ -public class PsiElementOnlyDiagnosticFactory2 extends DiagnosticFactoryWithPsiElement2 implements PsiElementOnlyDiagnosticFactory { - public static PsiElementOnlyDiagnosticFactory2 create(Severity severity, String messageStub, Renderer renderer) { - return new PsiElementOnlyDiagnosticFactory2(severity, messageStub, renderer); - } - - public static PsiElementOnlyDiagnosticFactory2 create(Severity severity, String messageStub) { - return new PsiElementOnlyDiagnosticFactory2(severity, messageStub); - } - - public PsiElementOnlyDiagnosticFactory2(Severity severity, String message, Renderer renderer) { - super(severity, message, renderer); - } - - protected PsiElementOnlyDiagnosticFactory2(Severity severity, String message) { - super(severity, message); - } -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PsiElementOnlyDiagnosticFactory3.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PsiElementOnlyDiagnosticFactory3.java deleted file mode 100644 index f0b3cb1c8b3..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PsiElementOnlyDiagnosticFactory3.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2010-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.jet.lang.diagnostics; - -import com.intellij.psi.PsiElement; -/** - * @author svtk - */ -public class PsiElementOnlyDiagnosticFactory3 extends DiagnosticFactoryWithPsiElement3 implements PsiElementOnlyDiagnosticFactory { - public static PsiElementOnlyDiagnosticFactory3 create(Severity severity, String messageStub) { - return new PsiElementOnlyDiagnosticFactory3(severity, messageStub); - } - - public static PsiElementOnlyDiagnosticFactory3 create(Severity severity, String messageStub, Renderer renderer) { - return new PsiElementOnlyDiagnosticFactory3(severity, messageStub, renderer); - } - - protected PsiElementOnlyDiagnosticFactory3(Severity severity, String messageStub) { - super(severity, messageStub); - } - - public PsiElementOnlyDiagnosticFactory3(Severity severity, String messageStub, Renderer renderer) { - super(severity, messageStub, renderer); - } -} 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 cb5646ab8dc..90ab6e7df87 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/RedeclarationDiagnostic.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/RedeclarationDiagnostic.java @@ -21,21 +21,31 @@ 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.psi.JetFile; +import org.jetbrains.jet.lang.psi.JetNamedDeclaration; import org.jetbrains.jet.lang.resolve.BindingContext; +import java.util.List; + /** * @author abreslav */ -public interface RedeclarationDiagnostic extends DiagnosticWithPsiElement { - public class SimpleRedeclarationDiagnostic extends DiagnosticWithPsiElementImpl implements RedeclarationDiagnostic { +public interface RedeclarationDiagnostic extends Diagnostic { + class SimpleRedeclarationDiagnostic extends AbstractDiagnostic implements RedeclarationDiagnostic { public SimpleRedeclarationDiagnostic(@NotNull PsiElement psiElement, @NotNull String name, RedeclarationDiagnosticFactory factory) { - super(factory, factory.severity, factory.makeMessage(name), psiElement); + super(psiElement, factory, factory.severity, factory.makeMessage(name)); + } + + @NotNull + @Override + public List getTextRanges() { + return POSITION_REDECLARATION.mark(getPsiElement()); } } - public class RedeclarationDiagnosticWithDeferredResolution implements RedeclarationDiagnostic { - + class RedeclarationDiagnosticWithDeferredResolution implements RedeclarationDiagnostic { + private final DeclarationDescriptor duplicatingDescriptor; private final BindingContext contextToResolveToDeclaration; private final RedeclarationDiagnosticFactory factory; @@ -54,7 +64,7 @@ public interface RedeclarationDiagnostic extends DiagnosticWithPsiElement getTextRanges() { + return POSITION_REDECLARATION.mark(getPsiElement()); } @NotNull @@ -75,7 +85,7 @@ public interface RedeclarationDiagnostic extends DiagnosticWithPsiElement DiagnosticWithPsiElement add(DiagnosticParameter

parameterType, P parameter) { - throw new UnsupportedOperationException(); - } } + PositioningStrategy POSITION_REDECLARATION = new PositioningStrategy() { + @NotNull + @Override + public List mark(@NotNull PsiElement element) { + if (element instanceof JetNamedDeclaration) { + PsiElement nameIdentifier = ((JetNamedDeclaration) element).getNameIdentifier(); + if (nameIdentifier != null) { + return markElement(nameIdentifier); + } + } + else if (element instanceof JetFile) { + JetFile file = (JetFile) element; + PsiElement nameIdentifier = file.getNamespaceHeader().getNameIdentifier(); + if (nameIdentifier != null) { + return markElement(nameIdentifier); + } + } + return markElement(element); + } + }; } 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 e683f8d0f73..7961088eb91 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/RedeclarationDiagnosticFactory.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/RedeclarationDiagnosticFactory.java @@ -55,26 +55,6 @@ public class RedeclarationDiagnosticFactory extends AbstractDiagnosticFactory { return new RedeclarationDiagnostic.RedeclarationDiagnosticWithDeferredResolution(duplicatingDescriptor, contextToResolveToDeclaration, this); } - @NotNull - @Override - public List getTextRanges(@NotNull Diagnostic diagnostic) { - PsiElement redeclaration = ((RedeclarationDiagnostic) diagnostic).getPsiElement(); - if (redeclaration instanceof JetNamedDeclaration) { - PsiElement nameIdentifier = ((JetNamedDeclaration) redeclaration).getNameIdentifier(); - if (nameIdentifier != null) { - return Collections.singletonList(nameIdentifier.getTextRange()); - } - } - else if (redeclaration instanceof JetFile) { - JetFile file = (JetFile) redeclaration; - PsiElement nameIdentifier = file.getNamespaceHeader().getNameIdentifier(); - if (nameIdentifier != null) { - return Collections.singletonList(nameIdentifier.getTextRange()); - } - } - return Collections.singletonList(redeclaration.getTextRange()); - } - @NotNull @Override public String getName() { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Renderer.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Renderer.java index df6a87cab40..3d427e03be6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Renderer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Renderer.java @@ -16,26 +16,15 @@ package org.jetbrains.jet.lang.diagnostics; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** * @author abreslav */ -public interface Renderer { - Renderer TO_STRING = new Renderer() { - @NotNull - @Override - public String render(@Nullable Object object) { - return object == null ? "null" : object.toString(); - } - - @Override - public String toString() { - return "TO_STRING"; - } - }; +public interface Renderer

{ @NotNull - String render(@Nullable Object object); + String render(@Nullable P element); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Renderers.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Renderers.java new file mode 100644 index 00000000000..7391db5ad99 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Renderers.java @@ -0,0 +1,77 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.diagnostics; + +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.Named; +import org.jetbrains.jet.lang.psi.JetClass; +import org.jetbrains.jet.lang.psi.JetClassOrObject; + +/** + * @author svtk + */ +public class Renderers { + public static final Renderer TO_STRING = new Renderer() { + @NotNull + @Override + public String render(@Nullable Object element) { + return element == null ? "null" : element.toString(); + } + + @Override + public String toString() { + return "TO_STRING"; + } + }; + + public static final Renderer NAME = new Renderer() { + @NotNull + @Override + public String render(@Nullable Object element) { + if (element == null) return "null"; + if (element instanceof Named) { + return ((Named) element).getName(); + } + return element.toString(); + } + }; + + public static final Renderer ELEMENT_TEXT = new Renderer() { + @NotNull + @Override + public String render(@Nullable PsiElement element) { + if (element == null) return "null"; + return element.getText(); + } + }; + + public static final Renderer RENDER_CLASS_OR_OBJECT = new Renderer() { + @NotNull + @Override + public String render(@Nullable JetClassOrObject classOrObject) { + assert classOrObject != null; + String name = classOrObject.getName() != null ? " '" + classOrObject.getName() + "'" : ""; + if (classOrObject instanceof JetClass) { + return "Class" + name; + } + return "Object" + name; + + } + }; +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/SimpleDiagnosticFactoryWithPsiElement.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/SimpleDiagnosticFactoryWithPsiElement.java deleted file mode 100644 index febfb8d7c55..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/SimpleDiagnosticFactoryWithPsiElement.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2010-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.jet.lang.diagnostics; - -import com.intellij.lang.ASTNode; -import com.intellij.openapi.util.TextRange; -import com.intellij.psi.PsiElement; -import org.jetbrains.annotations.NotNull; - -/** - * @author svtk - */ -public abstract class SimpleDiagnosticFactoryWithPsiElement extends DiagnosticFactoryWithSeverity { - - protected final String message; - - protected SimpleDiagnosticFactoryWithPsiElement(Severity severity, String message) { - super(severity); - this.message = message; - } - - private Diagnostic on(@NotNull T elementToBlame, @NotNull TextRange textRange) { - return new DiagnosticWithPsiElementImpl(this, severity, message, elementToBlame, textRange); - } - - @NotNull - public Diagnostic on(@NotNull T elementToBlame, @NotNull ASTNode nodeToMark) { - return on(elementToBlame, nodeToMark.getTextRange()); - } - - @NotNull - public Diagnostic on(@NotNull T elementToBlame, @NotNull PsiElement elementToMark) { - return on(elementToBlame, elementToMark.getTextRange()); - } - - @NotNull - public Diagnostic on(@NotNull T element) { - return on(element, getTextRange(element)); - } - - @NotNull - public TextRange getTextRange(@NotNull T element) { - return element.getTextRange(); - } -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/SimplePsiElementOnlyDiagnosticFactory.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/SimplePsiElementOnlyDiagnosticFactory.java deleted file mode 100644 index 791db5c241d..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/SimplePsiElementOnlyDiagnosticFactory.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2010-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.jet.lang.diagnostics; - -import com.intellij.psi.PsiElement; - -/** - * @author svtk - */ -public class SimplePsiElementOnlyDiagnosticFactory extends SimpleDiagnosticFactoryWithPsiElement implements PsiElementOnlyDiagnosticFactory { - - public static SimplePsiElementOnlyDiagnosticFactory create(Severity severity, String message) { - return new SimplePsiElementOnlyDiagnosticFactory(severity, message); - } - - protected SimplePsiElementOnlyDiagnosticFactory(Severity severity, String message) { - super(severity, message); - } -} 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 31ac8c2c7c5..8b1f2242987 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/UnresolvedReferenceDiagnostic.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/UnresolvedReferenceDiagnostic.java @@ -16,18 +16,23 @@ package org.jetbrains.jet.lang.diagnostics; +import com.intellij.openapi.util.TextRange; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.psi.JetArrayAccessExpression; import org.jetbrains.jet.lang.psi.JetReferenceExpression; +import java.util.Collections; +import java.util.List; + import static org.jetbrains.jet.lang.diagnostics.Severity.ERROR; /** -* @author abreslav -*/ -public class UnresolvedReferenceDiagnostic extends DiagnosticWithPsiElementImpl { + * @author abreslav + */ +public class UnresolvedReferenceDiagnostic extends AbstractDiagnostic { public UnresolvedReferenceDiagnostic(JetReferenceExpression referenceExpression, String message) { - super(Errors.UNRESOLVED_REFERENCE, ERROR, message, referenceExpression); + super(referenceExpression, Errors.UNRESOLVED_REFERENCE, ERROR, message); } @NotNull @@ -35,4 +40,14 @@ public class UnresolvedReferenceDiagnostic extends DiagnosticWithPsiElementImpl< public String getMessage() { return super.getMessage() + ": " + getPsiElement().getText(); } + + @NotNull + @Override + public List getTextRanges() { + JetReferenceExpression element = getPsiElement(); + if (element instanceof JetArrayAccessExpression) { + return ((JetArrayAccessExpression) element).getBracketRanges(); + } + return Collections.singletonList(element.getTextRange()); + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/UnresolvedReferenceDiagnosticFactory.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/UnresolvedReferenceDiagnosticFactory.java index 32d3f8e7ede..ddec486cf56 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/UnresolvedReferenceDiagnosticFactory.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/UnresolvedReferenceDiagnosticFactory.java @@ -17,6 +17,7 @@ package org.jetbrains.jet.lang.diagnostics; import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.psi.JetArrayAccessExpression; import org.jetbrains.jet.lang.psi.JetReferenceExpression; @@ -27,12 +28,11 @@ import java.util.List; /** * @author abreslav */ -public class UnresolvedReferenceDiagnosticFactory extends AbstractDiagnosticFactory - implements PsiElementOnlyDiagnosticFactory { +public class UnresolvedReferenceDiagnosticFactory extends AbstractDiagnosticFactory { private final String message; - public UnresolvedReferenceDiagnosticFactory(String message) { + private UnresolvedReferenceDiagnosticFactory(String message) { this.message = message; } @@ -40,15 +40,7 @@ public class UnresolvedReferenceDiagnosticFactory extends AbstractDiagnosticFact return new UnresolvedReferenceDiagnostic(reference, message); } - @NotNull - @Override - public List getTextRanges(@NotNull Diagnostic diagnostic) { - if (diagnostic instanceof UnresolvedReferenceDiagnostic) { - JetReferenceExpression element = ((UnresolvedReferenceDiagnostic) diagnostic).getPsiElement(); - if (element instanceof JetArrayAccessExpression) { - return ((JetArrayAccessExpression)element).getBracketRanges(); - } - } - return super.getTextRanges(diagnostic); + public static UnresolvedReferenceDiagnosticFactory create(String message) { + return new UnresolvedReferenceDiagnosticFactory(message); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/UnusedElementDiagnosticFactory.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/UnusedElementDiagnosticFactory.java index b3cf4a619a9..19a297fd9be 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/UnusedElementDiagnosticFactory.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/UnusedElementDiagnosticFactory.java @@ -20,20 +20,24 @@ import com.intellij.psi.PsiElement; /** * @author svtk */ -public class UnusedElementDiagnosticFactory extends PsiElementOnlyDiagnosticFactory1 { - public static UnusedElementDiagnosticFactory create(Severity severity, String messageStub) { - return new UnusedElementDiagnosticFactory(severity, messageStub); +public class UnusedElementDiagnosticFactory extends DiagnosticFactory1 { + private UnusedElementDiagnosticFactory(Severity severity, String message, PositioningStrategy positioningStrategy, Renderer renderer) { + super(severity, message, positioningStrategy, renderer); } - public static UnusedElementDiagnosticFactory create(Severity severity, String messageStub, Renderer renderer) { - return new UnusedElementDiagnosticFactory(severity, messageStub, renderer); + public static UnusedElementDiagnosticFactory create(Severity severity, String message, PositioningStrategy positioningStrategy, Renderer renderer) { + return new UnusedElementDiagnosticFactory(severity, message, positioningStrategy, renderer); } - public UnusedElementDiagnosticFactory(Severity severity, String message, Renderer renderer) { - super(severity, message, renderer); + public static UnusedElementDiagnosticFactory create(Severity severity, String message, PositioningStrategy positioningStrategy) { + return create(severity, message, positioningStrategy, Renderers.TO_STRING); } - protected UnusedElementDiagnosticFactory(Severity severity, String message) { - super(severity, message); + public static UnusedElementDiagnosticFactory create(Severity severity, String message, Renderer renderer) { + return create(severity, message, PositioningStrategies.DEFAULT, renderer); + } + + public static UnusedElementDiagnosticFactory create(Severity severity, String message) { + return create(severity, message, PositioningStrategies.DEFAULT, Renderers.TO_STRING); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/Call.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/Call.java index 700039654ae..4d5a1fa5937 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/Call.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/Call.java @@ -55,8 +55,5 @@ public interface Call { JetTypeArgumentList getTypeArgumentList(); @NotNull - ASTNode getCallNode(); - - @Nullable PsiElement getCallElement(); } 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 81a522c3254..bb1f8bd9278 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java @@ -61,8 +61,8 @@ public class AnalyzingUtils { }); } - public static List getSyntaxErrorRanges(@NotNull PsiElement root) { - final ArrayList r = new ArrayList(); + public static List getSyntaxErrorRanges(@NotNull PsiElement root) { + final ArrayList r = new ArrayList(); root.acceptChildren(new PsiElementVisitor() { @Override public void visitElement(PsiElement element) { @@ -71,7 +71,7 @@ public class AnalyzingUtils { @Override public void visitErrorElement(PsiErrorElement element) { - r.add(element.getTextRange()); + r.add(element); } }); return r; 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 f5f247abb66..9b2c69aaba3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java @@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.resolve; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.util.containers.Queue; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.*; @@ -130,9 +131,9 @@ public class BodyResolver { @Override public void visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call) { JetValueArgumentList valueArgumentList = call.getValueArgumentList(); - ASTNode node = valueArgumentList == null ? call.getNode() : valueArgumentList.getNode(); + PsiElement elementToMark = valueArgumentList == null ? call : valueArgumentList; if (descriptor.getKind() == ClassKind.TRAIT) { - context.getTrace().report(SUPERTYPE_INITIALIZED_IN_TRAIT.on(node)); + context.getTrace().report(SUPERTYPE_INITIALIZED_IN_TRAIT.on(elementToMark)); } JetTypeReference typeReference = call.getTypeReference(); if (typeReference == null) return; @@ -149,7 +150,7 @@ public class BodyResolver { ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype); if (classDescriptor != null) { if (classDescriptor.getKind() == ClassKind.TRAIT) { - context.getTrace().report(CONSTRUCTOR_IN_TRAIT.on(node)); + context.getTrace().report(CONSTRUCTOR_IN_TRAIT.on(elementToMark)); } } } @@ -304,13 +305,14 @@ public class BodyResolver { final CallResolver callResolver = new CallResolver(context.getSemanticServices(), DataFlowInfo.EMPTY); // TODO: dataFlowInfo + PsiElement nameElement = declaration.getNameNode().getPsi(); if (classDescriptor.getUnsubstitutedPrimaryConstructor() == null) { - context.getTrace().report(SECONDARY_CONSTRUCTOR_BUT_NO_PRIMARY.on(declaration.getNameNode())); + context.getTrace().report(SECONDARY_CONSTRUCTOR_BUT_NO_PRIMARY.on(nameElement)); } else { List initializers = declaration.getInitializers(); if (initializers.isEmpty()) { - context.getTrace().report(SECONDARY_CONSTRUCTOR_NO_INITIALIZER_LIST.on(declaration.getNameNode())); + context.getTrace().report(SECONDARY_CONSTRUCTOR_NO_INITIALIZER_LIST.on(nameElement)); } else { initializers.get(0).accept(new JetVisitorVoid() { 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 b67fb28557f..60e4d0e31a7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationResolver.java @@ -189,8 +189,7 @@ public class DeclarationResolver { private void processSecondaryConstructor(MutableClassDescriptor classDescriptor, JetSecondaryConstructor constructor) { if (classDescriptor.getKind() == ClassKind.TRAIT) { -// context.getTrace().getErrorHandler().genericError(constructor.getNameNode(), "A trait may not have a constructor"); - context.getTrace().report(CONSTRUCTOR_IN_TRAIT.on(constructor.getNameNode())); + context.getTrace().report(CONSTRUCTOR_IN_TRAIT.on(constructor.getNameNode().getPsi())); } ConstructorDescriptor constructorDescriptor = context.getDescriptorResolver().resolveSecondaryConstructorDescriptor( classDescriptor.getScopeForMemberResolution(), diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationsChecker.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationsChecker.java index de8956152f8..5a3e5285b59 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationsChecker.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationsChecker.java @@ -33,7 +33,6 @@ import org.jetbrains.jet.lexer.JetKeywordToken; import org.jetbrains.jet.lexer.JetToken; import org.jetbrains.jet.lexer.JetTokens; -import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; @@ -104,13 +103,13 @@ public class DeclarationsChecker { JetModifierList modifierList = aClass.getModifierList(); if (modifierList == null) return; if (modifierList.hasModifier(JetTokens.FINAL_KEYWORD)) { - context.getTrace().report(Errors.TRAIT_CAN_NOT_BE_FINAL.on(aClass, modifierList.getModifierNode(JetTokens.FINAL_KEYWORD))); + context.getTrace().report(Errors.TRAIT_CAN_NOT_BE_FINAL.on(modifierList.getModifierNode(JetTokens.FINAL_KEYWORD).getPsi())); } - ArrayList redundantModifiers = Lists.newArrayList(JetTokens.OPEN_KEYWORD, JetTokens.ABSTRACT_KEYWORD); - for (JetKeywordToken modifier : redundantModifiers) { - if (modifierList.hasModifier(modifier)) { - context.getTrace().report(Errors.REDUNDANT_MODIFIER_IN_TRAIT.on(modifierList, modifierList.getModifierNode(modifier), modifier)); - } + if (modifierList.hasModifier(JetTokens.ABSTRACT_KEYWORD)) { + context.getTrace().report(Errors.ABSTRACT_MODIFIER_IN_TRAIT.on(aClass)); + } + if (modifierList.hasModifier(JetTokens.OPEN_KEYWORD)) { + context.getTrace().report(Errors.OPEN_MODIFIER_IN_TRAIT.on(aClass)); } } @@ -127,7 +126,7 @@ public class DeclarationsChecker { JetModifierList modifierList = member.getModifierList(); assert modifierList != null; ASTNode openModifierNode = modifierList.getModifierNode(JetTokens.OPEN_KEYWORD); - context.getTrace().report(NON_FINAL_MEMBER_IN_FINAL_CLASS.on(member, openModifierNode, aClass)); + context.getTrace().report(NON_FINAL_MEMBER_IN_FINAL_CLASS.on(openModifierNode.getPsi())); } } } @@ -161,7 +160,7 @@ public class DeclarationsChecker { if (returnType instanceof DeferredType) { returnType = ((DeferredType) returnType).getActualType(); } - context.getTrace().report(PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE.on(member, nameIdentifier, returnType)); + context.getTrace().report(PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE.on(nameIdentifier)); } } @@ -173,18 +172,18 @@ public class DeclarationsChecker { if (abstractNode != null) { //has abstract modifier if (classDescriptor == null) { - context.getTrace().report(ABSTRACT_PROPERTY_NOT_IN_CLASS.on(property, abstractNode)); + context.getTrace().report(ABSTRACT_PROPERTY_NOT_IN_CLASS.on(property)); return; } if (!(classDescriptor.getModality() == Modality.ABSTRACT) && classDescriptor.getKind() != ClassKind.ENUM_CLASS) { PsiElement classElement = context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, classDescriptor); assert classElement instanceof JetClass; String name = property.getName(); - context.getTrace().report(ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS.on(property, abstractNode, name != null ? name : "", classDescriptor, (JetClass) classElement)); + context.getTrace().report(ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS.on(property, name != null ? name : "", classDescriptor, (JetClass) classElement)); return; } if (classDescriptor.getKind() == ClassKind.TRAIT) { - context.getTrace().report(REDUNDANT_MODIFIER_IN_TRAIT.on(modifierList, abstractNode, JetTokens.ABSTRACT_KEYWORD)); + context.getTrace().report(ABSTRACT_MODIFIER_IN_TRAIT.on(property)); } } @@ -196,13 +195,13 @@ public class DeclarationsChecker { JetExpression initializer = property.getInitializer(); if (initializer != null) { - context.getTrace().report(ABSTRACT_PROPERTY_WITH_INITIALIZER.on(property, initializer, returnType)); + context.getTrace().report(ABSTRACT_PROPERTY_WITH_INITIALIZER.on(initializer)); } if (getter != null && getter.getBodyExpression() != null) { - context.getTrace().report(ABSTRACT_PROPERTY_WITH_GETTER.on(property, getter, returnType)); + context.getTrace().report(ABSTRACT_PROPERTY_WITH_GETTER.on(getter)); } if (setter != null && setter.getBodyExpression() != null) { - context.getTrace().report(ABSTRACT_PROPERTY_WITH_SETTER.on(property, setter, returnType)); + context.getTrace().report(ABSTRACT_PROPERTY_WITH_SETTER.on(setter)); } } } @@ -229,7 +228,7 @@ public class DeclarationsChecker { context.getTrace().report(MUST_BE_INITIALIZED.on(nameIdentifier)); } else { - context.getTrace().report(MUST_BE_INITIALIZED_OR_BE_ABSTRACT.on(property, nameIdentifier)); + context.getTrace().report(MUST_BE_INITIALIZED_OR_BE_ABSTRACT.on(nameIdentifier)); } } return; @@ -239,7 +238,7 @@ public class DeclarationsChecker { if (returnType instanceof DeferredType) { returnType = ((DeferredType) returnType).getActualType(); } - context.getTrace().report(PROPERTY_INITIALIZER_IN_TRAIT.on(property, initializer, returnType)); + context.getTrace().report(PROPERTY_INITIALIZER_IN_TRAIT.on(initializer)); } else if (!backingFieldRequired) { context.getTrace().report(PROPERTY_INITIALIZER_NO_BACKING_FIELD.on(initializer)); @@ -261,24 +260,24 @@ public class DeclarationsChecker { if (hasAbstractModifier && !inAbstractClass && !inTrait && !inEnum) { PsiElement classElement = context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, classDescriptor); assert classElement instanceof JetClass; - context.getTrace().report(ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS.on(function, abstractNode, functionDescriptor.getName(), classDescriptor, (JetClass) classElement)); + context.getTrace().report(ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS.on(function, functionDescriptor.getName(), classDescriptor, (JetClass) classElement)); } if (hasAbstractModifier && inTrait) { - context.getTrace().report(REDUNDANT_MODIFIER_IN_TRAIT.on(modifierList, abstractNode, JetTokens.ABSTRACT_KEYWORD)); + context.getTrace().report(ABSTRACT_MODIFIER_IN_TRAIT.on(function)); } if (function.getBodyExpression() != null && hasAbstractModifier) { - context.getTrace().report(ABSTRACT_FUNCTION_WITH_BODY.on(function, abstractNode, functionDescriptor)); + context.getTrace().report(ABSTRACT_FUNCTION_WITH_BODY.on(abstractNode.getPsi(), functionDescriptor)); } if (function.getBodyExpression() == null && !hasAbstractModifier && !inTrait && nameIdentifier != null) { - context.getTrace().report(NON_ABSTRACT_FUNCTION_WITH_NO_BODY.on(function, nameIdentifier, functionDescriptor)); + context.getTrace().report(NON_ABSTRACT_FUNCTION_WITH_NO_BODY.on(function, functionDescriptor)); } return; } if (hasAbstractModifier) { - context.getTrace().report(NON_MEMBER_ABSTRACT_FUNCTION.on(function, abstractNode, functionDescriptor)); + context.getTrace().report(NON_MEMBER_ABSTRACT_FUNCTION.on(function, functionDescriptor)); } if (function.getBodyExpression() == null && !hasAbstractModifier && nameIdentifier != null) { - context.getTrace().report(NON_MEMBER_FUNCTION_NO_BODY.on(function, nameIdentifier, functionDescriptor)); + context.getTrace().report(NON_MEMBER_FUNCTION_NO_BODY.on(function, functionDescriptor)); } } @@ -292,13 +291,13 @@ public class DeclarationsChecker { if (getterModifierList != null && getterDescriptor != null) { Map nodes = getNodesCorrespondingToModifiers(getterModifierList, Sets.newHashSet(JetTokens.PUBLIC_KEYWORD, JetTokens.PROTECTED_KEYWORD, JetTokens.PRIVATE_KEYWORD, JetTokens.INTERNAL_KEYWORD)); if (getterDescriptor.getVisibility() != propertyDescriptor.getVisibility()) { - for (Map.Entry entry : nodes.entrySet()) { - context.getTrace().report(Errors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY.on(getterModifierList, entry.getValue(), entry.getKey())); + for (ASTNode node : nodes.values()) { + context.getTrace().report(Errors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY.on(node.getPsi())); } } else { - for (Map.Entry entry : nodes.entrySet()) { - context.getTrace().report(Errors.REDUNDANT_MODIFIER_IN_GETTER.on(getterModifierList, entry.getValue(), entry.getKey())); + for (ASTNode node : nodes.values()) { + context.getTrace().report(Errors.REDUNDANT_MODIFIER_IN_GETTER.on(node.getPsi())); } } } @@ -341,7 +340,7 @@ public class DeclarationsChecker { } } for (JetKeywordToken token : presentModifiers) { - context.getTrace().report(Errors.INCOMPATIBLE_MODIFIERS.on(modifierList.getModifierNode(token), presentModifiers)); + context.getTrace().report(Errors.INCOMPATIBLE_MODIFIERS.on(modifierList.getModifierNode(token).getPsi(), presentModifiers)); } } @@ -350,7 +349,7 @@ public class DeclarationsChecker { JetKeywordToken redundantModifier = tokenPair.getFirst(); JetKeywordToken sufficientModifier = tokenPair.getSecond(); if (modifierList.hasModifier(redundantModifier) && modifierList.hasModifier(sufficientModifier)) { - context.getTrace().report(Errors.REDUNDANT_MODIFIER.on(modifierList, modifierList.getModifierNode(redundantModifier), redundantModifier, sufficientModifier)); + context.getTrace().report(Errors.REDUNDANT_MODIFIER.on(modifierList.getModifierNode(redundantModifier).getPsi(), redundantModifier, sufficientModifier)); } } } @@ -359,7 +358,7 @@ public class DeclarationsChecker { if (modifierList == null) return; for (JetKeywordToken modifier : illegalModifiers) { if (modifierList.hasModifier(modifier)) { - context.getTrace().report(Errors.ILLEGAL_MODIFIER.on(modifierList, modifierList.getModifierNode(modifier), modifier)); + context.getTrace().report(Errors.ILLEGAL_MODIFIER.on(modifierList.getModifierNode(modifier).getPsi(), modifier)); } } } @@ -387,8 +386,7 @@ public class DeclarationsChecker { ConstructorDescriptor constructor = enumClass.getUnsubstitutedPrimaryConstructor(); assert constructor != null; if (!constructor.getValueParameters().isEmpty() && delegationSpecifiers.isEmpty()) { - PsiElement nameIdentifier = aClass.getNameIdentifier(); - context.getTrace().report(ENUM_ENTRY_SHOULD_BE_INITIALIZED.on(nameIdentifier != null ? nameIdentifier : aClass, enumClass)); + context.getTrace().report(ENUM_ENTRY_SHOULD_BE_INITIALIZED.on(aClass, enumClass)); } for (JetDelegationSpecifier delegationSpecifier : delegationSpecifiers) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java index 00afd4b0093..4bd813ee522 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java @@ -111,7 +111,6 @@ public class DescriptorResolver { return parentDescriptor.getDefaultType(); } else { -// trace.getErrorHandler().genericError(((JetEnumEntry) jetClass).getNameIdentifier().getNode(), "Generic arguments of the base type must be specified"); trace.report(NO_GENERICS_IN_SUPERTYPE_SPECIFIER.on(((JetEnumEntry) jetClass).getNameIdentifier())); return ErrorUtils.createErrorType("Supertype not specified"); } @@ -131,8 +130,7 @@ public class DescriptorResolver { JetTypeElement typeElement = typeReference.getTypeElement(); while (typeElement instanceof JetNullableType) { JetNullableType nullableType = (JetNullableType) typeElement; -// trace.getErrorHandler().genericError(nullableType.getQuestionMarkNode(), "A supertype cannot be nullable"); - trace.report(NULLABLE_SUPERTYPE.on(nullableType.getQuestionMarkNode())); + trace.report(NULLABLE_SUPERTYPE.on(nullableType)); typeElement = nullableType.getInnerType(); } if (typeElement instanceof JetUserType) { @@ -140,8 +138,7 @@ public class DescriptorResolver { List typeArguments = userType.getTypeArguments(); for (JetTypeProjection typeArgument : typeArguments) { if (typeArgument.getProjectionKind() != JetProjectionKind.NONE) { -// trace.getErrorHandler().genericError(typeArgument.getProjectionNode(), "Projections are not allowed for immediate arguments of a supertype"); - trace.report(PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE.on(typeArgument.getProjectionNode())); + trace.report(PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE.on(typeArgument)); } } } @@ -202,7 +199,6 @@ public class DescriptorResolver { }); } else { -// trace.getErrorHandler().genericError(function.asElement().getNode(), "This function must either declare a return type or have a body element"); trace.report(FUNCTION_WITH_NO_TYPE_NO_BODY.on(function.asElement())); returnType = ErrorUtils.createErrorType("No type, no body"); } @@ -247,7 +243,6 @@ public class DescriptorResolver { JetType type; if (typeReference == null) { -// trace.getErrorHandler().genericError(valueParameter.getNode(), "A type annotation is required on a value parameter"); trace.report(VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION.on(valueParameter)); type = ErrorUtils.createErrorType("Type annotation was missing"); } else { @@ -350,7 +345,6 @@ public class DescriptorResolver { // To tell the user that we look only for locally defined type parameters ClassifierDescriptor classifier = scope.getClassifier(referencedName); if (classifier != null) { -// trace.getErrorHandler().genericError(subjectTypeParameterName.getNode(), referencedName + " does not refer to a type parameter of " + declaration.getName()); trace.report(NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER.on(subjectTypeParameterName, constraint, declaration)); trace.record(BindingContext.REFERENCE_TARGET, subjectTypeParameterName, classifier); } @@ -379,7 +373,6 @@ public class DescriptorResolver { if (JetStandardClasses.isNothing(parameter.getUpperBoundsAsType())) { PsiElement nameIdentifier = typeParameters.get(parameter.getIndex()).getNameIdentifier(); if (nameIdentifier != null) { -// trace.getErrorHandler().genericError(nameIdentifier.getNode(), "Upper bounds of " + parameter.getName() + " have empty intersection"); trace.report(CONFLICTING_UPPER_BOUNDS.on(nameIdentifier, parameter)); } } @@ -388,7 +381,6 @@ public class DescriptorResolver { if (classObjectType != null && JetStandardClasses.isNothing(classObjectType)) { PsiElement nameIdentifier = typeParameters.get(parameter.getIndex()).getNameIdentifier(); if (nameIdentifier != null) { -// trace.getErrorHandler().genericError(nameIdentifier.getNode(), "Class object upper bounds of " + parameter.getName() + " have empty intersection"); trace.report(CONFLICTING_CLASS_OBJECT_UPPER_BOUNDS.on(nameIdentifier, parameter)); } } @@ -399,11 +391,9 @@ public class DescriptorResolver { JetType jetType = typeResolverNotCheckingBounds.resolveType(scope, upperBound); if (!TypeUtils.canHaveSubtypes(semanticServices.getTypeChecker(), jetType)) { if (classObjectConstaint) { -// trace.getErrorHandler().genericError(upperBound.getNode(), jetType + " is a final type, and thus a class object cannot extend it"); trace.report(FINAL_CLASS_OBJECT_UPPER_BOUND.on(upperBound, jetType)); } else { -// trace.getErrorHandler().genericWarning(upperBound.getNode(), jetType + " is a final type, and thus a value of the type parameter is predetermined"); trace.report(FINAL_UPPER_BOUND.on(upperBound, jetType)); } } @@ -615,10 +605,9 @@ public class DescriptorResolver { if (propertyTypeRef == null) { final JetExpression initializer = property.getInitializer(); if (initializer == null) { -// trace.getErrorHandler().genericError(property.getNode(), "This property must either have a type annotation or be initialized"); PsiElement nameIdentifier = property.getNameIdentifier(); if (nameIdentifier != null) { - trace.report(PROPERTY_WITH_NO_TYPE_NO_INITIALIZER.on(nameIdentifier.getNode())); + trace.report(PROPERTY_WITH_NO_TYPE_NO_INITIALIZER.on(nameIdentifier)); } return ErrorUtils.createErrorType("No type, no body"); } else { @@ -715,7 +704,7 @@ public class DescriptorResolver { JetType inType = propertyDescriptor.getType(); if (inType != null) { if (!TypeUtils.equalTypes(type, inType)) { - trace.report(WRONG_SETTER_PARAMETER_TYPE.on(setter, typeReference, inType)); + trace.report(WRONG_SETTER_PARAMETER_TYPE.on(typeReference, inType)); } } else { @@ -739,7 +728,7 @@ public class DescriptorResolver { if (! property.isVar()) { if (setter != null) { // trace.getErrorHandler().genericError(setter.asElement().getNode(), "A 'val'-property cannot have a setter"); - trace.report(VAL_WITH_SETTER.on(property, setter)); + trace.report(VAL_WITH_SETTER.on(setter)); } } return setterDescriptor; @@ -768,8 +757,7 @@ public class DescriptorResolver { if (returnTypeReference != null) { returnType = typeResolver.resolveType(scope, returnTypeReference); if (outType != null && !TypeUtils.equalTypes(returnType, outType)) { -// trace.getErrorHandler().genericError(returnTypeReference.getNode(), "Getter return type must be equal to the type of the property, i.e. " + propertyDescriptor.getReturnType()); - trace.report(WRONG_GETTER_RETURN_TYPE.on(getter, returnTypeReference, propertyDescriptor.getReturnType())); + trace.report(WRONG_GETTER_RETURN_TYPE.on(returnTypeReference, propertyDescriptor.getReturnType())); } } @@ -851,8 +839,7 @@ public class DescriptorResolver { if (modifierList != null) { ASTNode abstractNode = modifierList.getModifierNode(JetTokens.ABSTRACT_KEYWORD); if (abstractNode != null) { -// trace.getErrorHandler().genericError(abstractNode, "This property cannot be declared abstract"); - trace.report(ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS.on(parameter, abstractNode)); + trace.report(ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS.on(parameter)); } } @@ -913,7 +900,6 @@ public class DescriptorResolver { for (JetType bound : typeParameterDescriptor.getUpperBounds()) { JetType substitutedBound = substitutor.safeSubstitute(bound, Variance.INVARIANT); if (!semanticServices.getTypeChecker().isSubtypeOf(typeArgument, substitutedBound)) { -// trace.getErrorHandler().genericError(argumentTypeReference.getNode(), "An upper bound " + substitutedBound + " is violated"); trace.report(UPPER_BOUND_VIOLATED.on(argumentTypeReference, substitutedBound)); } } 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 41c3cbf53e6..41abb3987b3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java @@ -366,8 +366,7 @@ public class OverrideResolver { if (overridden != null) { if (hasOverrideModifier) { if (!overridden.getModality().isOverridable() && !finalOverriddenError) { - // context.getTrace().getErrorHandler().genericError(overrideNode, "Method " + overridden.getName() + " in " + overridden.getContainingDeclaration().getName() + " is final and cannot be overridden"); - context.getTrace().report(OVERRIDING_FINAL_MEMBER.on(overrideNode, overridden, overridden.getContainingDeclaration())); + context.getTrace().report(OVERRIDING_FINAL_MEMBER.on(overrideNode.getPsi(), overridden, overridden.getContainingDeclaration())); finalOverriddenError = true; } @@ -377,23 +376,19 @@ public class OverrideResolver { } if (checkPropertyKind(overridden, true) && checkPropertyKind(declared, false) && !kindMismatchError) { - context.getTrace().report(VAR_OVERRIDDEN_BY_VAL.on(member, ((JetProperty) member).getValOrVarNode(), (PropertyDescriptor) declared, (PropertyDescriptor) overridden)); + context.getTrace().report(VAR_OVERRIDDEN_BY_VAL.on((JetProperty) member, (PropertyDescriptor) declared, (PropertyDescriptor) overridden)); kindMismatchError = true; } } } } if (hasOverrideModifier && declared.getOverriddenDescriptors().size() == 0) { -// context.getTrace().getErrorHandler().genericError(overrideNode, "Method " + declared.getName() + " overrides nothing"); - context.getTrace().report(NOTHING_TO_OVERRIDE.on(modifierList, overrideNode, declared)); + context.getTrace().report(NOTHING_TO_OVERRIDE.on(member, declared)); } PsiElement nameIdentifier = member.getNameIdentifier(); if (!hasOverrideModifier && declared.getOverriddenDescriptors().size() > 0 && nameIdentifier != null) { CallableMemberDescriptor overridden = declared.getOverriddenDescriptors().iterator().next(); -// context.getTrace().getErrorHandler().genericError(nameIdentifier.getNode(), -// "Method '" + declared.getName() + "' overrides method '" + overridden.getName() + "' in class " + -// overridden.getContainingDeclaration().getName() + " and needs 'override' modifier"); - context.getTrace().report(VIRTUAL_MEMBER_HIDDEN.on(member, nameIdentifier, declared, overridden, overridden.getContainingDeclaration())); + context.getTrace().report(VIRTUAL_MEMBER_HIDDEN.on(member, declared, overridden, overridden.getContainingDeclaration())); } } 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 98f2d922e1f..91dd76e0d25 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java @@ -368,7 +368,7 @@ public class TypeHierarchyResolver { ClassDescriptor superclass = (i < size - 1) ? currentPath.get(i + 1) : current; PsiElement psiElement = context.getTrace().get(DESCRIPTOR_TO_DECLARATION, classDescriptor); - ASTNode node = null; + PsiElement elementToMark = null; if (psiElement instanceof JetClassOrObject) { JetClassOrObject classOrObject = (JetClassOrObject) psiElement; for (JetDelegationSpecifier delegationSpecifier : classOrObject.getDelegationSpecifiers()) { @@ -376,19 +376,19 @@ public class TypeHierarchyResolver { if (typeReference == null) continue; JetType supertype = context.getTrace().get(TYPE, typeReference); if (supertype != null && supertype.getConstructor() == superclass.getTypeConstructor()) { - node = typeReference.getNode(); + elementToMark = typeReference; } } } - if (node == null && psiElement instanceof PsiNameIdentifierOwner) { + if (elementToMark == null && psiElement instanceof PsiNameIdentifierOwner) { PsiNameIdentifierOwner namedElement = (PsiNameIdentifierOwner) psiElement; PsiElement nameIdentifier = namedElement.getNameIdentifier(); if (nameIdentifier != null) { - node = nameIdentifier.getNode(); + elementToMark = nameIdentifier; } } - if (node != null) { - context.getTrace().report(CYCLIC_INHERITANCE_HIERARCHY.on(node)); + if (elementToMark != null) { + context.getTrace().report(CYCLIC_INHERITANCE_HIERARCHY.on(elementToMark)); } } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallMaker.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallMaker.java index 56ba418d568..d1d2ec9d373 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallMaker.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallMaker.java @@ -71,15 +71,13 @@ public class CallMaker { private static class CallImpl implements Call { - private final ASTNode callNode; private final PsiElement callElement; private final ReceiverDescriptor explicitReceiver; private ASTNode callOperationNode; private final JetExpression calleeExpression; private final List valueArguments; - protected CallImpl(@NotNull ASTNode callNode, @Nullable PsiElement callElement, @NotNull ReceiverDescriptor explicitReceiver, @Nullable ASTNode callOperationNode, @NotNull JetExpression calleeExpression, @NotNull List valueArguments) { - this.callNode = callNode; + protected CallImpl(@Nullable PsiElement callElement, @NotNull ReceiverDescriptor explicitReceiver, @Nullable ASTNode callOperationNode, @NotNull JetExpression calleeExpression, @NotNull List valueArguments) { this.callElement = callElement; this.explicitReceiver = explicitReceiver; this.callOperationNode = callOperationNode; @@ -87,10 +85,6 @@ public class CallMaker { this.valueArguments = valueArguments; } - protected CallImpl(@NotNull PsiElement callElement, @NotNull ReceiverDescriptor explicitReceiver, @Nullable ASTNode callOperationNode, @NotNull JetExpression calleeExpression, @NotNull List valueArguments) { - this(callElement.getNode(), callElement, explicitReceiver, callOperationNode, calleeExpression, valueArguments); - } - @Override public ASTNode getCallOperationNode() { return callOperationNode; @@ -114,11 +108,6 @@ public class CallMaker { } @NotNull - @Override - public ASTNode getCallNode() { - return callNode; - } - @Override public PsiElement getCallElement() { return callElement; @@ -147,7 +136,7 @@ public class CallMaker { @Override public String toString() { - return getCallNode().getText(); + return getCallElement().getText(); } } @@ -237,11 +226,6 @@ public class CallMaker { } @NotNull - @Override - public ASTNode getCallNode() { - return callElement.getNode(); - } - @Override public PsiElement getCallElement() { return callElement; 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 5f193da9c73..aace789cd3f 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 @@ -151,7 +151,7 @@ public class CallResolver { } else { JetValueArgumentList valueArgumentList = call.getValueArgumentList(); - ASTNode reportAbsenceOn = valueArgumentList == null ? call.getCallNode() : valueArgumentList.getNode(); + PsiElement reportAbsenceOn = valueArgumentList == null ? call.getCallElement() : valueArgumentList; if (calleeExpression instanceof JetConstructorCalleeExpression) { assert !call.getExplicitReceiver().exists(); @@ -336,7 +336,7 @@ public class CallResolver { @Override public void ambiguity(@NotNull BindingTrace trace, @NotNull Collection> descriptors) { - trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(call.getCallNode(), descriptors)); + trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(call.getCallElement(), descriptors)); } @Override @@ -346,20 +346,20 @@ public class CallResolver { @Override public void instantiationOfAbstractClass(@NotNull BindingTrace trace) { - trace.report(CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS.on(call.getCallNode())); + trace.report(CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS.on(call.getCallElement())); } @Override public void typeInferenceFailed(@NotNull BindingTrace trace, SolutionStatus status) { assert !status.isSuccessful(); - trace.report(TYPE_INFERENCE_FAILED.on(call.getCallNode(), status)); + trace.report(TYPE_INFERENCE_FAILED.on(call.getCallElement(), status)); } @Override public void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType type) { ASTNode callOperationNode = call.getCallOperationNode(); if (callOperationNode != null) { - trace.report(UNSAFE_CALL.on(callOperationNode, type)); + trace.report(UNSAFE_CALL.on(callOperationNode.getPsi(), type)); } else { PsiElement callElement = call.getCallElement(); @@ -382,9 +382,7 @@ public class CallResolver { public void unnecessarySafeCall(@NotNull BindingTrace trace, @NotNull JetType type) { ASTNode callOperationNode = call.getCallOperationNode(); assert callOperationNode != null; - PsiElement callElement = call.getCallElement(); - assert callElement != null; - trace.report(UNNECESSARY_SAFE_CALL.on((JetElement) callOperationNode.getTreeParent().getPsi(), callOperationNode, type)); + trace.report(UNNECESSARY_SAFE_CALL.on(callOperationNode.getPsi(), type)); } @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/DelegatingCall.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/DelegatingCall.java index 6e4b15c3cff..6112c8e274a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/DelegatingCall.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/DelegatingCall.java @@ -84,12 +84,6 @@ public class DelegatingCall implements Call { return delegate.getTypeArgumentList(); } - @Override - @NotNull - public ASTNode getCallNode() { - return delegate.getCallNode(); - } - @Override @Nullable public PsiElement getCallElement() { 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 b3866940f95..333e456d295 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 @@ -169,7 +169,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { } if (value instanceof ErrorValue) { ErrorValue errorValue = (ErrorValue) value; - context.trace.report(ERROR_COMPILE_TIME_VALUE.on(node, errorValue.getMessage())); + context.trace.report(ERROR_COMPILE_TIME_VALUE.on(node.getPsi(), errorValue.getMessage())); return getDefaultType(context.semanticServices, elementType); } else { @@ -243,7 +243,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { JetTypeChecker typeChecker = context.semanticServices.getTypeChecker(); if (!typeChecker.isSubtypeOf(targetType, actualType)) { if (typeChecker.isSubtypeOf(actualType, targetType)) { - context.trace.report(USELESS_CAST_STATIC_ASSERT_IS_FINE.on(expression, expression.getOperationSign())); + context.trace.report(USELESS_CAST_STATIC_ASSERT_IS_FINE.on(expression.getOperationSign())); } else { // See JET-58 Make 'as never succeeds' a warning, or even never check for Java (external) types @@ -252,7 +252,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { } else { if (typeChecker.isSubtypeOf(actualType, targetType)) { - context.trace.report(USELESS_CAST.on(expression, expression.getOperationSign())); + context.trace.report(USELESS_CAST.on(expression.getOperationSign())); } else { if (isCastErased(actualType, targetType, typeChecker)) { context.trace.report(Errors.UNCHECKED_CAST.on(expression, actualType, targetType)); @@ -852,7 +852,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { JetType rightType = right == null ? null : facade.getType(right, contextWithExpectedType.replaceScope(context.scope)); if (leftType != null) { if (!leftType.isNullable()) { - context.trace.report(USELESS_ELVIS.on(expression, left, leftType)); + context.trace.report(USELESS_ELVIS.on(left, leftType)); } if (rightType != null) { DataFlowUtils.checkType(TypeUtils.makeNullableAsSpecified(leftType, rightType.isNullable()), left, contextWithExpectedType); @@ -1035,8 +1035,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { arrayAccessExpression, isGet ? "get" : "set"); if (!functionResults.isSuccess()) { - JetContainerNode indicesNode = arrayAccessExpression.getIndicesNode(); - traceForResolveResult.report(isGet ? NO_GET_METHOD.on(indicesNode) : NO_SET_METHOD.on(indicesNode)); + traceForResolveResult.report(isGet ? NO_GET_METHOD.on(arrayAccessExpression) : NO_SET_METHOD.on(arrayAccessExpression)); return null; } traceForResolveResult.record(isGet ? INDEXED_LVALUE_GET : INDEXED_LVALUE_SET, arrayAccessExpression, functionResults.getResultingCall()); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java index 6189c4f4304..c2facbec749 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java @@ -27,7 +27,6 @@ import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptorUtil; import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.diagnostics.Diagnostic; -import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; @@ -318,7 +317,7 @@ public class ExpressionTypingServices { @Override public void report(@NotNull Diagnostic diagnostic) { - if (diagnostic.getFactory() == TYPE_MISMATCH && ((DiagnosticWithPsiElement) diagnostic).getPsiElement() == expressionToWatch) { + if (diagnostic.getFactory() == TYPE_MISMATCH && diagnostic.getPsiElement() == expressionToWatch) { mismatchFound[0] = true; } super.report(diagnostic); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java index 1aa9925ee81..9e2ef4b0e3e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java @@ -89,7 +89,6 @@ public class ExpressionTypingUtils { if (resultType != null) { // TODO : Relax? if (!isBoolean(context.semanticServices, resultType)) { -// context.trace.getErrorHandler().genericError(operationSign.getNode(), subjectName + " must return Boolean but returns " + resultType); context.trace.report(RESULT_TYPE_MISMATCH.on(operationSign, subjectName, context.semanticServices.getStandardLibrary().getBooleanType(), resultType)); return false; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java index fd1a907d133..a0a70b2a7f0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/PatternMatchingTypingVisitor.java @@ -205,7 +205,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor { ASTNode nameLabelNode = entry.getNameLabelNode(); if (nameLabelNode != null) { // context.trace.getErrorHandler().genericError(nameLabelNode, "Unsupported [OperatorConventions]"); - context.trace.report(UNSUPPORTED.on(nameLabelNode, getClass().getCanonicalName())); + context.trace.report(UNSUPPORTED.on(nameLabelNode.getPsi(), getClass().getCanonicalName())); } JetPattern entryPattern = entry.getPattern(); diff --git a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java index 1d221df659d..6477acaf619 100644 --- a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java +++ b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java @@ -33,7 +33,7 @@ import java.util.List; /** * @author abreslav */ -public class DescriptorRenderer implements Renderer { +public class DescriptorRenderer implements Renderer { public static final DescriptorRenderer TEXT = new DescriptorRenderer(); @@ -97,11 +97,6 @@ public class DescriptorRenderer implements Renderer { @NotNull @Override - public String render(@Nullable Object object) { - assert object instanceof DeclarationDescriptor; - return render((DeclarationDescriptor) object); - } - public String render(DeclarationDescriptor declarationDescriptor) { if (declarationDescriptor == null) return lt() + "null>"; StringBuilder stringBuilder = new StringBuilder(); diff --git a/compiler/testData/diagnostics/tests/AbstractInTrait.jet b/compiler/testData/diagnostics/tests/AbstractInTrait.jet index 84b283c6b23..dbc9d20f8a1 100644 --- a/compiler/testData/diagnostics/tests/AbstractInTrait.jet +++ b/compiler/testData/diagnostics/tests/AbstractInTrait.jet @@ -4,29 +4,29 @@ trait MyTrait { //properties val a: Int val a1: Int = 1 - abstract val a2: Int - abstract val a3: 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 + 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 } + 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 + abstract val e2: Int get() = a + abstract val e3: Int = 0; get() = a //methods fun f() fun g() {} - abstract fun h() - abstract fun j() {} + abstract fun h() + abstract fun j() {} //property accessors var i: Int abstract get abstract set @@ -42,5 +42,4 @@ trait MyTrait { var l1: Int = 0; abstract get abstract set var n: Int abstract get abstract set(v: Int) {} -} - +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/actions/CopyAsDiagnosticTestAction.java b/idea/src/org/jetbrains/jet/plugin/actions/CopyAsDiagnosticTestAction.java index 70e79d1624f..6c40cd76517 100644 --- a/idea/src/org/jetbrains/jet/plugin/actions/CopyAsDiagnosticTestAction.java +++ b/idea/src/org/jetbrains/jet/plugin/actions/CopyAsDiagnosticTestAction.java @@ -23,6 +23,7 @@ import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiErrorElement; import com.intellij.psi.PsiFile; import org.jetbrains.jet.checkers.CheckerTestUtil; import org.jetbrains.jet.lang.psi.JetFile; @@ -48,7 +49,7 @@ public class CopyAsDiagnosticTestAction extends AnAction { assert editor != null && psiFile != null; BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) psiFile); - List syntaxError = AnalyzingUtils.getSyntaxErrorRanges(psiFile); + List syntaxError = AnalyzingUtils.getSyntaxErrorRanges(psiFile); String result = CheckerTestUtil.addDiagnosticMarkersToText(psiFile, bindingContext, syntaxError).toString(); diff --git a/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java b/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java index b01207e6fe2..79934419bbe 100644 --- a/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java +++ b/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java @@ -79,7 +79,7 @@ public class JetPsiChecker implements Annotator { for (Diagnostic diagnostic : diagnostics) { // This is needed because we have the same context for all files - if (diagnostic.getFactory().getPsiFile(diagnostic) != file) continue; + if (diagnostic.getPsiFile() != file) continue; registerDiagnosticAnnotations(diagnostic, redeclarations, holder); } @@ -158,7 +158,7 @@ public class JetPsiChecker implements Annotator { @NotNull Set redeclarations, @NotNull final AnnotationHolder holder ) { - List textRanges = diagnostic.getFactory().getTextRanges(diagnostic); + List textRanges = diagnostic.getTextRanges(); if (diagnostic.getSeverity() == Severity.ERROR) { if (diagnostic.getFactory() == Errors.UNRESOLVED_IDE_TEMPLATE) { return; @@ -226,21 +226,18 @@ public class JetPsiChecker implements Annotator { return null; } - if (diagnostic instanceof DiagnosticWithPsiElementImpl && diagnostic.getFactory() instanceof PsiElementOnlyDiagnosticFactory) { - PsiElementOnlyDiagnosticFactory factory = (PsiElementOnlyDiagnosticFactory) diagnostic.getFactory(); - Collection intentionActionFactories = QuickFixes.get(factory); - for (JetIntentionActionFactory intentionActionFactory : intentionActionFactories) { - IntentionAction action = null; - if (intentionActionFactory != null) { - action = intentionActionFactory.createAction((DiagnosticWithPsiElement) diagnostic); - } - if (action != null) { - annotation.registerFix(action); - } + Collection intentionActionFactories = QuickFixes.getActionFactories(diagnostic.getFactory()); + for (JetIntentionActionFactory intentionActionFactory : intentionActionFactories) { + IntentionAction action = null; + if (intentionActionFactory != null) { + action = intentionActionFactory.createAction(diagnostic); + } + if (action != null) { + annotation.registerFix(action); } } - Collection actions = QuickFixes.get(diagnostic.getFactory()); + Collection actions = QuickFixes.getActions(diagnostic.getFactory()); for (IntentionAction action : actions) { annotation.registerFix(action); } @@ -259,7 +256,7 @@ public class JetPsiChecker implements Annotator { @Nullable private Annotation markRedeclaration(@NotNull Set redeclarations, @NotNull RedeclarationDiagnostic diagnostic, @NotNull AnnotationHolder holder) { if (!redeclarations.add(diagnostic.getPsiElement())) return null; - return holder.createErrorAnnotation(diagnostic.getFactory().getTextRanges(diagnostic).get(0), getMessage(diagnostic)); + return holder.createErrorAnnotation(diagnostic.getTextRanges().get(0), getMessage(diagnostic)); } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionBodyFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionBodyFix.java index 7088ddf9a22..8a9569bb78b 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionBodyFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionBodyFix.java @@ -18,11 +18,14 @@ package org.jetbrains.jet.plugin.quickfix; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiWhiteSpace; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetFunction; import org.jetbrains.jet.lang.psi.JetPsiFactory; @@ -67,12 +70,15 @@ public class AddFunctionBodyFix extends JetIntentionAction { element.replace(newElement); } - public static JetIntentionActionFactory createFactory() { - return new JetIntentionActionFactory() { + public static JetIntentionActionFactory createFactory() { + return new JetIntentionActionFactory() { + @Nullable @Override - public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { - assert diagnostic.getPsiElement() instanceof JetFunction; - return new AddFunctionBodyFix((JetFunction) diagnostic.getPsiElement()); + public JetIntentionAction createAction(Diagnostic diagnostic) { + PsiElement element = diagnostic.getPsiElement(); + JetFunction function = PsiTreeUtil.getParentOfType(element, JetFunction.class, false); + if (function == null) return null; + return new AddFunctionBodyFix(function); } }; } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/AddModifierFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/AddModifierFix.java index f3decc77e5e..01b1b024011 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/AddModifierFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/AddModifierFix.java @@ -23,7 +23,7 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.PsiNameIdentifierOwner; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; +import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.psi.JetModifierList; import org.jetbrains.jet.lang.psi.JetModifierListOwner; import org.jetbrains.jet.lang.psi.JetPropertyAccessor; @@ -120,17 +120,14 @@ public class AddModifierFix extends JetIntentionAction { return true; } - public static JetIntentionActionFactory createFactory(final JetKeywordToken modifier, final JetToken[] modifiersThatCanBeReplaced) { - return new JetIntentionActionFactory() { + public static JetIntentionActionFactory createFactory(final JetKeywordToken modifier, final JetToken[] modifiersThatCanBeReplaced) { + return new JetIntentionActionFactory() { @Override - public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { - assert diagnostic.getPsiElement() instanceof JetModifierListOwner; - return new AddModifierFix((JetModifierListOwner) diagnostic.getPsiElement(), modifier, modifiersThatCanBeReplaced); + public JetIntentionAction createAction(Diagnostic diagnostic) { + JetModifierListOwner modifierListOwner = QuickFixUtil.getParentElementOfType(diagnostic, JetModifierListOwner.class); + if (modifierListOwner == null) return null; + return new AddModifierFix(modifierListOwner, modifier, modifiersThatCanBeReplaced); } }; } - - public static JetIntentionActionFactory createFactory(final JetKeywordToken modifier) { - return createFactory(modifier, new JetToken[0]); - } } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/AddReturnTypeFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/AddReturnTypeFix.java index e8c0e05c2d0..b4acf923204 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/AddReturnTypeFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/AddReturnTypeFix.java @@ -23,23 +23,18 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.diagnostics.DiagnosticParameters; -import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters; -import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; +import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.plugin.JetBundle; /** -* @author svtk -*/ + * @author svtk + */ public class AddReturnTypeFix extends JetIntentionAction { - private JetType type; - - public AddReturnTypeFix(@NotNull JetNamedDeclaration element, JetType type) { + public AddReturnTypeFix(@NotNull JetNamedDeclaration element) { super(element); - this.type = type; } @NotNull @@ -56,13 +51,16 @@ public class AddReturnTypeFix extends JetIntentionAction { @Override public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return super.isAvailable(project, editor, file) && !ErrorUtils.isErrorType(type); + JetType type = QuickFixUtil.getDeclarationReturnType(element); + return super.isAvailable(project, editor, file) && type != null && !ErrorUtils.isErrorType(type); } @Override public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { if (!(file instanceof JetFile)) return; PsiElement newElement; + JetType type = QuickFixUtil.getDeclarationReturnType(element); + if (type == null) return; if (element instanceof JetProperty) { newElement = addPropertyType(project, (JetProperty) element, type); } @@ -70,7 +68,7 @@ public class AddReturnTypeFix extends JetIntentionAction { assert element instanceof JetFunction; newElement = addFunctionType(project, (JetFunction) element, type); } - ImportClassHelper.addImportDirectiveIfNeeded(type, (JetFile)file); + ImportClassHelper.addImportDirectiveIfNeeded(type, (JetFile) file); element.replace(newElement); } @@ -79,7 +77,7 @@ public class AddReturnTypeFix extends JetIntentionAction { return true; } - public static JetProperty addPropertyType(Project project, JetProperty property, JetType type) { + public static JetProperty addPropertyType(@NotNull Project project, @NotNull JetProperty property, @NotNull JetType type) { JetProperty newProperty = (JetProperty) property.copy(); JetTypeReference typeReference = JetPsiFactory.createType(project, type.toString()); Pair colon = JetPsiFactory.createColon(project); @@ -88,7 +86,7 @@ public class AddReturnTypeFix extends JetIntentionAction { return newProperty; } - public static JetFunction addFunctionType(Project project, JetFunction function, JetType type) { + public static JetFunction addFunctionType(@NotNull Project project, @NotNull JetFunction function, @NotNull JetType type) { JetFunction newFunction = (JetFunction) function.copy(); JetTypeReference typeReference = JetPsiFactory.createType(project, type.toString()); Pair colon = JetPsiFactory.createColon(project); @@ -103,14 +101,13 @@ public class AddReturnTypeFix extends JetIntentionAction { element.addRangeAfter(colon.getFirst(), colon.getSecond(), anchor); } - public static JetIntentionActionFactory createFactory() { - return new JetIntentionActionFactory() { + public static JetIntentionActionFactory createFactory() { + return new JetIntentionActionFactory() { @Override - public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { - assert diagnostic.getPsiElement() instanceof JetNamedDeclaration; - DiagnosticWithParameters diagnosticWithParameters = assertAndCastToDiagnosticWithParameters(diagnostic, DiagnosticParameters.TYPE); - JetType type = diagnosticWithParameters.getParameter(DiagnosticParameters.TYPE); - return new AddReturnTypeFix((JetNamedDeclaration) diagnostic.getPsiElement(), type); + public JetIntentionAction createAction(Diagnostic diagnostic) { + JetNamedDeclaration declaration = QuickFixUtil.getParentElementOfType(diagnostic, JetNamedDeclaration.class); + if (declaration == null) return null; + return new AddReturnTypeFix(declaration); } }; } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeAccessorTypeFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeAccessorTypeFix.java index 1481b61f4c5..5ff86a4cd4e 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeAccessorTypeFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeAccessorTypeFix.java @@ -18,18 +18,19 @@ package org.jetbrains.jet.plugin.quickfix; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.impl.source.codeStyle.CodeEditUtil; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.diagnostics.DiagnosticParameters; -import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters; -import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; -import org.jetbrains.jet.lang.psi.JetParameter; -import org.jetbrains.jet.lang.psi.JetPropertyAccessor; -import org.jetbrains.jet.lang.psi.JetPsiFactory; -import org.jetbrains.jet.lang.psi.JetTypeReference; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; +import org.jetbrains.jet.lang.diagnostics.Diagnostic; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade; +import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.plugin.JetBundle; @@ -37,17 +38,30 @@ import org.jetbrains.jet.plugin.JetBundle; * @author svtk */ public class ChangeAccessorTypeFix extends JetIntentionAction { - private final JetType type; - - public ChangeAccessorTypeFix(@NotNull JetPropertyAccessor element, JetType type) { + public ChangeAccessorTypeFix(@NotNull JetPropertyAccessor element) { super(element); - this.type = type; + } + + @Nullable + private JetType getPropertyType() { + JetProperty property = PsiTreeUtil.getParentOfType(element, JetProperty.class); + if (property == null) return null; + return QuickFixUtil.getDeclarationReturnType(property); + } + + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { + JetType type = getPropertyType(); + return super.isAvailable(project, editor, file) && type != null && !ErrorUtils.isErrorType(type); } @NotNull @Override public String getText() { - return element.isGetter() ? JetBundle.message("change.getter.type", type) : JetBundle.message("change.setter.type", type); + JetType type = getPropertyType(); + return element.isGetter() + ? JetBundle.message("change.getter.type", type) + : JetBundle.message("change.setter.type", type); } @NotNull @@ -58,6 +72,8 @@ public class ChangeAccessorTypeFix extends JetIntentionAction createFactory() { - return new JetIntentionActionFactory() { + + public static JetIntentionActionFactory createFactory() { + return new JetIntentionActionFactory() { @Override - public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { - assert diagnostic.getPsiElement() instanceof JetPropertyAccessor; - DiagnosticWithParameters diagnosticWithParameters = assertAndCastToDiagnosticWithParameters(diagnostic, DiagnosticParameters.TYPE); - JetType type = diagnosticWithParameters.getParameter(DiagnosticParameters.TYPE); - return new ChangeAccessorTypeFix((JetPropertyAccessor) diagnostic.getPsiElement(), type); + public JetIntentionAction createAction(Diagnostic diagnostic) { + JetPropertyAccessor accessor = QuickFixUtil.getParentElementOfType(diagnostic, JetPropertyAccessor.class); + if (accessor == null) return null; + return new ChangeAccessorTypeFix(accessor); } }; } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToBackingFieldFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToBackingFieldFix.java index 0caeed72a05..19674455c04 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToBackingFieldFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToBackingFieldFix.java @@ -18,12 +18,12 @@ package org.jetbrains.jet.plugin.quickfix; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; -import org.jetbrains.jet.lang.psi.JetPsiFactory; -import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; +import org.jetbrains.jet.lang.diagnostics.Diagnostic; +import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.plugin.JetBundle; /** @@ -52,12 +52,22 @@ public class ChangeToBackingFieldFix extends JetIntentionAction createFactory() { - return new JetIntentionActionFactory() { + public static JetIntentionActionFactory createFactory() { + return new JetIntentionActionFactory() { @Override - public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { - assert diagnostic.getPsiElement() instanceof JetSimpleNameExpression; - return new ChangeToBackingFieldFix((JetSimpleNameExpression) diagnostic.getPsiElement()); + public JetIntentionAction createAction(Diagnostic diagnostic) { + JetSimpleNameExpression expression = QuickFixUtil.getParentElementOfType(diagnostic, JetSimpleNameExpression.class); + if (expression == null) { + PsiElement element = diagnostic.getPsiElement(); + if (element instanceof JetQualifiedExpression && ((JetQualifiedExpression) element).getReceiverExpression() instanceof JetThisExpression) { + JetExpression selector = ((JetQualifiedExpression) element).getSelectorExpression(); + if (selector instanceof JetSimpleNameExpression) { + expression = (JetSimpleNameExpression) selector; + } + } + } + if (expression == null) return null; + return new ChangeToBackingFieldFix(expression); } }; } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToInvocationFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToInvocationFix.java index 84efe106d09..1982499ac82 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToInvocationFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToInvocationFix.java @@ -21,7 +21,7 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.PsiFile; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; +import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.psi.JetClass; import org.jetbrains.jet.lang.psi.JetDelegationSpecifier; import org.jetbrains.jet.lang.psi.JetDelegatorToSuperClass; @@ -61,12 +61,14 @@ public class ChangeToInvocationFix extends JetIntentionAction createFactory() { - return new JetIntentionActionFactory() { + public static JetIntentionActionFactory createFactory() { + return new JetIntentionActionFactory() { @Override - public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { - assert diagnostic.getPsiElement() instanceof JetDelegatorToSuperClass; - return new ChangeToInvocationFix((JetDelegatorToSuperClass) diagnostic.getPsiElement()); + public JetIntentionAction createAction(Diagnostic diagnostic) { + if (diagnostic.getPsiElement() instanceof JetDelegatorToSuperClass) { + return new ChangeToInvocationFix((JetDelegatorToSuperClass) diagnostic.getPsiElement()); + } + return null; } }; } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/FakeDiagnosticForQuickFixes.java b/idea/src/org/jetbrains/jet/plugin/quickfix/FakeDiagnosticForQuickFixes.java new file mode 100644 index 00000000000..e671aa61083 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/FakeDiagnosticForQuickFixes.java @@ -0,0 +1,74 @@ +/* + * Copyright 2000-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.quickfix; + +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.diagnostics.AbstractDiagnosticFactory; +import org.jetbrains.jet.lang.diagnostics.Diagnostic; +import org.jetbrains.jet.lang.diagnostics.Severity; + +import java.util.List; + +/** + * @author svtk + */ +public class FakeDiagnosticForQuickFixes implements Diagnostic { + private final PsiElement element; + + public FakeDiagnosticForQuickFixes(PsiElement element) { + this.element = element; + } + + @NotNull + @Override + public AbstractDiagnosticFactory getFactory() { + throw new UnsupportedOperationException(); + } + + @NotNull + @Override + public String getMessage() { + throw new UnsupportedOperationException(); + } + + @NotNull + @Override + public Severity getSeverity() { + throw new UnsupportedOperationException(); + } + + @NotNull + @Override + public PsiElement getPsiElement() { + return element; + } + + @NotNull + @Override + public List getTextRanges() { + throw new UnsupportedOperationException(); + } + + @NotNull + @Override + public PsiFile getPsiFile() { + return element.getContainingFile(); + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ImportClassAndFunFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ImportClassAndFunFix.java index 7da439a053f..6a5fc57ac16 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ImportClassAndFunFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ImportClassAndFunFix.java @@ -38,7 +38,7 @@ import com.intellij.psi.search.PsiShortNamesCache; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; +import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetNamedFunction; import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; @@ -205,11 +205,11 @@ public class ImportClassAndFunFix extends JetHintAction } @Nullable - public static JetIntentionActionFactory createFactory() { - return new JetIntentionActionFactory() { + public static JetIntentionActionFactory createFactory() { + return new JetIntentionActionFactory() { @Nullable @Override - public JetIntentionAction createAction(@NotNull DiagnosticWithPsiElement diagnostic) { + public JetIntentionAction createAction(@NotNull Diagnostic diagnostic) { // There could be different psi elements (i.e. JetArrayAccessExpression), but we can fix only JetSimpleNameExpression case if (diagnostic.getPsiElement() instanceof JetSimpleNameExpression) { JetSimpleNameExpression psiElement = (JetSimpleNameExpression) diagnostic.getPsiElement(); @@ -219,4 +219,5 @@ public class ImportClassAndFunFix extends JetHintAction return null; } }; - }} + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/JetIntentionAction.java b/idea/src/org/jetbrains/jet/plugin/quickfix/JetIntentionAction.java index d129df8c8d4..1cdf8e1e7ec 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/JetIntentionAction.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/JetIntentionAction.java @@ -21,12 +21,10 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.diagnostics.Diagnostic; -import org.jetbrains.jet.lang.diagnostics.DiagnosticParameter; -import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters; - -import java.util.Arrays; /** * @author svtk @@ -47,16 +45,4 @@ public abstract class JetIntentionAction implements Intent public boolean startInWriteAction() { return true; } - - public static DiagnosticWithParameters assertAndCastToDiagnosticWithParameters(Diagnostic diagnostic, DiagnosticParameter... parameters) { - assert diagnostic instanceof DiagnosticWithParameters : - "For this type of quick fix diagnostic with additional " + - (parameters.length == 1 ? "parameter '" + parameters[0] + "'" : "parameters " + Arrays.asList(parameters)) + " is expected"; - - for (DiagnosticParameter parameter : parameters) { - assert ((DiagnosticWithParameters) diagnostic).hasParameter(parameter) : - "For this type of quick fix diagnostic with additional parameter '" + parameter + "' is expected"; - } - return (DiagnosticWithParameters) diagnostic; - } } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/JetIntentionActionFactory.java b/idea/src/org/jetbrains/jet/plugin/quickfix/JetIntentionActionFactory.java index 07f1d3bcfb3..84ca4a0e1f2 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/JetIntentionActionFactory.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/JetIntentionActionFactory.java @@ -16,14 +16,16 @@ package org.jetbrains.jet.plugin.quickfix; -import com.intellij.psi.PsiElement; -import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; +import com.intellij.codeInsight.intention.IntentionAction; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.diagnostics.Diagnostic; /** * @author svtk */ -public interface JetIntentionActionFactory { +public interface JetIntentionActionFactory { - JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic); + @Nullable + IntentionAction createAction(Diagnostic diagnostic); } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixUtil.java b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixUtil.java index b1b8b5966c8..e42df3ee145 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixUtil.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixUtil.java @@ -16,18 +16,22 @@ package org.jetbrains.jet.plugin.quickfix; +import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.extapi.psi.ASTDelegatePsiElement; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiWhiteSpace; -import com.intellij.util.IncorrectOperationException; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.diagnostics.DiagnosticParameter; -import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters; -import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; -import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElementImpl; +import com.intellij.psi.util.PsiTreeUtil; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.CallableDescriptor; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.diagnostics.Diagnostic; +import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.psi.JetNamedDeclaration; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade; +import org.jetbrains.jet.lang.types.DeferredType; +import org.jetbrains.jet.lang.types.JetType; /** * @author svtk @@ -36,54 +40,12 @@ public class QuickFixUtil { private QuickFixUtil() { } - public static JetIntentionActionFactory createFactoryRedirectingAdditionalInfoToAnotherFactory(final JetIntentionActionFactory factory, final DiagnosticParameter

parameter) { - return new JetIntentionActionFactory() { + public static JetIntentionActionFactory createFactoryRedirectingAdditionalInfoToAnotherFactory(final JetIntentionActionFactory factory, final Class aClass) { + return new JetIntentionActionFactory() { @Override - public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { - - DiagnosticWithParameters diagnosticWithParameters = JetIntentionAction.assertAndCastToDiagnosticWithParameters(diagnostic, parameter); - P element = diagnosticWithParameters.getParameter(parameter); - return (JetIntentionAction) factory.createAction(new DiagnosticWithPsiElementImpl(diagnostic.getFactory(), diagnostic.getSeverity(), diagnostic.getMessage(), element)); - } - }; - } - - public static JetIntentionActionFactory createFactoryRedirectingAdditionalInfoIfAnyToAnotherFactory(final JetIntentionActionFactory factory, final DiagnosticParameter

parameter) { - return new JetIntentionActionFactory() { - @Override - public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { - - if (diagnostic instanceof DiagnosticWithParameters && ((DiagnosticWithParameters) diagnostic).hasParameter(parameter)) { - P element = ((DiagnosticWithParameters) diagnostic).getParameter(parameter); - return (JetIntentionAction) factory.createAction(new DiagnosticWithPsiElementImpl(diagnostic.getFactory(), diagnostic.getSeverity(), diagnostic.getMessage(), element)); - } - return createDoNothingAction(diagnostic); - } - }; - } - - public static JetIntentionAction createDoNothingAction(DiagnosticWithPsiElement diagnostic) { - return new JetIntentionAction(diagnostic.getPsiElement()) { - @Override - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return false; - } - - @NotNull - @Override - public String getText() { - throw new UnsupportedOperationException(); - } - - @NotNull - @Override - public String getFamilyName() { - throw new UnsupportedOperationException(); - } - - @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - throw new UnsupportedOperationException(); + public IntentionAction createAction(Diagnostic diagnostic) { + T element = getParentElementOfType(diagnostic, aClass); + return factory.createAction(new FakeDiagnosticForQuickFixes(element)); } }; } @@ -95,4 +57,23 @@ public class QuickFixUtil { } return false; } + + @Nullable + public static T getParentElementOfType(Diagnostic diagnostic, Class aClass) { + return PsiTreeUtil.getParentOfType(diagnostic.getPsiElement(), aClass, false); + } + + @Nullable + public static JetType getDeclarationReturnType(JetNamedDeclaration declaration) { + PsiFile file = declaration.getContainingFile(); + if (!(file instanceof JetFile)) return null; + BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache((JetFile) file, AnalyzerFacade.SINGLE_DECLARATION_PROVIDER); + DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration); + if (!(descriptor instanceof CallableDescriptor)) return null; + JetType type = ((CallableDescriptor) descriptor).getReturnType(); + if (type instanceof DeferredType) { + type = ((DeferredType) type).getActualType(); + } + return type; + } } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java index c54a5411a1c..f568bb5c301 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java @@ -19,12 +19,9 @@ package org.jetbrains.jet.plugin.quickfix; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import com.intellij.codeInsight.intention.IntentionAction; -import com.intellij.psi.PsiElement; -import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory; -import org.jetbrains.jet.lang.diagnostics.DiagnosticParameters; import org.jetbrains.jet.lang.diagnostics.Errors; -import org.jetbrains.jet.lang.diagnostics.PsiElementOnlyDiagnosticFactory; -import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.diagnostics.AbstractDiagnosticFactory; +import org.jetbrains.jet.lang.psi.JetClass; import org.jetbrains.jet.lexer.JetToken; import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.plugin.codeInsight.ImplementMethodsHandler; @@ -35,109 +32,107 @@ import java.util.Collection; * @author svtk */ public class QuickFixes { - private static final Multimap jetActionMap = HashMultimap.create(); - private static final Multimap actionMap = HashMultimap.create(); - public static Collection get(PsiElementOnlyDiagnosticFactory diagnosticFactory) { - return jetActionMap.get(diagnosticFactory); + private static final Multimap factories = HashMultimap.create(); + private static final Multimap actions = HashMultimap.create(); + + public static Collection getActionFactories(AbstractDiagnosticFactory diagnosticFactory) { + return factories.get(diagnosticFactory); } - public static Collection get(DiagnosticFactory diagnosticFactory) { - return actionMap.get(diagnosticFactory); + public static Collection getActions(AbstractDiagnosticFactory diagnosticFactory) { + return actions.get(diagnosticFactory); } private QuickFixes() {} - private static void add(PsiElementOnlyDiagnosticFactory diagnosticFactory, JetIntentionActionFactory actionFactory) { - jetActionMap.put(diagnosticFactory, actionFactory); - } - static { - JetIntentionActionFactory removeAbstractModifierFactory = RemoveModifierFix.createRemoveModifierFromListOwnerFactory(JetTokens.ABSTRACT_KEYWORD); - JetIntentionActionFactory addAbstractModifierFactory = AddModifierFix.createFactory(JetTokens.ABSTRACT_KEYWORD, new JetToken[]{JetTokens.OPEN_KEYWORD, JetTokens.FINAL_KEYWORD}); + JetIntentionActionFactory removeAbstractModifierFactory = RemoveModifierFix.createRemoveModifierFromListOwnerFactory(JetTokens.ABSTRACT_KEYWORD); + JetIntentionActionFactory addAbstractModifierFactory = AddModifierFix.createFactory(JetTokens.ABSTRACT_KEYWORD, new JetToken[]{JetTokens.OPEN_KEYWORD, JetTokens.FINAL_KEYWORD}); - add(Errors.ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS, removeAbstractModifierFactory); - add(Errors.ABSTRACT_PROPERTY_NOT_IN_CLASS, removeAbstractModifierFactory); - - JetIntentionActionFactory removePartsFromPropertyFactory = RemovePartsFromPropertyFix.createFactory(); - add(Errors.ABSTRACT_PROPERTY_WITH_INITIALIZER, removeAbstractModifierFactory); - add(Errors.ABSTRACT_PROPERTY_WITH_INITIALIZER, removePartsFromPropertyFactory); + factories.put(Errors.ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS, removeAbstractModifierFactory); + factories.put(Errors.ABSTRACT_PROPERTY_NOT_IN_CLASS, removeAbstractModifierFactory); - add(Errors.ABSTRACT_PROPERTY_WITH_GETTER, removeAbstractModifierFactory); - add(Errors.ABSTRACT_PROPERTY_WITH_GETTER, removePartsFromPropertyFactory); + JetIntentionActionFactory removePartsFromPropertyFactory = RemovePartsFromPropertyFix.createFactory(); + factories.put(Errors.ABSTRACT_PROPERTY_WITH_INITIALIZER, removeAbstractModifierFactory); + factories.put(Errors.ABSTRACT_PROPERTY_WITH_INITIALIZER, removePartsFromPropertyFactory); - add(Errors.ABSTRACT_PROPERTY_WITH_SETTER, removeAbstractModifierFactory); - add(Errors.ABSTRACT_PROPERTY_WITH_SETTER, removePartsFromPropertyFactory); + factories.put(Errors.ABSTRACT_PROPERTY_WITH_GETTER, removeAbstractModifierFactory); + factories.put(Errors.ABSTRACT_PROPERTY_WITH_GETTER, removePartsFromPropertyFactory); - add(Errors.PROPERTY_INITIALIZER_IN_TRAIT, removePartsFromPropertyFactory); + factories.put(Errors.ABSTRACT_PROPERTY_WITH_SETTER, removeAbstractModifierFactory); + factories.put(Errors.ABSTRACT_PROPERTY_WITH_SETTER, removePartsFromPropertyFactory); - add(Errors.MUST_BE_INITIALIZED_OR_BE_ABSTRACT, addAbstractModifierFactory); + factories.put(Errors.PROPERTY_INITIALIZER_IN_TRAIT, removePartsFromPropertyFactory); - JetIntentionActionFactory addAbstractToClassFactory = QuickFixUtil.createFactoryRedirectingAdditionalInfoToAnotherFactory(addAbstractModifierFactory, DiagnosticParameters.CLASS); - add(Errors.ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS, removeAbstractModifierFactory); - add(Errors.ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS, addAbstractToClassFactory); + factories.put(Errors.MUST_BE_INITIALIZED_OR_BE_ABSTRACT, addAbstractModifierFactory); - JetIntentionActionFactory removeFunctionBodyFactory = RemoveFunctionBodyFix.createFactory(); - add(Errors.ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS, removeAbstractModifierFactory); - add(Errors.ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS, addAbstractToClassFactory); + JetIntentionActionFactory addAbstractToClassFactory = QuickFixUtil.createFactoryRedirectingAdditionalInfoToAnotherFactory(addAbstractModifierFactory, JetClass.class); + factories.put(Errors.ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS, removeAbstractModifierFactory); + factories.put(Errors.ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS, addAbstractToClassFactory); - add(Errors.ABSTRACT_FUNCTION_WITH_BODY, removeAbstractModifierFactory); - add(Errors.ABSTRACT_FUNCTION_WITH_BODY, removeFunctionBodyFactory); + JetIntentionActionFactory removeFunctionBodyFactory = RemoveFunctionBodyFix.createFactory(); + factories.put(Errors.ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS, removeAbstractModifierFactory); + factories.put(Errors.ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS, addAbstractToClassFactory); - JetIntentionActionFactory addFunctionBodyFactory = AddFunctionBodyFix.createFactory(); - add(Errors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY, addAbstractModifierFactory); - add(Errors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY, addFunctionBodyFactory); + factories.put(Errors.ABSTRACT_FUNCTION_WITH_BODY, removeAbstractModifierFactory); + factories.put(Errors.ABSTRACT_FUNCTION_WITH_BODY, removeFunctionBodyFactory); - add(Errors.NON_MEMBER_ABSTRACT_FUNCTION, removeAbstractModifierFactory); - add(Errors.NON_MEMBER_FUNCTION_NO_BODY, addFunctionBodyFactory); + JetIntentionActionFactory addFunctionBodyFactory = AddFunctionBodyFix.createFactory(); + factories.put(Errors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY, addAbstractModifierFactory); + factories.put(Errors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY, addFunctionBodyFactory); - add(Errors.NOTHING_TO_OVERRIDE, RemoveModifierFix.createRemoveModifierFromListFactory(JetTokens.OVERRIDE_KEYWORD)); - add(Errors.VIRTUAL_MEMBER_HIDDEN, AddModifierFix.createFactory(JetTokens.OVERRIDE_KEYWORD, new JetToken[] {JetTokens.OPEN_KEYWORD})); + factories.put(Errors.NON_MEMBER_ABSTRACT_FUNCTION, removeAbstractModifierFactory); + factories.put(Errors.NON_MEMBER_FUNCTION_NO_BODY, addFunctionBodyFactory); - add(Errors.USELESS_CAST_STATIC_ASSERT_IS_FINE, ReplaceOperationInBinaryExpressionFix.createChangeCastToStaticAssertFactory()); - add(Errors.USELESS_CAST, RemoveRightPartOfBinaryExpressionFix.createRemoveCastFactory()); + factories.put(Errors.NOTHING_TO_OVERRIDE, RemoveModifierFix.createRemoveModifierFromListOwnerFactory(JetTokens.OVERRIDE_KEYWORD)); + factories.put(Errors.VIRTUAL_MEMBER_HIDDEN, AddModifierFix.createFactory(JetTokens.OVERRIDE_KEYWORD, new JetToken[] {JetTokens.OPEN_KEYWORD})); - JetIntentionActionFactory changeAccessorTypeFactory = ChangeAccessorTypeFix.createFactory(); - add(Errors.WRONG_SETTER_PARAMETER_TYPE, changeAccessorTypeFactory); - add(Errors.WRONG_GETTER_RETURN_TYPE, changeAccessorTypeFactory); + factories.put(Errors.USELESS_CAST_STATIC_ASSERT_IS_FINE, ReplaceOperationInBinaryExpressionFix.createChangeCastToStaticAssertFactory()); + factories.put(Errors.USELESS_CAST, RemoveRightPartOfBinaryExpressionFix.createRemoveCastFactory()); - add(Errors.USELESS_ELVIS, RemoveRightPartOfBinaryExpressionFix.createRemoveElvisOperatorFactory()); + JetIntentionActionFactory changeAccessorTypeFactory = ChangeAccessorTypeFix.createFactory(); + factories.put(Errors.WRONG_SETTER_PARAMETER_TYPE, changeAccessorTypeFactory); + factories.put(Errors.WRONG_GETTER_RETURN_TYPE, changeAccessorTypeFactory); - JetIntentionActionFactory removeRedundantModifierFactory = RemoveModifierFix.createRemoveModifierFromListFactory(true); - add(Errors.REDUNDANT_MODIFIER, removeRedundantModifierFactory); - add(Errors.REDUNDANT_MODIFIER_IN_TRAIT, removeRedundantModifierFactory); - add(Errors.TRAIT_CAN_NOT_BE_FINAL, RemoveModifierFix.createRemoveModifierFromListOwnerFactory(JetTokens.FINAL_KEYWORD)); + factories.put(Errors.USELESS_ELVIS, RemoveRightPartOfBinaryExpressionFix.createRemoveElvisOperatorFactory()); - JetIntentionActionFactory addOpenModifierFactory = AddModifierFix.createFactory(JetTokens.OPEN_KEYWORD, new JetToken[]{JetTokens.FINAL_KEYWORD}); - JetIntentionActionFactory removeOpenModifierFactory = RemoveModifierFix.createRemoveModifierFromListOwnerFactory(JetTokens.OPEN_KEYWORD); - add(Errors.NON_FINAL_MEMBER_IN_FINAL_CLASS, QuickFixUtil.createFactoryRedirectingAdditionalInfoToAnotherFactory(addOpenModifierFactory, DiagnosticParameters.CLASS)); - add(Errors.NON_FINAL_MEMBER_IN_FINAL_CLASS, removeOpenModifierFactory); + JetIntentionActionFactory removeRedundantModifierFactory = RemoveModifierFix.createRemoveModifierFactory(true); + factories.put(Errors.REDUNDANT_MODIFIER, removeRedundantModifierFactory); + factories.put(Errors.ABSTRACT_MODIFIER_IN_TRAIT, RemoveModifierFix.createRemoveModifierFromListOwnerFactory(JetTokens.ABSTRACT_KEYWORD, true)); + factories.put(Errors.OPEN_MODIFIER_IN_TRAIT, RemoveModifierFix.createRemoveModifierFromListOwnerFactory(JetTokens.OPEN_KEYWORD, true)); + factories.put(Errors.TRAIT_CAN_NOT_BE_FINAL, RemoveModifierFix.createRemoveModifierFromListOwnerFactory(JetTokens.FINAL_KEYWORD)); - JetIntentionActionFactory removeModifierFactory = RemoveModifierFix.createRemoveModifierFromListFactory(); - add(Errors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY, removeModifierFactory); - add(Errors.REDUNDANT_MODIFIER_IN_GETTER, removeRedundantModifierFactory); - add(Errors.ILLEGAL_MODIFIER, removeModifierFactory); + JetIntentionActionFactory addOpenModifierFactory = AddModifierFix.createFactory(JetTokens.OPEN_KEYWORD, new JetToken[]{JetTokens.FINAL_KEYWORD}); + JetIntentionActionFactory removeOpenModifierFactory = RemoveModifierFix.createRemoveModifierFromListOwnerFactory(JetTokens.OPEN_KEYWORD); + factories.put(Errors.NON_FINAL_MEMBER_IN_FINAL_CLASS, QuickFixUtil.createFactoryRedirectingAdditionalInfoToAnotherFactory(addOpenModifierFactory, JetClass.class)); + factories.put(Errors.NON_FINAL_MEMBER_IN_FINAL_CLASS, removeOpenModifierFactory); - add(Errors.PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE, AddReturnTypeFix.createFactory()); + JetIntentionActionFactory removeModifierFactory = RemoveModifierFix.createRemoveModifierFactory(); + factories.put(Errors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY, removeModifierFactory); + factories.put(Errors.REDUNDANT_MODIFIER_IN_GETTER, removeRedundantModifierFactory); + factories.put(Errors.ILLEGAL_MODIFIER, removeModifierFactory); - JetIntentionActionFactory changeToBackingFieldFactory = ChangeToBackingFieldFix.createFactory(); - add(Errors.INITIALIZATION_USING_BACKING_FIELD_CUSTOM_SETTER, changeToBackingFieldFactory); - add(Errors.INITIALIZATION_USING_BACKING_FIELD_OPEN_SETTER, changeToBackingFieldFactory); + factories.put(Errors.PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE, AddReturnTypeFix.createFactory()); - JetIntentionActionFactory unresolvedReferenceFactory = ImportClassAndFunFix.createFactory(); - add(Errors.UNRESOLVED_REFERENCE, unresolvedReferenceFactory); + JetIntentionActionFactory changeToBackingFieldFactory = ChangeToBackingFieldFix.createFactory(); + factories.put(Errors.INITIALIZATION_USING_BACKING_FIELD_CUSTOM_SETTER, changeToBackingFieldFactory); + factories.put(Errors.INITIALIZATION_USING_BACKING_FIELD_OPEN_SETTER, changeToBackingFieldFactory); + + JetIntentionActionFactory unresolvedReferenceFactory = ImportClassAndFunFix.createFactory(); + factories.put(Errors.UNRESOLVED_REFERENCE, unresolvedReferenceFactory); + + factories.put(Errors.SUPERTYPE_NOT_INITIALIZED_DEFAULT, ChangeToInvocationFix.createFactory()); - add(Errors.SUPERTYPE_NOT_INITIALIZED_DEFAULT, ChangeToInvocationFix.createFactory()); - ImplementMethodsHandler implementMethodsHandler = new ImplementMethodsHandler(); - actionMap.put(Errors.ABSTRACT_MEMBER_NOT_IMPLEMENTED, implementMethodsHandler); - actionMap.put(Errors.MANY_IMPL_MEMBER_NOT_IMPLEMENTED, implementMethodsHandler); + actions.put(Errors.ABSTRACT_MEMBER_NOT_IMPLEMENTED, implementMethodsHandler); + actions.put(Errors.MANY_IMPL_MEMBER_NOT_IMPLEMENTED, implementMethodsHandler); ChangeVariableMutabilityFix changeVariableMutabilityFix = new ChangeVariableMutabilityFix(); - actionMap.put(Errors.VAL_WITH_SETTER, changeVariableMutabilityFix); - actionMap.put(Errors.VAL_REASSIGNMENT, changeVariableMutabilityFix); + actions.put(Errors.VAL_WITH_SETTER, changeVariableMutabilityFix); + actions.put(Errors.VAL_REASSIGNMENT, changeVariableMutabilityFix); - actionMap.put(Errors.UNNECESSARY_SAFE_CALL, new ReplaceCallFix(false)); - actionMap.put(Errors.UNSAFE_CALL, new ReplaceCallFix(true)); + actions.put(Errors.UNNECESSARY_SAFE_CALL, new ReplaceCallFix(false)); + actions.put(Errors.UNSAFE_CALL, new ReplaceCallFix(true)); } -} +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveFunctionBodyFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveFunctionBodyFix.java index cc1d08be732..747cb3fb2f3 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveFunctionBodyFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveFunctionBodyFix.java @@ -24,7 +24,7 @@ import com.intellij.psi.impl.source.tree.LeafPsiElement; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; +import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.psi.JetElement; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetFunction; @@ -88,12 +88,13 @@ public class RemoveFunctionBodyFix extends JetIntentionAction { return false; } - public static JetIntentionActionFactory createFactory() { - return new JetIntentionActionFactory() { + public static JetIntentionActionFactory createFactory() { + return new JetIntentionActionFactory() { @Override - public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { - assert diagnostic.getPsiElement() instanceof JetFunction; - return new RemoveFunctionBodyFix((JetFunction) diagnostic.getPsiElement()); + public JetIntentionAction createAction(Diagnostic diagnostic) { + JetFunction function = QuickFixUtil.getParentElementOfType(diagnostic, JetFunction.class); + if (function == null) return null; + return new RemoveFunctionBodyFix(function); } }; } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveModifierFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveModifierFix.java index 9845019d2e9..ffa997550f1 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveModifierFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveModifierFix.java @@ -21,12 +21,11 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import com.intellij.psi.tree.IElementType; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.diagnostics.DiagnosticParameters; -import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters; -import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; +import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.psi.JetElement; import org.jetbrains.jet.lang.psi.JetModifierList; import org.jetbrains.jet.lang.psi.JetModifierListOwner; @@ -36,13 +35,14 @@ import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.plugin.JetBundle; /** -* @author svtk -*/ -public class RemoveModifierFix { + * @author svtk + */ +public class RemoveModifierFix extends JetIntentionAction { private final JetKeywordToken modifier; private final boolean isRedundant; - public RemoveModifierFix(JetKeywordToken modifier, boolean isRedundant) { + public RemoveModifierFix(@NotNull JetModifierListOwner element, @NotNull JetKeywordToken modifier, boolean isRedundant) { + super(element); this.modifier = modifier; this.isRedundant = isRedundant; } @@ -56,8 +56,10 @@ public class RemoveModifierFix { } return JetBundle.message("remove.modifier", modifier.getValue()); } - - private static String getFamilyName() { + + @NotNull + @Override + public String getFamilyName() { return JetBundle.message("remove.modifier.family"); } @@ -87,111 +89,53 @@ public class RemoveModifierFix { } return modifierList; } - - private class RemoveModifierFromListOwner extends JetIntentionAction { - public RemoveModifierFromListOwner(@NotNull JetModifierListOwner element) { - super(element); - } - @NotNull - @Override - public String getText() { - return makeText(element, modifier, isRedundant); - } - - @NotNull - @Override - public String getFamilyName() { - return RemoveModifierFix.getFamilyName(); - } - - @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - JetModifierListOwner newElement = (JetModifierListOwner) element.copy(); - element.replace(removeModifier(newElement, modifier)); - } + @NotNull + @Override + public String getText() { + return makeText(element, modifier, isRedundant); } - private class RemoveModifierFromList extends JetIntentionAction { - public RemoveModifierFromList(@NotNull JetModifierList element) { - super(element); - } - - @NotNull - @Override - public String getText() { - return makeText(null, modifier, isRedundant); - } - - @NotNull - @Override - public String getFamilyName() { - return RemoveModifierFix.getFamilyName(); - } - - @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - JetModifierList newElement = (JetModifierList) element.copy(); - element.replace(RemoveModifierFix.removeModifierFromList(newElement, modifier)); - } + @Override + public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + JetModifierListOwner newElement = (JetModifierListOwner) element.copy(); + element.replace(removeModifier(newElement, modifier)); } - public static JetIntentionActionFactory createRemoveModifierFromListOwnerFactory(final JetKeywordToken modifier, final boolean isRedundant) { - return new JetIntentionActionFactory() { - @Override - public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { - assert diagnostic.getPsiElement() instanceof JetModifierListOwner; - return new RemoveModifierFix(modifier, isRedundant).new RemoveModifierFromListOwner((JetModifierListOwner) diagnostic.getPsiElement()); - } - }; - } - - private static RemoveModifierFix createRemoveModifierFixFromDiagnostic(DiagnosticWithPsiElement diagnostic, boolean isRedundant) { - DiagnosticWithParameters diagnosticWithParameters = JetIntentionAction.assertAndCastToDiagnosticWithParameters(diagnostic, DiagnosticParameters.MODIFIER); - JetKeywordToken modifier = diagnosticWithParameters.getParameter(DiagnosticParameters.MODIFIER); - return new RemoveModifierFix(modifier, isRedundant); - } - - public static JetIntentionActionFactory createRemoveModifierFromListOwnerFactory(final boolean isRedundant) { - return new JetIntentionActionFactory() { - @Override - public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { - assert diagnostic.getPsiElement() instanceof JetModifierListOwner; - return createRemoveModifierFixFromDiagnostic(diagnostic, isRedundant).new RemoveModifierFromListOwner((JetModifierListOwner) diagnostic.getPsiElement()); - } - }; - } - - public static JetIntentionActionFactory createRemoveModifierFromListFactory(final boolean isRedundant) { - return new JetIntentionActionFactory() { - @Override - public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { - assert diagnostic.getPsiElement() instanceof JetModifierList; - return createRemoveModifierFixFromDiagnostic(diagnostic, isRedundant).new RemoveModifierFromList((JetModifierList) diagnostic.getPsiElement()); - } - }; - } - - public static JetIntentionActionFactory createRemoveModifierFromListFactory(final JetKeywordToken modifier, final boolean isRedundant) { - return new JetIntentionActionFactory() { - @Override - public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { - assert diagnostic.getPsiElement() instanceof JetModifierList; - return new RemoveModifierFix(modifier, isRedundant).new RemoveModifierFromList((JetModifierList) diagnostic.getPsiElement()); - } - }; - } - - public static JetIntentionActionFactory createRemoveModifierFromListOwnerFactory(final JetKeywordToken modifier) { + public static JetIntentionActionFactory createRemoveModifierFromListOwnerFactory(final JetKeywordToken modifier) { return createRemoveModifierFromListOwnerFactory(modifier, false); } - public static JetIntentionActionFactory createRemoveModifierFromListFactory() { - return createRemoveModifierFromListFactory(false); + public static JetIntentionActionFactory createRemoveModifierFromListOwnerFactory(final JetKeywordToken modifier, final boolean isRedundant) { + return new JetIntentionActionFactory() { + @Nullable + @Override + public JetIntentionAction createAction(Diagnostic diagnostic) { + JetModifierListOwner modifierListOwner = QuickFixUtil.getParentElementOfType(diagnostic, JetModifierListOwner.class); + if (modifierListOwner == null) return null; + return new RemoveModifierFix(modifierListOwner, modifier, isRedundant); + } + }; } - public static JetIntentionActionFactory createRemoveModifierFromListFactory(final JetKeywordToken modifier) { - return createRemoveModifierFromListFactory(modifier, false); + public static JetIntentionActionFactory createRemoveModifierFactory() { + return createRemoveModifierFactory(false); + } + + public static JetIntentionActionFactory createRemoveModifierFactory(final boolean isRedundant) { + return new JetIntentionActionFactory() { + @Nullable + @Override + public JetIntentionAction createAction(Diagnostic diagnostic) { + JetModifierListOwner modifierListOwner = QuickFixUtil.getParentElementOfType(diagnostic, JetModifierListOwner.class); + if (modifierListOwner == null) return null; + PsiElement psiElement = diagnostic.getPsiElement(); + IElementType elementType = psiElement.getNode().getElementType(); + if (!(elementType instanceof JetKeywordToken)) return null; + JetKeywordToken modifier = (JetKeywordToken) elementType; + return new RemoveModifierFix(modifierListOwner, modifier, isRedundant); + } + }; } } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/RemovePartsFromPropertyFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/RemovePartsFromPropertyFix.java index a449028f04b..534efa00fbb 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/RemovePartsFromPropertyFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/RemovePartsFromPropertyFix.java @@ -20,16 +20,12 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.diagnostics.DiagnosticParameters; -import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters; -import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; -import org.jetbrains.jet.lang.psi.JetExpression; -import org.jetbrains.jet.lang.psi.JetFile; -import org.jetbrains.jet.lang.psi.JetProperty; -import org.jetbrains.jet.lang.psi.JetPropertyAccessor; +import org.jetbrains.jet.lang.diagnostics.Diagnostic; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.plugin.JetBundle; @@ -37,29 +33,23 @@ import org.jetbrains.jet.plugin.JetBundle; * @author svtk */ public class RemovePartsFromPropertyFix extends JetIntentionAction { - private final JetType type; private final boolean removeInitializer; private final boolean removeGetter; private final boolean removeSetter; - private RemovePartsFromPropertyFix(@NotNull JetProperty element, @Nullable JetType type, boolean removeInitializer, boolean removeGetter, boolean removeSetter) { + private RemovePartsFromPropertyFix(@NotNull JetProperty element, boolean removeInitializer, boolean removeGetter, boolean removeSetter) { super(element); - this.type = type; this.removeInitializer = removeInitializer; this.removeGetter = removeGetter; this.removeSetter = removeSetter; } - private RemovePartsFromPropertyFix(@NotNull JetProperty element, @Nullable JetType type) { - this(element, type, element.getInitializer() != null, + private RemovePartsFromPropertyFix(@NotNull JetProperty element) { + this(element, element.getInitializer() != null, element.getGetter() != null && element.getGetter().getBodyExpression() != null, element.getSetter() != null && element.getSetter().getBodyExpression() != null); } - private RemovePartsFromPropertyFix(@NotNull JetProperty element, boolean removeInitializer, boolean removeGetter, boolean removeSetter) { - this(element, null, removeInitializer, removeGetter, removeSetter); - } - private static String partsToRemove(boolean getter, boolean setter, boolean initializer) { StringBuilder sb = new StringBuilder(); if (getter) { @@ -95,9 +85,16 @@ public class RemovePartsFromPropertyFix extends JetIntentionAction return JetBundle.message("remove.parts.from.property.family"); } + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { + JetType type = QuickFixUtil.getDeclarationReturnType(element); + return super.isAvailable(project, editor, file) && type != null && !ErrorUtils.isErrorType(type); + } + @Override public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { if (!(file instanceof JetFile)) return; + JetType type = QuickFixUtil.getDeclarationReturnType(element); JetProperty newElement = (JetProperty) element.copy(); JetPropertyAccessor getter = newElement.getGetter(); if (removeGetter && getter != null) { @@ -127,24 +124,15 @@ public class RemovePartsFromPropertyFix extends JetIntentionAction element.replace(newElement); } - public static JetIntentionActionFactory createFactory() { - return new JetIntentionActionFactory() { + public static JetIntentionActionFactory createFactory() { + return new JetIntentionActionFactory() { @Override - public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { - assert diagnostic.getPsiElement() instanceof JetProperty; - DiagnosticWithParameters diagnosticWithParameters = assertAndCastToDiagnosticWithParameters(diagnostic, DiagnosticParameters.TYPE); - JetType type = diagnosticWithParameters.getParameter(DiagnosticParameters.TYPE); - return new RemovePartsFromPropertyFix((JetProperty) diagnostic.getPsiElement(), type); - } - }; - } - - public static JetIntentionActionFactory createRemoveInitializerFactory() { - return new JetIntentionActionFactory() { - @Override - public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { - assert diagnostic.getPsiElement() instanceof JetProperty; - return new RemovePartsFromPropertyFix((JetProperty) diagnostic.getPsiElement(), true, false, false); + public JetIntentionAction createAction(Diagnostic diagnostic) { + PsiElement element = diagnostic.getPsiElement(); + assert element instanceof JetElement; + JetProperty property = PsiTreeUtil.getParentOfType(element, JetProperty.class); + if (property == null) return null; + return new RemovePartsFromPropertyFix(property); } }; } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveRightPartOfBinaryExpressionFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveRightPartOfBinaryExpressionFix.java index d3575f471c8..634081475f7 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveRightPartOfBinaryExpressionFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveRightPartOfBinaryExpressionFix.java @@ -21,7 +21,7 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.PsiFile; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; +import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.psi.JetBinaryExpression; import org.jetbrains.jet.lang.psi.JetBinaryExpressionWithTypeRHS; import org.jetbrains.jet.lang.psi.JetExpression; @@ -30,9 +30,16 @@ import org.jetbrains.jet.plugin.JetBundle; /** * @author svtk */ -public abstract class RemoveRightPartOfBinaryExpressionFix extends JetIntentionAction { - public RemoveRightPartOfBinaryExpressionFix(@NotNull T element) { +public class RemoveRightPartOfBinaryExpressionFix extends JetIntentionAction { + private final String message; + + public RemoveRightPartOfBinaryExpressionFix(@NotNull T element, String message) { super(element); + this.message = message; + } + + public String getText() { + return message; } @NotNull @@ -53,34 +60,24 @@ public abstract class RemoveRightPartOfBinaryExpressionFix createRemoveCastFactory() { - return new JetIntentionActionFactory() { + public static JetIntentionActionFactory createRemoveCastFactory() { + return new JetIntentionActionFactory() { @Override - public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { - assert diagnostic.getPsiElement() instanceof JetBinaryExpressionWithTypeRHS; - return new RemoveRightPartOfBinaryExpressionFix((JetBinaryExpressionWithTypeRHS) diagnostic.getPsiElement()) { - @NotNull - @Override - public String getText() { - return JetBundle.message("remove.cast"); - } - }; + public JetIntentionAction createAction(Diagnostic diagnostic) { + JetBinaryExpressionWithTypeRHS expression = QuickFixUtil.getParentElementOfType(diagnostic, JetBinaryExpressionWithTypeRHS.class); + if (expression == null) return null; + return new RemoveRightPartOfBinaryExpressionFix(expression, JetBundle.message("remove.cast")); } }; } - public static JetIntentionActionFactory createRemoveElvisOperatorFactory() { - return new JetIntentionActionFactory() { + public static JetIntentionActionFactory createRemoveElvisOperatorFactory() { + return new JetIntentionActionFactory() { @Override - public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { - assert diagnostic.getPsiElement() instanceof JetBinaryExpression; - return new RemoveRightPartOfBinaryExpressionFix((JetBinaryExpression) diagnostic.getPsiElement()) { - @NotNull - @Override - public String getText() { - return JetBundle.message("remove.elvis.operator"); - } - }; + public JetIntentionAction createAction(Diagnostic diagnostic) { + JetBinaryExpression expression = QuickFixUtil.getParentElementOfType(diagnostic, JetBinaryExpression.class); + if (expression == null) return null; + return new RemoveRightPartOfBinaryExpressionFix(expression, JetBundle.message("remove.elvis.operator")); } }; } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ReplaceOperationInBinaryExpressionFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ReplaceOperationInBinaryExpressionFix.java index eed7b18fbef..bda55a7c8c3 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ReplaceOperationInBinaryExpressionFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ReplaceOperationInBinaryExpressionFix.java @@ -18,10 +18,11 @@ package org.jetbrains.jet.plugin.quickfix; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; +import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.psi.JetBinaryExpressionWithTypeRHS; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetPsiFactory; @@ -33,6 +34,7 @@ import org.jetbrains.jet.plugin.JetBundle; */ public abstract class ReplaceOperationInBinaryExpressionFix extends JetIntentionAction { private final String operation; + public ReplaceOperationInBinaryExpressionFix(@NotNull T element, String operation) { super(element); this.operation = operation; @@ -56,12 +58,13 @@ public abstract class ReplaceOperationInBinaryExpressionFix createChangeCastToStaticAssertFactory() { - return new JetIntentionActionFactory() { + public static JetIntentionActionFactory createChangeCastToStaticAssertFactory() { + return new JetIntentionActionFactory() { @Override - public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { - assert diagnostic.getPsiElement() instanceof JetBinaryExpressionWithTypeRHS; - return new ReplaceOperationInBinaryExpressionFix((JetBinaryExpressionWithTypeRHS) diagnostic.getPsiElement(), " : ") { + public JetIntentionAction createAction(Diagnostic diagnostic) { + JetBinaryExpressionWithTypeRHS expression = QuickFixUtil.getParentElementOfType(diagnostic, JetBinaryExpressionWithTypeRHS.class); + if (expression == null) return null; + return new ReplaceOperationInBinaryExpressionFix(expression, " : ") { @NotNull @Override public String getText() { diff --git a/idea/testData/quickfix/modifiers/afterRemoveRedundantModifier3.kt b/idea/testData/quickfix/modifiers/afterRemoveRedundantModifier3.kt index 2f6b03af29c..8dea6adeadc 100644 --- a/idea/testData/quickfix/modifiers/afterRemoveRedundantModifier3.kt +++ b/idea/testData/quickfix/modifiers/afterRemoveRedundantModifier3.kt @@ -4,5 +4,5 @@ abstract class B() { } abstract class A() : B() { - abstract override fun foo() + abstract override fun foo() } From 1610e7eefdaf6b5cb2ef7788d32205b000dbfaa9 Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Mon, 27 Feb 2012 22:11:13 +0400 Subject: [PATCH 2/4] fixes after merge --- .../src/org/jetbrains/jet/lang/diagnostics/Errors.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 4e3faeac91b..d687d34f8c1 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -131,11 +131,11 @@ public interface Errors { DiagnosticFactory PROPERTY_INITIALIZER_NO_BACKING_FIELD = DiagnosticFactory.create(ERROR, "Initializer is not allowed here because this property has no backing field"); DiagnosticFactory3 ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS = DiagnosticFactory3.create(ERROR, "Abstract property {0} in non-abstract class {1}", PositioningStrategies.POSITION_ABSTRACT_MODIFIER); DiagnosticFactory3 ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS = DiagnosticFactory3.create(ERROR, "Abstract function {0} in non-abstract class {1}", PositioningStrategies.POSITION_ABSTRACT_MODIFIER); - DiagnosticFactory1 ABSTRACT_FUNCTION_WITH_BODY = DiagnosticFactory1.create(ERROR, "A function {0} with body cannot be abstract"); - DiagnosticFactory1 NON_ABSTRACT_FUNCTION_WITH_NO_BODY = DiagnosticFactory1.create(ERROR, "Method {0} without a body must be abstract", PositioningStrategies.POSITION_NAME_IDENTIFIER); - DiagnosticFactory1 NON_MEMBER_ABSTRACT_FUNCTION = DiagnosticFactory1.create(ERROR, "Function {0} is not a class or trait member and cannot be abstract", PositioningStrategies.POSITION_ABSTRACT_MODIFIER); + DiagnosticFactory1 ABSTRACT_FUNCTION_WITH_BODY = DiagnosticFactory1.create(ERROR, "A function {0} with body cannot be abstract"); + DiagnosticFactory1 NON_ABSTRACT_FUNCTION_WITH_NO_BODY = DiagnosticFactory1.create(ERROR, "Method {0} without a body must be abstract", PositioningStrategies.POSITION_NAME_IDENTIFIER); + DiagnosticFactory1 NON_MEMBER_ABSTRACT_FUNCTION = DiagnosticFactory1.create(ERROR, "Function {0} is not a class or trait member and cannot be abstract", PositioningStrategies.POSITION_ABSTRACT_MODIFIER); - DiagnosticFactory1 NON_MEMBER_FUNCTION_NO_BODY = DiagnosticFactory1.create(ERROR, "Function {0} must have a body", PositioningStrategies.POSITION_NAME_IDENTIFIER); + DiagnosticFactory1 NON_MEMBER_FUNCTION_NO_BODY = DiagnosticFactory1.create(ERROR, "Function {0} must have a body", PositioningStrategies.POSITION_NAME_IDENTIFIER); DiagnosticFactory NON_FINAL_MEMBER_IN_FINAL_CLASS = DiagnosticFactory.create(ERROR, "Non final member in a final class"); DiagnosticFactory PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE = DiagnosticFactory.create(ERROR, "Public or protected member should specify a type"); From 9ba1dbf98aa0b5ebdedf9f02043db558cfb17708 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Mon, 27 Feb 2012 22:59:34 +0200 Subject: [PATCH 3/4] refactoring in progress --- .../jetbrains/jet/codegen/ClassCodegen.java | 3 - .../jet/codegen/ClosureAnnotator.java | 288 ++++++++++++++++++ .../jetbrains/jet/codegen/ClosureCodegen.java | 30 +- .../jetbrains/jet/codegen/CodegenContext.java | 4 +- .../jetbrains/jet/codegen/CodegenUtil.java | 15 - .../jet/codegen/ConstructorFrameMap.java | 5 +- .../jet/codegen/ExpressionCodegen.java | 4 +- .../GeneratedAnonymousClassDescriptor.java | 6 +- .../jet/codegen/GenerationState.java | 36 +-- .../codegen/ImplementationBodyCodegen.java | 48 ++- .../jetbrains/jet/codegen/JetTypeMapper.java | 86 ++---- .../jet/codegen/JvmMethodParameterKind.java | 2 - .../jet/codegen/NamespaceCodegen.java | 13 - .../jet/codegen/ObjectOrClosureCodegen.java | 6 +- .../jet/compiler/CompileSession.java | 7 +- .../jetbrains/jet/asJava/JetLightClass.java | 8 +- .../objects/objectLiteralInClosure.jet | 17 ++ .../jetbrains/jet/codegen/ObjectGenTest.java | 5 + .../jetbrains/jet/codegen/TestlibTest.java | 3 +- .../plugin/debugger/JetPositionManager.java | 16 +- .../codewindow/BytecodeToolwindow.java | 3 +- 21 files changed, 396 insertions(+), 209 deletions(-) create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/ClosureAnnotator.java create mode 100644 compiler/testData/codegen/objects/objectLiteralInClosure.jet diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java index 03c38ce4fc1..aa8753a8d8d 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java @@ -37,9 +37,6 @@ public class ClassCodegen { public void generate(CodegenContext context, JetClassOrObject aClass) { ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass); ClassBuilder classBuilder = state.forClassImplementation(descriptor); - if (classBuilder.generateCode()) { - GenerationState.prepareAnonymousClasses(aClass, state.getTypeMapper()); - } final CodegenContext contextForInners = context.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state.getTypeMapper()); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureAnnotator.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureAnnotator.java new file mode 100644 index 00000000000..ae6c782e09b --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureAnnotator.java @@ -0,0 +1,288 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.codegen; + +import com.intellij.util.containers.MultiMap; +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.BindingContext; +import org.jetbrains.jet.lang.resolve.java.JvmAbi; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.types.JetStandardClasses; + +import java.util.*; + +/** + * @author alex.tkachman + */ +public class ClosureAnnotator { + private final Map classNamesForAnonymousClasses = new HashMap(); + private final Map classNamesForClassDescriptor = new HashMap(); + private final Map anonymousSubclassesCount = new HashMap(); + private final Map classesForFunctions = new HashMap(); + private final Map enclosing = new HashMap(); + + private final MultiMap namespaceName2Files = MultiMap.create(); + private final BindingContext bindingContext; + + public ClosureAnnotator(BindingContext bindingContext, Collection files) { + this.bindingContext = bindingContext; + mapFilesToNamespaces(files); + prepareAnonymousClasses(); + } + + public ClassDescriptor classDescriptorForFunctionDescriptor(FunctionDescriptor funDescriptor, String name) { + ClassDescriptorImpl classDescriptor = classesForFunctions.get(funDescriptor); + if(classDescriptor == null) { + int arity = funDescriptor.getValueParameters().size(); + + classDescriptor = new ClassDescriptorImpl( + funDescriptor, + Collections.emptyList(), + name); + classDescriptor.initialize( + false, + Collections.emptyList(), + Collections.singleton((funDescriptor.getReceiverParameter().exists() ? JetStandardClasses.getReceiverFunction(arity) : JetStandardClasses.getFunction(arity)).getDefaultType()), JetScope.EMPTY, Collections.emptySet(), null); + classesForFunctions.put(funDescriptor, classDescriptor); + } + return classDescriptor; + } + + private void mapFilesToNamespaces(Collection files) { + for (JetFile file : files) { + String fqName = JetPsiUtil.getFQName(file); + namespaceName2Files.putValue(fqName, file); + } + } + + private void prepareAnonymousClasses() { + MyJetVisitorVoid visitor = new MyJetVisitorVoid(); + for (Map.Entry> entry : namespaceName2Files.entrySet()) { + for (JetFile jetFile : entry.getValue()) { + jetFile.accept(visitor); + } + } + } + + public String classNameForAnonymousClass(JetElement expression) { + if(expression instanceof JetObjectLiteralExpression) { + JetObjectLiteralExpression jetObjectLiteralExpression = (JetObjectLiteralExpression) expression; + expression = jetObjectLiteralExpression.getObjectDeclaration(); + } + + if(expression instanceof JetFunctionLiteralExpression) { + JetFunctionLiteralExpression jetFunctionLiteralExpression = (JetFunctionLiteralExpression) expression; + expression = jetFunctionLiteralExpression.getFunctionLiteral(); + } + + String name = classNamesForAnonymousClasses.get(expression); + assert name != null; + return name; + } + + public ClassDescriptor getEclosingClassDescriptor(ClassDescriptor descriptor) { + return enclosing.get(descriptor); + } + + public boolean hasThis0(ClassDescriptor classDescriptor) { + if(CodegenUtil.isClassObject(classDescriptor)) + return false; + + ClassDescriptor other = enclosing.get(classDescriptor); + return other != null; + } + + private class MyJetVisitorVoid extends JetVisitorVoid { + private LinkedList classStack = new LinkedList(); + private LinkedList nameStack = new LinkedList(); + + private void recordEnclosing(ClassDescriptor classDescriptor) { + if(classStack.size() > 0) { + ClassDescriptor put = enclosing.put(classDescriptor, classStack.peek()); + assert put == null; + } + } + + private String recordAnonymousClass(JetElement declaration) { + String name = classNamesForAnonymousClasses.get(declaration); + assert name == null; + + String top = nameStack.peek(); + Integer cnt = anonymousSubclassesCount.get(top); + if(cnt == null) { + cnt = 0; + } + name = top + "$" + (cnt + 1); + classNamesForAnonymousClasses.put(declaration, name); + anonymousSubclassesCount.put(top, cnt + 1); + + return name; + } + + private String recordClassObject(JetClassObject declaration) { + String name = classNamesForAnonymousClasses.get(declaration.getObjectDeclaration()); + assert name == null; + + name = nameStack.peek() + JvmAbi.CLASS_OBJECT_SUFFIX; + classNamesForAnonymousClasses.put(declaration.getObjectDeclaration(), name); + + return name; + } + + @Override + public void visitJetElement(JetElement element) { + super.visitJetElement(element); + element.acceptChildren(this); + } + + @Override + public void visitJetFile(JetFile file) { + nameStack.push(JetPsiUtil.getFQName(file).replace('.', '/')); + file.acceptChildren(this); + nameStack.pop(); + } + + @Override + public void visitClassObject(JetClassObject classObject) { + String name = recordClassObject(classObject); + ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, classObject.getObjectDeclaration()); + recordEnclosing(classDescriptor); + recordName(classDescriptor, name); + classStack.push(classDescriptor); + nameStack.push(name); + super.visitClassObject(classObject); + nameStack.pop(); + classStack.pop(); + } + + @Override + public void visitObjectDeclaration(JetObjectDeclaration declaration) { + if(declaration.getParent() instanceof JetObjectLiteralExpression || declaration.getParent() instanceof JetClassObject) { + super.visitObjectDeclaration(declaration); + } + else { + ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, declaration); + recordEnclosing(classDescriptor); + classStack.push(classDescriptor); + String base = nameStack.peek(); + if(classDescriptor.getContainingDeclaration() instanceof NamespaceDescriptor) { + nameStack.push(base.isEmpty() ? classDescriptor.getName() : base + '/' + classDescriptor.getName()); + } + else + nameStack.push(base + '$' + classDescriptor.getName()); + super.visitObjectDeclaration(declaration); + nameStack.pop(); + classStack.pop(); + } + } + + @Override + public void visitClass(JetClass klass) { + ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, klass); + recordEnclosing(classDescriptor); + classStack.push(classDescriptor); + String base = nameStack.peek(); + if(classDescriptor.getContainingDeclaration() instanceof NamespaceDescriptor) { + nameStack.push(base.isEmpty() ? classDescriptor.getName() : base + '/' + classDescriptor.getName()); + } + else + nameStack.push(base + '$' + classDescriptor.getName()); + super.visitClass(klass); + nameStack.pop(); + classStack.pop(); + } + + @Override + public void visitObjectLiteralExpression(JetObjectLiteralExpression expression) { + String name = recordAnonymousClass(expression.getObjectDeclaration()); + ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, expression.getObjectDeclaration()); + recordName(classDescriptor, name); + recordEnclosing(classDescriptor); + classStack.push(classDescriptor); + nameStack.push(classNameForClassDescriptor(classDescriptor)); + super.visitObjectLiteralExpression(expression); + nameStack.pop(); + classStack.pop(); + } + + @Override + public void visitFunctionLiteralExpression(JetFunctionLiteralExpression expression) { + String name = recordAnonymousClass(expression.getFunctionLiteral()); + FunctionDescriptor declarationDescriptor = (FunctionDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, expression); + ClassDescriptor classDescriptor = classDescriptorForFunctionDescriptor(declarationDescriptor, name); + recordName(classDescriptor, name); + recordEnclosing(classDescriptor); + classStack.push(classDescriptor); + nameStack.push(classNameForClassDescriptor(classDescriptor)); + super.visitFunctionLiteralExpression(expression); + nameStack.pop(); + classStack.pop(); + } + + private void recordName(ClassDescriptor classDescriptor, String name) { + String old = classNamesForClassDescriptor.put(classDescriptor, name); + assert old == null; + } + + @Override + public void visitProperty(JetProperty property) { + nameStack.push(nameStack.peek() + '$' + property.getName()); + super.visitProperty(property); + nameStack.pop(); + } + + @Override + public void visitNamedFunction(JetNamedFunction function) { + FunctionDescriptor functionDescriptor = (FunctionDescriptor) bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, function); + DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration(); + if (containingDeclaration instanceof ClassDescriptor) { + nameStack.push(nameStack.peek() + '$' + function.getName()); + super.visitNamedFunction(function); + nameStack.pop(); + } + else if (containingDeclaration instanceof NamespaceDescriptor) { + String peek = nameStack.peek(); + if(peek.isEmpty()) + peek = "namespace"; + else + peek = peek + "/namespace"; + nameStack.push(peek + '$' + function.getName()); + super.visitNamedFunction(function); + nameStack.pop(); + } + else { + String name = recordAnonymousClass(function); + ClassDescriptor classDescriptor = classDescriptorForFunctionDescriptor(functionDescriptor, name); + recordName(classDescriptor, name); + recordEnclosing(classDescriptor); + classStack.push(classDescriptor); + nameStack.push(name); + super.visitNamedFunction(function); + nameStack.pop(); + classStack.pop(); + } + } + } + + public String classNameForClassDescriptor(ClassDescriptor classDescriptor) { + String name = classNamesForClassDescriptor.get(classDescriptor); + assert name != null; + return name; + } +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java index df5e3b9e66b..310039906e3 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -23,12 +23,10 @@ package org.jetbrains.jet.codegen; import com.intellij.openapi.util.Pair; import com.intellij.psi.PsiElement; import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.psi.JetDeclarationWithBody; import org.jetbrains.jet.lang.psi.JetElement; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetStandardClasses; import org.jetbrains.jet.lang.types.JetType; @@ -40,7 +38,6 @@ import org.objectweb.asm.commons.Method; import org.objectweb.asm.signature.SignatureWriter; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import static org.objectweb.asm.Opcodes.*; @@ -136,11 +133,11 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { ClassDescriptor thisDescriptor = context.getThisDescriptor(); final Type enclosingType = thisDescriptor == null ? null : state.getTypeMapper().mapType(thisDescriptor.getDefaultType()); if (enclosingType == null) - captureThis = false; + captureThis = null; final Method constructor = generateConstructor(funClass, fun); - if (captureThis) { + if (captureThis != null) { cv.newField(fun, ACC_FINAL, "this$0", enclosingType.getDescriptor(), null, null); } @@ -189,17 +186,8 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { } } - private boolean generateBody(FunctionDescriptor funDescriptor, ClassBuilder cv, JetDeclarationWithBody body) { - int arity = funDescriptor.getValueParameters().size(); - - ClassDescriptorImpl function = new ClassDescriptorImpl( - funDescriptor, - Collections.emptyList(), - name); - function = function.initialize( - false, - Collections.emptyList(), - Collections.singleton((funDescriptor.getReceiverParameter().exists() ? JetStandardClasses.getReceiverFunction(arity) : JetStandardClasses.getFunction(arity)).getDefaultType()), JetScope.EMPTY, Collections.emptySet(), null); + private Type generateBody(FunctionDescriptor funDescriptor, ClassBuilder cv, JetDeclarationWithBody body) { + ClassDescriptor function = state.getTypeMapper().getClosureAnnotator().classDescriptorForFunctionDescriptor(funDescriptor, name); final CodegenContext.ClosureContext closureContext = context.intoClosure(funDescriptor, function, name, this, state.getTypeMapper()); FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state); @@ -248,7 +236,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { } private Method generateConstructor(String funClass, PsiElement fun) { - int argCount = captureThis ? 1 : 0; + int argCount = captureThis != null ? 1 : 0; argCount += (captureReceiver != null ? 1 : 0); ArrayList variableDescriptors = new ArrayList(); @@ -270,7 +258,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { Type[] argTypes = new Type[argCount]; int i = 0; - if (captureThis) { + if (captureThis != null) { argTypes[i++] = state.getTypeMapper().mapType(context.getThisDescriptor().getDefaultType()); } @@ -285,7 +273,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { argTypes[i++] = type; } else if(CodegenUtil.isNamedFun(descriptor, state.getBindingContext()) && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) { - final Type type = Type.getObjectType(state.getTypeMapper().classNameForAnonymousClass((JetElement) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor))); + final Type type = Type.getObjectType(state.getTypeMapper().getClosureAnnotator().classNameForAnonymousClass((JetElement) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor))); argTypes[i++] = type; } } @@ -304,11 +292,11 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { StackValue.local(0, JetTypeMapper.TYPE_OBJECT).put(JetTypeMapper.TYPE_OBJECT, iv); StackValue.local(i, type).put(type, iv); final String fieldName; - if (captureThis && i == 1) { + if (captureThis != null && i == 1) { fieldName = "this$0"; } else { - if (captureReceiver != null && (captureThis && i == 2 || !captureThis && i == 1)) { + if (captureReceiver != null && (captureThis != null && i == 2 || captureThis == null && i == 1)) { fieldName = "receiver$0"; } else { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java index 9f203fc1ee2..5224d6aac84 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenContext.java @@ -68,7 +68,7 @@ public abstract class CodegenContext { protected StackValue outerExpression; - protected boolean outerWasUsed ; + protected Type outerWasUsed ; public CodegenContext(DeclarationDescriptor contextType, OwnerKind contextKind, @Nullable CodegenContext parentContext, @Nullable ObjectOrClosureCodegen closureCodegen) { this.contextType = contextType; @@ -100,7 +100,7 @@ public abstract class CodegenContext { if(outerExpression == null) throw new UnsupportedOperationException(); - outerWasUsed = true; + outerWasUsed = outerExpression.type; return prefix != null ? StackValue.composed(prefix, outerExpression) : outerExpression; } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java index 55ca8a33101..3edc00c3dfb 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/CodegenUtil.java @@ -59,21 +59,6 @@ public class CodegenUtil { return false; } - public static boolean hasThis0(ClassDescriptor classDescriptor) { - return getOuterClassDescriptor(classDescriptor) != null && !isClassObject(classDescriptor); - } - - public static ClassDescriptor getOuterClassDescriptor(DeclarationDescriptor descriptor) { - DeclarationDescriptor outerDescriptor = descriptor.getContainingDeclaration(); - while(outerDescriptor != null) { - if(outerDescriptor instanceof ClassDescriptor) - break; - - outerDescriptor = outerDescriptor.getContainingDeclaration(); - } - return (ClassDescriptor) outerDescriptor; - } - public static SimpleFunctionDescriptor createInvoke(FunctionDescriptor fd) { int arity = fd.getValueParameters().size(); SimpleFunctionDescriptorImpl invokeDescriptor = new SimpleFunctionDescriptorImpl( diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ConstructorFrameMap.java b/compiler/backend/src/org/jetbrains/jet/codegen/ConstructorFrameMap.java index 21b94c5fd5c..6c6ea28e187 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ConstructorFrameMap.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ConstructorFrameMap.java @@ -17,7 +17,6 @@ package org.jetbrains.jet.codegen; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.objectweb.asm.Type; @@ -33,10 +32,10 @@ public class ConstructorFrameMap extends FrameMap { private int myOuterThisIndex = -1; private int myTypeInfoIndex = -1; - public ConstructorFrameMap(CallableMethod callableMethod, @Nullable ConstructorDescriptor descriptor, ClassDescriptor classDescriptor, OwnerKind kind) { + public ConstructorFrameMap(CallableMethod callableMethod, @Nullable ConstructorDescriptor descriptor, boolean hasThis0) { enterTemp(); // this if (descriptor != null) { - if (CodegenUtil.hasThis0(classDescriptor)) { + if (hasThis0) { myOuterThisIndex = enterTemp(); // outer class instance } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 7fb90fc8eb0..9484a9a9368 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -809,7 +809,7 @@ public class ExpressionCodegen extends JetVisitor { if(closureCodegen.superCall != null) { ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, closureCodegen.superCall.getCalleeExpression().getConstructorReferenceExpression()); - CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION); + CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION, typeMapper.hasThis0(superConstructor.getContainingDeclaration())); Type[] argumentTypes = superCallable.getSignature().getAsmMethod().getArgumentTypes(); Collections.addAll(consArgTypes, argumentTypes); ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, closureCodegen.superCall.getCalleeExpression()); @@ -2258,7 +2258,7 @@ public class ExpressionCodegen extends JetVisitor { receiver.put(receiver.type, v); } - CallableMethod method = typeMapper.mapToCallableMethod((ConstructorDescriptor) constructorDescriptor, OwnerKind.IMPLEMENTATION); + CallableMethod method = typeMapper.mapToCallableMethod((ConstructorDescriptor) constructorDescriptor, OwnerKind.IMPLEMENTATION, typeMapper.hasThis0(((ConstructorDescriptor) constructorDescriptor).getContainingDeclaration())); invokeMethodWithArguments(method, expression, StackValue.none()); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/GeneratedAnonymousClassDescriptor.java b/compiler/backend/src/org/jetbrains/jet/codegen/GeneratedAnonymousClassDescriptor.java index 83d985ae84e..286aaa0fe0a 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/GeneratedAnonymousClassDescriptor.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/GeneratedAnonymousClassDescriptor.java @@ -28,11 +28,11 @@ import java.util.List; public class GeneratedAnonymousClassDescriptor { private final String classname; private Method constructor; - private final boolean captureThis; + private final Type captureThis; private final Type captureReceiver; private List args = new ArrayList(); - public GeneratedAnonymousClassDescriptor(String classname, Method constructor, boolean captureThis, Type captureReceiver) { + public GeneratedAnonymousClassDescriptor(String classname, Method constructor, Type captureThis, Type captureReceiver) { this.classname = classname; this.constructor = constructor; this.captureThis = captureThis; @@ -56,7 +56,7 @@ public class GeneratedAnonymousClassDescriptor { } public boolean isCaptureThis() { - return captureThis; + return captureThis != null; } public Type isCaptureReceiver() { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java index 6638960a7ae..cac631f6232 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/GenerationState.java @@ -22,7 +22,6 @@ package org.jetbrains.jet.codegen; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; -import com.intellij.psi.PsiElement; import com.intellij.util.containers.Stack; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods; @@ -102,7 +101,7 @@ public class GenerationState { } public Pair forAnonymousSubclass(JetExpression expression) { - String className = typeMapper.classNameForAnonymousClass(expression); + String className = typeMapper.getClosureAnnotator().classNameForAnonymousClass(expression); return Pair.create(className, factory.forAnonymousSubclass(className)); } @@ -113,7 +112,7 @@ public class GenerationState { public BindingContext compile(JetFile file) { final BindingContext bindingContext = AnalyzerFacade.analyzeOneFileWithJavaIntegration(file, JetControlFlowDataTraceFactory.EMPTY); AnalyzingUtils.throwExceptionOnErrors(bindingContext); - compileCorrectFiles(bindingContext, Collections.singletonList(file)); + compileCorrectFiles(bindingContext, Collections.singletonList(file), CompilationErrorHandler.THROW_EXCEPTION, true); return bindingContext; // NamespaceCodegen codegen = forNamespace(namespace); // bindingContexts.push(bindingContext); @@ -129,12 +128,13 @@ public class GenerationState { // } } - public void compileCorrectFiles(BindingContext bindingContext, List files) { - compileCorrectFiles(bindingContext, files, CompilationErrorHandler.THROW_EXCEPTION); + public void compileCorrectFiles(BindingContext bindingContext, List files, boolean annotate) { + compileCorrectFiles(bindingContext, files, CompilationErrorHandler.THROW_EXCEPTION, annotate); } - public void compileCorrectFiles(BindingContext bindingContext, List files, CompilationErrorHandler errorHandler) { - typeMapper = new JetTypeMapper(standardLibrary, bindingContext); + public void compileCorrectFiles(BindingContext bindingContext, List files, CompilationErrorHandler errorHandler, boolean annotate) { + ClosureAnnotator closureAnnotator = !annotate ? null : new ClosureAnnotator(bindingContext, files); + typeMapper = new JetTypeMapper(standardLibrary, bindingContext, closureAnnotator); bindingContexts.push(bindingContext); try { for (JetFile namespace : files) { @@ -172,30 +172,10 @@ public class GenerationState { new ImplementationBodyCodegen(objectDeclaration, objectContext, nameAndVisitor.getSecond(), this).generate(); ConstructorDescriptor constructorDescriptor = closure.state.getBindingContext().get(BindingContext.CONSTRUCTOR, objectDeclaration); - CallableMethod callableMethod = closure.state.getTypeMapper().mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION); + CallableMethod callableMethod = closure.state.getTypeMapper().mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION, typeMapper.hasThis0(constructorDescriptor.getContainingDeclaration())); return new GeneratedAnonymousClassDescriptor(nameAndVisitor.first, callableMethod.getSignature().getAsmMethod(), objectContext.outerWasUsed, null); } - public static void prepareAnonymousClasses(PsiElement element, final JetTypeMapper typeMapper) { - element.acceptChildren(new JetVisitorVoid() { - @Override - public void visitJetElement(JetElement element) { - super.visitJetElement(element); - element.acceptChildren(this); - } - - @Override - public void visitObjectLiteralExpression(JetObjectLiteralExpression expression) { - typeMapper.classNameForAnonymousClass(expression.getObjectDeclaration()); - } - - @Override - public void visitFunctionLiteralExpression(JetFunctionLiteralExpression expression) { - typeMapper.classNameForAnonymousClass(expression.getFunctionLiteral()); - } - }); - } - public String createText() { StringBuilder answer = new StringBuilder(); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index efd53abd0c5..e377090ba2c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -403,6 +403,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { JvmMethodSignature constructorMethod; CallableMethod callableMethod; + boolean hasThis0 = typeMapper.hasThis0(descriptor); if (constructorDescriptor == null) { BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, false); @@ -411,9 +412,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { signatureWriter.writeParametersStart(); - if (CodegenUtil.hasThis0(descriptor)) { + if (hasThis0) { signatureWriter.writeParameterType(JvmMethodParameterKind.THIS0); - typeMapper.mapType(CodegenUtil.getOuterClassDescriptor(descriptor).getDefaultType(), OwnerKind.IMPLEMENTATION, signatureWriter, false); + typeMapper.mapType(typeMapper.getClosureAnnotator().getEclosingClassDescriptor(descriptor).getDefaultType(), OwnerKind.IMPLEMENTATION, signatureWriter, false); signatureWriter.writeParameterTypeEnd(); } @@ -425,7 +426,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { callableMethod = new CallableMethod("", "", "", constructorMethod, INVOKESPECIAL); } else { - callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, kind); + callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, kind, typeMapper.hasThis0(constructorDescriptor.getContainingDeclaration())); constructorMethod = callableMethod.getSignature(); } @@ -435,13 +436,13 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { int insert = 0; if(closure != null) { - if(closure.captureThis) { - if(!CodegenUtil.hasThis0(descriptor)) + if(closure.captureThis != null) { + if(!hasThis0) consArgTypes.add(insert, new JvmMethodParameterSignature(Type.getObjectType(context.getThisDescriptor().getName()), "", JvmMethodParameterKind.THIS0)); insert++; } else { - if(CodegenUtil.hasThis0(descriptor)) + if(hasThis0) insert++; } @@ -469,7 +470,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { declarationDescriptor = ((ClassDescriptor)declarationDescriptor).getUnsubstitutedPrimaryConstructor(); } ConstructorDescriptor superConstructor = (ConstructorDescriptor) declarationDescriptor; - CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION); + CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION, typeMapper.hasThis0(superConstructor.getContainingDeclaration())); firstSuperArgument = insert; for(Type t : superCallable.getSignature().getAsmMethod().getArgumentTypes()) { consArgTypes.add(insert++, new JvmMethodParameterSignature(t, "", JvmMethodParameterKind.SHARED_VAR)); @@ -494,7 +495,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { if (constructorDescriptor != null) { int i = 0; - if (CodegenUtil.hasThis0(descriptor)) { + if (hasThis0) { i++; } @@ -514,7 +515,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { ? constructorDescriptor.getValueParameters() : Collections.emptyList(); - ConstructorFrameMap frameMap = new ConstructorFrameMap(callableMethod, constructorDescriptor, descriptor, kind); + ConstructorFrameMap frameMap = new ConstructorFrameMap(callableMethod, constructorDescriptor, hasThis0); final InstructionAdapter iv = new InstructionAdapter(mv); ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, constructorContext, state); @@ -548,9 +549,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { List parameterTypes = new ArrayList(); assert superType != null; ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); - if (CodegenUtil.hasThis0(superClassDescriptor)) { + if (typeMapper.hasThis0(superClassDescriptor)) { iv.load(1, JetTypeMapper.TYPE_OBJECT); - parameterTypes.add(typeMapper.mapType(CodegenUtil.getOuterClassDescriptor(descriptor).getDefaultType(), OwnerKind.IMPLEMENTATION)); + parameterTypes.add(typeMapper.mapType(typeMapper.getClosureAnnotator().getEclosingClassDescriptor(descriptor).getDefaultType(), OwnerKind.IMPLEMENTATION)); } Method superCallMethod = new Method("", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()])); iv.invokespecial(typeMapper.mapType(superClassDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "", superCallMethod.getDescriptor()); @@ -587,9 +588,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } } - final ClassDescriptor outerDescriptor = getOuterClassDescriptor(); - if (outerDescriptor != null && !CodegenUtil.isClassObject(outerDescriptor)) { - final Type type = typeMapper.mapType(outerDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION); + final ClassDescriptor outerDescriptor = typeMapper.getClosureAnnotator().getEclosingClassDescriptor(descriptor); + if (typeMapper.hasThis0(descriptor) && outerDescriptor != null) { + final Type type = typeMapper.mapType(outerDescriptor.getDefaultType()); String interfaceDesc = type.getDescriptor(); final String fieldName = "this$0"; v.newField(myClass, ACC_FINAL, fieldName, interfaceDesc, null, null); @@ -714,15 +715,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } } - @Nullable - private ClassDescriptor getOuterClassDescriptor() { - if (myClass.getParent() instanceof JetClassObject) { - return null; - } - - return CodegenUtil.getOuterClassDescriptor(descriptor); - } - private void generateDelegatorToConstructorCall(InstructionAdapter iv, ExpressionCodegen codegen, JetCallElement constructorCall, ConstructorDescriptor constructorDescriptor, ConstructorFrameMap frameMap, int firstSuperArgument) { @@ -734,11 +726,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { iv.load(frameMap.getOuterThisIndex(), typeMapper.mapType(((ClassDescriptor) descriptor.getContainingDeclaration()).getDefaultType(), OwnerKind.IMPLEMENTATION)); } - CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, kind); + CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, kind, typeMapper.hasThis0(constructorDescriptor.getContainingDeclaration())); if(myClass instanceof JetObjectDeclaration && superCall instanceof JetDelegatorToSuperCall && ((JetObjectDeclaration) myClass).isObjectLiteral()) { ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, ((JetDelegatorToSuperCall) superCall).getCalleeExpression().getConstructorReferenceExpression()); - CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION); + CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION, typeMapper.hasThis0(superConstructor.getContainingDeclaration())); int nextVar = firstSuperArgument+1; for(Type t : superCallable.getSignature().getAsmMethod().getArgumentTypes()) { iv.load(nextVar, t); @@ -799,7 +791,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { if (specifier instanceof JetDelegatorToSuperCall) { final JetDelegatorToSuperCall superCall = (JetDelegatorToSuperCall) specifier; ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, superCall.getCalleeExpression().getConstructorReferenceExpression()); - CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION); + CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION, typeMapper.hasThis0(constructorDescriptor.getContainingDeclaration())); codegen.invokeMethodWithArguments(method, superCall, StackValue.none()); } else { @@ -818,13 +810,13 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { if (constructorDescriptor == null) { throw new UnsupportedOperationException("failed to get descriptor for secondary constructor"); } - CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, kind); + CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, kind, typeMapper.hasThis0(constructorDescriptor.getContainingDeclaration())); int flags = ACC_PUBLIC; // TODO final MethodVisitor mv = v.newMethod(constructor, flags, "", method.getSignature().getAsmMethod().getDescriptor(), null, null); if (v.generateCode()) { mv.visitCode(); - ConstructorFrameMap frameMap = new ConstructorFrameMap(method, constructorDescriptor, descriptor, kind); + ConstructorFrameMap frameMap = new ConstructorFrameMap(method, constructorDescriptor, typeMapper.hasThis0(constructorDescriptor.getContainingDeclaration())); final InstructionAdapter iv = new InstructionAdapter(mv); ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index 4221e4d5566..b2e0c0a01f2 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -21,10 +21,12 @@ import com.intellij.psi.util.PsiTreeUtil; 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.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.java.*; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.*; import org.objectweb.asm.Opcodes; @@ -51,9 +53,17 @@ public class JetTypeMapper { public static final Type ARRAY_GENERIC_TYPE = Type.getType(Object[].class); private final JetStandardLibrary standardLibrary; - private final BindingContext bindingContext; - private final Map classNamesForAnonymousClasses = new HashMap(); - private final Map anonymousSubclassesCount = new HashMap(); + public final BindingContext bindingContext; + + public boolean hasThis0(ClassDescriptor classDescriptor) { + return closureAnnotator.hasThis0(classDescriptor); + } + + public ClosureAnnotator getClosureAnnotator() { + return closureAnnotator; + } + + private final ClosureAnnotator closureAnnotator; private final HashMap knowTypeNames = new HashMap(); private final HashMap knowTypes = new HashMap(); @@ -72,13 +82,10 @@ public class JetTypeMapper { public static final Type TYPE_FUNCTION0 = Type.getObjectType("jet/Function0"); public static final Type TYPE_FUNCTION1 = Type.getObjectType("jet/Function1"); - public JetStandardLibrary getStandardLibrary() { - return standardLibrary; - } - - public JetTypeMapper(JetStandardLibrary standardLibrary, BindingContext bindingContext) { + public JetTypeMapper(JetStandardLibrary standardLibrary, BindingContext bindingContext, ClosureAnnotator closureAnnotator) { this.standardLibrary = standardLibrary; this.bindingContext = bindingContext; + this.closureAnnotator = closureAnnotator; initKnownTypes(); initKnownTypeNames(); } @@ -193,7 +200,7 @@ public class JetTypeMapper { DeclarationDescriptor container = descriptor.getContainingDeclaration(); String name = descriptor.getName(); if(JetPsiUtil.NO_NAME_PROVIDED.equals(name)) { - return classNameForAnonymousClass((JetElement) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor)); + return closureAnnotator.classNameForAnonymousClass((JetElement) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor)); } if(name.contains("/")) return name; @@ -667,21 +674,20 @@ public class JetTypeMapper { return new JvmPropertyAccessorSignature(jvmMethodSignature, jvmMethodSignature.getKotlinParameterType(jvmMethodSignature.getParameterCount() - 1)); } - private JvmMethodSignature mapConstructorSignature(ConstructorDescriptor descriptor) { + private JvmMethodSignature mapConstructorSignature(ConstructorDescriptor descriptor, boolean hasThis0) { BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, true); List parameters = descriptor.getOriginal().getValueParameters(); - ClassDescriptor classDescriptor = descriptor.getContainingDeclaration(); // constructor type parmeters are fake writeFormalTypeParameters(Collections.emptyList(), signatureWriter); signatureWriter.writeParametersStart(); - if (CodegenUtil.hasThis0(classDescriptor)) { + if (hasThis0) { signatureWriter.writeParameterType(JvmMethodParameterKind.THIS0); - mapType(CodegenUtil.getOuterClassDescriptor(classDescriptor).getDefaultType(), OwnerKind.IMPLEMENTATION, signatureWriter); + mapType(closureAnnotator.getEclosingClassDescriptor(descriptor.getContainingDeclaration()).getDefaultType(), OwnerKind.IMPLEMENTATION, signatureWriter); signatureWriter.writeParameterTypeEnd(); } @@ -698,8 +704,8 @@ public class JetTypeMapper { return signatureWriter.makeJvmMethodSignature(""); } - public CallableMethod mapToCallableMethod(ConstructorDescriptor descriptor, OwnerKind kind) { - final JvmMethodSignature method = mapConstructorSignature(descriptor); + public CallableMethod mapToCallableMethod(ConstructorDescriptor descriptor, OwnerKind kind, boolean hasThis0) { + final JvmMethodSignature method = mapConstructorSignature(descriptor, hasThis0); String owner = mapType(descriptor.getContainingDeclaration().getDefaultType(), kind).getInternalName(); return new CallableMethod(owner, owner, owner, method, INVOKESPECIAL); } @@ -726,54 +732,6 @@ public class JetTypeMapper { } } - String classNameForAnonymousClass(JetElement expression) { - if(expression instanceof JetObjectLiteralExpression) { - JetObjectLiteralExpression jetObjectLiteralExpression = (JetObjectLiteralExpression) expression; - expression = jetObjectLiteralExpression.getObjectDeclaration(); - } - - if(expression instanceof JetFunctionLiteralExpression) { - JetFunctionLiteralExpression jetFunctionLiteralExpression = (JetFunctionLiteralExpression) expression; - expression = jetFunctionLiteralExpression.getFunctionLiteral(); - } - - String name = classNamesForAnonymousClasses.get(expression); - if (name != null) { - return name; - } - - @SuppressWarnings("unchecked") - PsiElement container = PsiTreeUtil.getParentOfType(expression, JetFile.class, JetClass.class, JetObjectDeclaration.class, JetFunctionLiteral.class); - - String baseName; - if(container instanceof JetFile) { - baseName = NamespaceCodegen.getJVMClassName(JetPsiUtil.getFQName(((JetFile) container)), true); - } - else if(container instanceof JetClass) { - ClassDescriptor aClass = bindingContext.get(BindingContext.CLASS, container); - baseName = mapType(aClass.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(); - - ClassDescriptor myClass = bindingContext.get(BindingContext.CLASS, expression); - if(CodegenUtil.isClassObject(myClass)) { - return mapType(aClass.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName() + JvmAbi.CLASS_OBJECT_SUFFIX; - } - else - baseName = classNameForAnonymousClass((JetElement) container); - } - else { - baseName = classNameForAnonymousClass((JetElement) container); - } - - Integer count = anonymousSubclassesCount.get(baseName); - if (count == null) count = 0; - - anonymousSubclassesCount.put(baseName, count + 1); - - final String className = baseName + "$" + (count + 1); - classNamesForAnonymousClasses.put(expression, className); - return className; - } - public Collection allJvmNames(JetClassOrObject jetClass) { Set result = new HashSet(); final ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, jetClass); @@ -856,7 +814,7 @@ public class JetTypeMapper { } else if (descriptor instanceof SimpleFunctionDescriptor && descriptor.getContainingDeclaration() instanceof FunctionDescriptor) { PsiElement psiElement = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor); - return Type.getObjectType(classNameForAnonymousClass((JetElement) psiElement)); + return Type.getObjectType(closureAnnotator.classNameForAnonymousClass((JetElement) psiElement)); } else if (descriptor instanceof FunctionDescriptor) { return StackValue.sharedTypeForType(mapType(((FunctionDescriptor) descriptor).getReceiverParameter().getType())); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JvmMethodParameterKind.java b/compiler/backend/src/org/jetbrains/jet/codegen/JvmMethodParameterKind.java index 6d464f09494..d0fdd813c14 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JvmMethodParameterKind.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JvmMethodParameterKind.java @@ -24,9 +24,7 @@ import org.jetbrains.jet.lang.descriptors.ClassDescriptor; public enum JvmMethodParameterKind { VALUE, THIS, - /** @see CodegenUtil#hasThis0(ClassDescriptor) */ THIS0, RECEIVER, - TYPE_INFO, SHARED_VAR, } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java index bd15f79af25..d417ad19eb5 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/NamespaceCodegen.java @@ -17,24 +17,15 @@ package org.jetbrains.jet.codegen; import com.intellij.psi.PsiFile; -import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.java.JvmAbi; -import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames; -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.TypeUtils; -import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Type; import org.objectweb.asm.commons.InstructionAdapter; -import java.util.List; - import static org.objectweb.asm.Opcodes.*; /** @@ -68,10 +59,6 @@ public class NamespaceCodegen { final PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, state); final ClassCodegen classCodegen = state.forClass(); - if (v.generateCode()) { - GenerationState.prepareAnonymousClasses(file, state.getTypeMapper()); - } - for (JetDeclaration declaration : file.getDeclarations()) { if (declaration instanceof JetProperty) { propertyCodegen.gen((JetProperty) declaration); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ObjectOrClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ObjectOrClosureCodegen.java index 69203c98bd9..549d30f2940 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ObjectOrClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ObjectOrClosureCodegen.java @@ -30,7 +30,7 @@ import java.util.Map; * @author alex.tkachman */ public class ObjectOrClosureCodegen { - protected boolean captureThis; + protected Type captureThis; protected Type captureReceiver; public final GenerationState state; @@ -83,7 +83,7 @@ public class ObjectOrClosureCodegen { if (idx < 0) return null; JetElement expression = (JetElement) state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, vd); - String cn = state.getTypeMapper().classNameForAnonymousClass(expression); + String cn = state.getTypeMapper().getClosureAnnotator().classNameForAnonymousClass(expression); Type localType = Type.getObjectType(cn); StackValue outerValue = StackValue.local(idx, localType); @@ -131,6 +131,6 @@ public class ObjectOrClosureCodegen { } public boolean isConst () { - return !captureThis && captureReceiver != null && closure.isEmpty(); + return captureThis == null && captureReceiver == null && closure.isEmpty(); } } diff --git a/compiler/cli/src/org/jetbrains/jet/compiler/CompileSession.java b/compiler/cli/src/org/jetbrains/jet/compiler/CompileSession.java index c8f97f02607..804730b40f6 100644 --- a/compiler/cli/src/org/jetbrains/jet/compiler/CompileSession.java +++ b/compiler/cli/src/org/jetbrains/jet/compiler/CompileSession.java @@ -25,10 +25,7 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import com.intellij.psi.PsiRecursiveElementWalkingVisitor; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.codegen.ClassBuilderFactory; -import org.jetbrains.jet.codegen.ClassFileFactory; -import org.jetbrains.jet.codegen.GenerationState; -import org.jetbrains.jet.codegen.JetTypeMapper; +import org.jetbrains.jet.codegen.*; import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassOrNamespaceDescriptor; @@ -201,7 +198,7 @@ public class CompileSession { public ClassFileFactory generate() { Project project = myEnvironment.getProject(); GenerationState generationState = new GenerationState(project, ClassBuilderFactory.BINARIES, myFileNameTransformer); - generationState.compileCorrectFiles(myBindingContext, mySourceFiles); + generationState.compileCorrectFiles(myBindingContext, mySourceFiles, CompilationErrorHandler.THROW_EXCEPTION, true); ClassFileFactory answer = generationState.getFactory(); List fileProcessors = myEnvironment.getCompilerPlugins(); 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 42ee6e39684..2cc50f58962 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 @@ -43,7 +43,9 @@ import com.intellij.util.containers.Stack; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.codegen.ClassBuilder; import org.jetbrains.jet.codegen.ClassBuilderFactory; +import org.jetbrains.jet.codegen.CompilationErrorHandler; import org.jetbrains.jet.codegen.GenerationState; +import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetPsiUtil; import org.jetbrains.jet.lang.resolve.BindingContext; @@ -184,8 +186,10 @@ public class JetLightClass extends AbstractLightClass implements JetJavaMirrorMa }; List files = Collections.singletonList(file); - final BindingContext context = AnalyzerFacade.shallowAnalyzeFiles(files); - state.compileCorrectFiles(context, files); +//todo: +// final BindingContext context = AnalyzerFacade.shallowAnalyzeFiles(files); + final BindingContext context = AnalyzerFacade.analyzeOneFileWithJavaIntegration(file, JetControlFlowDataTraceFactory.EMPTY); + state.compileCorrectFiles(context, files, CompilationErrorHandler.THROW_EXCEPTION, true); state.getFactory().files(); return answer; diff --git a/compiler/testData/codegen/objects/objectLiteralInClosure.jet b/compiler/testData/codegen/objects/objectLiteralInClosure.jet new file mode 100644 index 00000000000..d63c1c879fa --- /dev/null +++ b/compiler/testData/codegen/objects/objectLiteralInClosure.jet @@ -0,0 +1,17 @@ +package p + +class C(val y : Int) { + val initChild = { -> + object : java.lang.Object() { + override fun toString(): String { + return "child" + y + } + } + } +} + +fun box(): String { + val c = C(3).initChild + val x = c().toString() + return if(x == "child3") "OK" else x +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/ObjectGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/ObjectGenTest.java index a52c26c6f53..ee83ac306d9 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ObjectGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ObjectGenTest.java @@ -31,6 +31,11 @@ public class ObjectGenTest extends CodegenTestCase { // System.out.println(generateToText()); } + public void testObjectLiteralInClosure() throws Exception { + blackBoxFile("objects/objectLiteralInClosure.jet"); +// System.out.println(generateToText()); + } + public void testMethodOnObject() throws Exception { blackBoxFile("objects/methodOnObject.jet"); } diff --git a/compiler/tests/org/jetbrains/jet/codegen/TestlibTest.java b/compiler/tests/org/jetbrains/jet/codegen/TestlibTest.java index 41b752b19d4..67c38f688f2 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/TestlibTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/TestlibTest.java @@ -96,7 +96,8 @@ public class TestlibTest extends CodegenTestCase { new URLClassLoader(new URL[]{ForTestCompileStdlib.stdlibJarForTests().toURI().toURL(), junitJar.toURI().toURL()}, TestCase.class.getClassLoader())); - JetTypeMapper typeMapper = new JetTypeMapper(classFileFactory.state.getStandardLibrary(), session.getMyBindingContext()); + ClosureAnnotator closureAnnotator = new ClosureAnnotator(session.getMyBindingContext(), session.getSourceFileNamespaces()); + JetTypeMapper typeMapper = new JetTypeMapper(classFileFactory.state.getStandardLibrary(), session.getMyBindingContext(), closureAnnotator); TestSuite suite = new TestSuite("stdlib_test"); try { for(JetFile jetFile : session.getSourceFileNamespaces()) { diff --git a/idea/src/org/jetbrains/jet/plugin/debugger/JetPositionManager.java b/idea/src/org/jetbrains/jet/plugin/debugger/JetPositionManager.java index b57ef95a4ba..554a5e350ec 100644 --- a/idea/src/org/jetbrains/jet/plugin/debugger/JetPositionManager.java +++ b/idea/src/org/jetbrains/jet/plugin/debugger/JetPositionManager.java @@ -34,7 +34,7 @@ import com.sun.jdi.ReferenceType; import com.sun.jdi.request.ClassPrepareRequest; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.codegen.GenerationState; +import org.jetbrains.jet.codegen.ClosureAnnotator; import org.jetbrains.jet.codegen.JetTypeMapper; import org.jetbrains.jet.codegen.NamespaceCodegen; import org.jetbrains.jet.lang.psi.*; @@ -154,18 +154,8 @@ public class JetPositionManager implements PositionManager { } final BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file); final JetStandardLibrary standardLibrary = JetStandardLibrary.getInstance(); - final JetTypeMapper typeMapper = new JetTypeMapper(standardLibrary, bindingContext); - file.acceptChildren(new JetVisitorVoid() { - @Override - public void visitJetElement(JetElement element) { - element.acceptChildren(this); - } - - @Override - public void visitClass(JetClass klass) { - GenerationState.prepareAnonymousClasses(klass, typeMapper); - } - }); + ClosureAnnotator closureAnnotator = new ClosureAnnotator(bindingContext, Collections.singleton(file)); + final JetTypeMapper typeMapper = new JetTypeMapper(standardLibrary, bindingContext, closureAnnotator); myTypeMappers.put(file, typeMapper); return 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 c3189378eaa..2c5fdaf5244 100644 --- a/idea/src/org/jetbrains/jet/plugin/internal/codewindow/BytecodeToolwindow.java +++ b/idea/src/org/jetbrains/jet/plugin/internal/codewindow/BytecodeToolwindow.java @@ -38,6 +38,7 @@ import com.intellij.psi.PsiManager; import com.intellij.util.Alarm; import org.jetbrains.jet.codegen.ClassBuilderFactory; import org.jetbrains.jet.codegen.ClassFileFactory; +import org.jetbrains.jet.codegen.CompilationErrorHandler; import org.jetbrains.jet.codegen.GenerationState; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.resolve.AnalyzingUtils; @@ -203,7 +204,7 @@ public class BytecodeToolwindow extends JPanel implements Disposable { try { BindingContext binding = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile(file); AnalyzingUtils.throwExceptionOnErrors(binding); - state.compileCorrectFiles(binding, Collections.singletonList(file)); + state.compileCorrectFiles(binding, Collections.singletonList(file), CompilationErrorHandler.THROW_EXCEPTION, true); } catch (Exception e) { StringWriter out = new StringWriter(1024); e.printStackTrace(new PrintWriter(out)); From 84327d06c10e4a5c6f4a1efc8235864d03eaa466 Mon Sep 17 00:00:00 2001 From: James Strachan Date: Tue, 28 Feb 2012 09:08:39 +0000 Subject: [PATCH 4/4] added a demonstration of how Kotlin currently handles nullable collections on for loops - by throwing NPEs --- .../stdlib/testall/LanguageTestAllTest.java | 28 +++++++++++++++++++ .../test/language/NullableCollectionsTest.kt | 20 +++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 runtests/test/stdlib/testall/LanguageTestAllTest.java create mode 100644 testlib/test/language/NullableCollectionsTest.kt diff --git a/runtests/test/stdlib/testall/LanguageTestAllTest.java b/runtests/test/stdlib/testall/LanguageTestAllTest.java new file mode 100644 index 00000000000..3e4371e8e9e --- /dev/null +++ b/runtests/test/stdlib/testall/LanguageTestAllTest.java @@ -0,0 +1,28 @@ +/* + * 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 stdlib.testall; + +import junit.framework.TestSuite; +import test.language.*; + +/** + */ +public class LanguageTestAllTest { + public static TestSuite suite() { + return new TestSuite(NullableCollectionsTest.class); + } +} diff --git a/testlib/test/language/NullableCollectionsTest.kt b/testlib/test/language/NullableCollectionsTest.kt new file mode 100644 index 00000000000..213ce88cd56 --- /dev/null +++ b/testlib/test/language/NullableCollectionsTest.kt @@ -0,0 +1,20 @@ +package test.language + +import junit.framework.TestCase +import java.util.Collection +import stdhack.test.* + +class NullableCollectionsTest : TestCase() { + + fun testIterateOverNullCollectionsThrowsNPE() { + val c: Collection? = null + + // TODO currently this will throw a NPE + // should it either be a compile error or handle nulls gracefully? + failsWith { + for (e in c) { + println("Hey got $e") + } + } + } +}