diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement1.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement1.java index 8d10286885c..5d19f299ae8 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement1.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement1.java @@ -1,6 +1,7 @@ package org.jetbrains.jet.lang.diagnostics; import com.intellij.lang.ASTNode; +import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; @@ -22,16 +23,21 @@ public abstract class DiagnosticFactoryWithPsiElement1 @NotNull public Diagnostic on(@NotNull T element, @NotNull A argument) { - return on(element, element.getNode(), argument); + return on(element, element.getTextRange(), argument); } @NotNull public Diagnostic on(@NotNull T element, @NotNull ASTNode node, @NotNull A argument) { - return new DiagnosticWithPsiElementImpl(this, severity, makeMessage(argument), element, node.getTextRange()); + return on(element, node.getTextRange(), argument); } @NotNull public Diagnostic on(@NotNull T element, @NotNull PsiElement psiElement, @NotNull A argument) { - return new DiagnosticWithPsiElementImpl(this, severity, makeMessage(argument), element, psiElement.getTextRange()); + return on(element, psiElement.getTextRange(), argument); + } + + @NotNull + protected Diagnostic on(@NotNull T element, @NotNull TextRange textRange, @NotNull A argument) { + return new DiagnosticWithPsiElementImpl(this, severity, makeMessage(argument), element, textRange); } } \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement3.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement3.java new file mode 100644 index 00000000000..921e28405b1 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactoryWithPsiElement3.java @@ -0,0 +1,52 @@ +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 class DiagnosticFactoryWithPsiElement3 extends DiagnosticFactoryWithMessageFormat { + protected DiagnosticFactoryWithPsiElement3(Severity severity, String messageStub) { + super(severity, messageStub); + } + + 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 a.toString(); + } + + protected String makeMessageForB(@NotNull B b) { + return b.toString(); + } + + protected String makeMessageForC(@NotNull C c) { + return c.toString(); + } + + @NotNull + public Diagnostic on(@NotNull T element, @NotNull A a, @NotNull B b, @NotNull C c) { + return on(element, element, a, b, c); + } + + @NotNull + public Diagnostic on(@NotNull T element, @NotNull PsiElement psiElement, @NotNull A a, @NotNull B b, @NotNull C c) { + return on(element, psiElement.getTextRange(), a, b, c); + } + + @NotNull + public Diagnostic on(@NotNull T element, @NotNull ASTNode node, @NotNull A a, @NotNull B b, @NotNull C c) { + return on(element, node.getTextRange(), a, b, c); + } + + @NotNull + protected Diagnostic on(@NotNull T element, @NotNull TextRange textRange, @NotNull A a, @NotNull B b, @NotNull C c) { + return new DiagnosticWithPsiElementImpl(this, severity, makeMessage(a, b, c), element, textRange); + } + +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithAdditionalInfo.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithAdditionalInfo.java new file mode 100644 index 00000000000..a1374e5bb6a --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithAdditionalInfo.java @@ -0,0 +1,26 @@ +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 DiagnosticWithAdditionalInfo extends DiagnosticWithPsiElementImpl { + private final I info; + + public DiagnosticWithAdditionalInfo(DiagnosticFactory factory, Severity severity, String message, T psiElement, I info) { + super(factory, severity, message, psiElement); + this.info = info; + } + + public DiagnosticWithAdditionalInfo(DiagnosticFactory factory, Severity severity, String message, T psiElement, @NotNull TextRange textRange, I info) { + super(factory, severity, message, psiElement, textRange); + this.info = info; + } + + public I getInfo() { + return info; + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithAdditionalInfoFactory1.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithAdditionalInfoFactory1.java new file mode 100644 index 00000000000..fa9200d63a8 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticWithAdditionalInfoFactory1.java @@ -0,0 +1,24 @@ +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 DiagnosticWithAdditionalInfoFactory1 extends PsiElementOnlyDiagnosticFactory1 { + public static DiagnosticWithAdditionalInfoFactory1 create(Severity severity, String messageStub) { + return new DiagnosticWithAdditionalInfoFactory1(severity, messageStub); + } + + protected DiagnosticWithAdditionalInfoFactory1(Severity severity, String message) { + super(severity, message); + } + + @NotNull + @Override + protected Diagnostic on(@NotNull T element, @NotNull TextRange textRange, @NotNull A argument) { + return new DiagnosticWithAdditionalInfo(this, severity, makeMessage(argument), element, textRange, argument); + } +} 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 0a3919c9174..73cd701c5f7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -1,5 +1,7 @@ package org.jetbrains.jet.lang.diagnostics; +import com.intellij.lang.ASTNode; +import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.*; @@ -43,25 +45,36 @@ public interface Errors { SimpleDiagnosticFactory PROPERTY_WITH_NO_TYPE_NO_INITIALIZER = SimpleDiagnosticFactory.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"); - SimpleDiagnosticFactory ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS = SimpleDiagnosticFactory.create(ERROR, "This property cannot be declared abstract"); - SimpleDiagnosticFactory ABSTRACT_PROPERTY_NOT_IN_CLASS = SimpleDiagnosticFactory.create(ERROR, "A property may be abstract only when defined in a class or trait"); - SimpleDiagnosticFactory ABSTRACT_PROPERTY_WITH_INITIALIZER = SimpleDiagnosticFactory.create(ERROR, "Property with initializer cannot be abstract"); - SimpleDiagnosticFactory ABSTRACT_PROPERTY_WITH_GETTER = SimpleDiagnosticFactory.create(ERROR, "Property with getter implementation cannot be abstract"); - SimpleDiagnosticFactory ABSTRACT_PROPERTY_WITH_SETTER = SimpleDiagnosticFactory.create(ERROR, "Property with setter implementation cannot be abstract"); + 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"); + //TODO pass String instead of JetType or ensure JetType's value is computed + DiagnosticWithAdditionalInfoFactory1 ABSTRACT_PROPERTY_WITH_INITIALIZER = DiagnosticWithAdditionalInfoFactory1.create(ERROR, "Property with initializer cannot be abstract"); + DiagnosticWithAdditionalInfoFactory1 ABSTRACT_PROPERTY_WITH_GETTER = DiagnosticWithAdditionalInfoFactory1.create(ERROR, "Property with getter implementation cannot be abstract"); + DiagnosticWithAdditionalInfoFactory1 ABSTRACT_PROPERTY_WITH_SETTER = DiagnosticWithAdditionalInfoFactory1.create(ERROR, "Property with setter implementation cannot be abstract"); 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"); - SimpleDiagnosticFactory MUST_BE_INITIALIZED_OR_BE_ABSTRACT = SimpleDiagnosticFactory.create(ERROR, "Property must be initialized or be abstract"); + SimplePsiElementOnlyDiagnosticFactory MUST_BE_INITIALIZED_OR_BE_ABSTRACT = SimplePsiElementOnlyDiagnosticFactory.create(ERROR, "Property must be initialized or be abstract"); SimpleDiagnosticFactory PROPERTY_INITIALIZER_IN_TRAIT = SimpleDiagnosticFactory.create(ERROR, "Property initializers are not allowed in traits"); SimpleDiagnosticFactory PROPERTY_INITIALIZER_NO_BACKING_FIELD = SimpleDiagnosticFactory.create(ERROR, "Initializer is not allowed here because this property has no backing field"); SimpleDiagnosticFactory PROPERTY_INITIALIZER_NO_PRIMARY_CONSTRUCTOR = SimpleDiagnosticFactory.create(ERROR, "Property initializers are not allowed when no primary constructor is present"); SimplePsiElementOnlyDiagnosticFactory REDUNDANT_ABSTRACT = SimplePsiElementOnlyDiagnosticFactory.create(WARNING, "Abstract modifier is redundant in traits"); - PsiElementOnlyDiagnosticFactory2 ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS = PsiElementOnlyDiagnosticFactory2.create(ERROR, "Abstract property {0} in non-abstract class {1}"); - ParameterizedDiagnosticFactory2 ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS = ParameterizedDiagnosticFactory2.create(ERROR, "Abstract function {0} in non-abstract class {1}"); - ParameterizedDiagnosticFactory1 ABSTRACT_FUNCTION_WITH_BODY = ParameterizedDiagnosticFactory1.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"); - ParameterizedDiagnosticFactory1 NON_MEMBER_ABSTRACT_FUNCTION = ParameterizedDiagnosticFactory1.create(ERROR, "Function {0} is not a class or trait member and cannot be abstract"); - SimpleDiagnosticFactory NON_MEMBER_ABSTRACT_ACCESSOR = SimpleDiagnosticFactory.create(ERROR, "This property is not a class or trait member and thus cannot have abstract accessors"); // TODO : Better message - ParameterizedDiagnosticFactory1 NON_MEMBER_FUNCTION_NO_BODY = ParameterizedDiagnosticFactory1.create(ERROR, "Function {0} must have a body"); + PsiElementOnlyDiagnosticFactory3 ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS = new PsiElementOnlyDiagnosticFactory3(ERROR, "Abstract property {0} in non-abstract class {1}") { + @NotNull + protected Diagnostic on(@NotNull JetModifierListOwner element, @NotNull TextRange textRange, @NotNull String s, @NotNull ClassDescriptor classDescriptor, @NotNull JetClass jetClass) { + return new DiagnosticWithAdditionalInfo(this, severity, makeMessage(s, classDescriptor, jetClass), element, textRange, jetClass); + } + }; + PsiElementOnlyDiagnosticFactory3 ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS = new PsiElementOnlyDiagnosticFactory3(ERROR, "Abstract function {0} in non-abstract class {1}") { + @NotNull + public Diagnostic on(@NotNull JetFunctionOrPropertyAccessor element, @NotNull ASTNode node, @NotNull String s, @NotNull ClassDescriptor classDescriptor, @NotNull JetModifierListOwner jetClass) { + return new DiagnosticWithAdditionalInfo(this, severity, makeMessage(s, classDescriptor, jetClass), element, node.getTextRange(), jetClass); + } + }; + 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"); + SimplePsiElementOnlyDiagnosticFactory NON_MEMBER_ABSTRACT_ACCESSOR = SimplePsiElementOnlyDiagnosticFactory.create(ERROR, "This property is not a class or trait member and thus cannot have abstract accessors"); // TODO : Better message + PsiElementOnlyDiagnosticFactory1 NON_MEMBER_FUNCTION_NO_BODY = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Function {0} must have a body"); SimpleDiagnosticFactory PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT = SimpleDiagnosticFactory.create(ERROR, "Projections are not allowed on type arguments of functions and properties"); // TODO : better positioning @@ -71,7 +84,7 @@ public interface Errors { 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"); - ParameterizedDiagnosticFactory1 NOTHING_TO_OVERRIDE = ParameterizedDiagnosticFactory1.create(ERROR, "Function {0} overrides nothing"); + PsiElementOnlyDiagnosticFactory1 NOTHING_TO_OVERRIDE = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Function {0} overrides nothing"); ParameterizedDiagnosticFactory1 PRIMARY_CONSTRUCTOR_MISSING_STATEFUL_PROPERTY = ParameterizedDiagnosticFactory1.create(ERROR, "This class must have a primary constructor, because property {0} has a backing field"); ParameterizedDiagnosticFactory1 PRIMARY_CONSTRUCTOR_MISSING_SUPER_CONSTRUCTOR_CALL = new ParameterizedDiagnosticFactory1(ERROR, "Class {0} must have a constructor in order to be able to initialize supertypes") { @Override @@ -85,7 +98,7 @@ public interface Errors { return e.getClass().getSimpleName() + ": " + e.getMessage(); } }; - ParameterizedDiagnosticFactory3 VIRTUAL_METHOD_HIDDEN = ParameterizedDiagnosticFactory3.create(ERROR, "Function '{0}' hides '{1}' in class {2} and needs 'override' modifier"); + PsiElementOnlyDiagnosticFactory3 VIRTUAL_METHOD_HIDDEN = PsiElementOnlyDiagnosticFactory3.create(ERROR, "Function '{0}' hides '{1}' in class {2} and needs 'override' modifier"); SimpleDiagnosticFactory UNREACHABLE_CODE = SimpleDiagnosticFactory.create(ERROR, "Unreachable code"); ParameterizedDiagnosticFactory1 UNREACHABLE_BECAUSE_OF_NOTHING = ParameterizedDiagnosticFactory1.create(ERROR, "This code is unreachable, because '{0}' never terminates normally"); @@ -100,7 +113,7 @@ public interface Errors { 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"); - SimpleDiagnosticFactory VAL_WITH_SETTER = SimpleDiagnosticFactory.create(ERROR, "A 'val'-property cannot have a setter"); + SimplePsiElementOnlyDiagnosticFactory VAL_WITH_SETTER = SimplePsiElementOnlyDiagnosticFactory.create(ERROR, "A 'val'-property cannot have a setter"); 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"); @@ -111,11 +124,11 @@ public interface Errors { SimpleDiagnosticFactory NO_THIS = SimpleDiagnosticFactory.create(ERROR, "'this' is not defined in this context"); SimpleDiagnosticFactory NOT_A_SUPERTYPE = SimpleDiagnosticFactory.create(ERROR, "Not a supertype"); SimpleDiagnosticFactory NO_WHEN_ENTRIES = SimpleDiagnosticFactory.create(ERROR, "Entries are required for when-expression"); // TODO : Scope, and maybe this should not be an error - SimpleDiagnosticFactory USELESS_CAST_STATIC_ASSERT_IS_FINE = SimpleDiagnosticFactory.create(WARNING, "No cast needed, use ':' instead"); - SimpleDiagnosticFactory USELESS_CAST = SimpleDiagnosticFactory.create(WARNING, "No cast needed"); + 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"); - ParameterizedDiagnosticFactory1 WRONG_SETTER_PARAMETER_TYPE = ParameterizedDiagnosticFactory1.create(ERROR, "Setter parameter type must be equal to the type of the property, i.e. {0}"); - ParameterizedDiagnosticFactory1 WRONG_GETTER_RETURN_TYPE = ParameterizedDiagnosticFactory1.create(ERROR, "Getter return type must be equal to the type of the property, i.e. {0}"); + DiagnosticWithAdditionalInfoFactory1 WRONG_SETTER_PARAMETER_TYPE = DiagnosticWithAdditionalInfoFactory1.create(ERROR, "Setter parameter type must be equal to the type of the property, i.e. {0}"); + DiagnosticWithAdditionalInfoFactory1 WRONG_GETTER_RETURN_TYPE = DiagnosticWithAdditionalInfoFactory1.create(ERROR, "Getter return type must be equal to the type of the property, i.e. {0}"); ParameterizedDiagnosticFactory1 NO_CLASS_OBJECT = new ParameterizedDiagnosticFactory1(ERROR, "Classifier {0} does not have a class object") { @Override protected String makeMessageFor(@NotNull ClassifierDescriptor argument) { @@ -145,7 +158,7 @@ public interface Errors { 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"); - ParameterizedDiagnosticFactory1 USELESS_ELVIS = ParameterizedDiagnosticFactory1.create(WARNING, "Elvis operator (?:) always returns the left operand of non-nullable type {0}"); + 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) { @@ -182,7 +195,7 @@ public interface Errors { 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}"); + PsiElementOnlyDiagnosticFactory1 UNNECESSARY_SAFE_CALL = PsiElementOnlyDiagnosticFactory1.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}") { @Override protected String makeMessageForA(@NotNull JetTypeConstraint jetTypeConstraint) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory3.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory3.java index fafff17af01..77e7e047c75 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory3.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/ParameterizedDiagnosticFactory3.java @@ -9,31 +9,15 @@ import org.jetbrains.annotations.NotNull; /** * @author abreslav */ -public class ParameterizedDiagnosticFactory3 extends DiagnosticFactoryWithMessageFormat { +public class ParameterizedDiagnosticFactory3 extends DiagnosticFactoryWithPsiElement3 { public static ParameterizedDiagnosticFactory3 create(Severity severity, String messageStub) { return new ParameterizedDiagnosticFactory3(severity, messageStub); } - public ParameterizedDiagnosticFactory3(Severity severity, String messageStub) { + protected ParameterizedDiagnosticFactory3(Severity severity, String messageStub) { super(severity, messageStub); } - 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 a.toString(); - } - - protected String makeMessageForB(@NotNull B b) { - return b.toString(); - } - - protected String makeMessageForC(@NotNull C c) { - return c.toString(); - } - @NotNull public Diagnostic on(@NotNull PsiFile psiFile, @NotNull TextRange range, @NotNull A a, @NotNull B b, @NotNull C c) { return new GenericDiagnostic(this, severity, makeMessage(a, b, c), psiFile, range); @@ -43,9 +27,4 @@ public class ParameterizedDiagnosticFactory3 extends DiagnosticFactoryW public Diagnostic on(@NotNull ASTNode node, @NotNull A a, @NotNull B b, @NotNull C c) { return on(DiagnosticUtils.getContainingFile(node), node.getTextRange(), a, b, c); } - - @NotNull - public Diagnostic on(@NotNull PsiElement element, @NotNull A a, @NotNull B b, @NotNull C c) { - return new DiagnosticWithPsiElementImpl(this, severity, makeMessage(a, b, c), element); - } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PsiElementOnlyDiagnosticFactory3.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PsiElementOnlyDiagnosticFactory3.java new file mode 100644 index 00000000000..eb7a0a3753c --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/PsiElementOnlyDiagnosticFactory3.java @@ -0,0 +1,15 @@ +package org.jetbrains.jet.lang.diagnostics; + +import com.intellij.psi.PsiElement; +/** + * @author svtk + */ +public class PsiElementOnlyDiagnosticFactory3 extends DiagnosticFactoryWithPsiElement3 implements PsiElementOnlyDiagnosticFactory { + protected PsiElementOnlyDiagnosticFactory3(Severity severity, String messageStub) { + super(severity, messageStub); + } + + public static PsiElementOnlyDiagnosticFactory3 create(Severity severity, String messageStub) { + return new PsiElementOnlyDiagnosticFactory3(severity, messageStub); + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/SimpleDiagnosticFactoryWithPsiElement.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/SimpleDiagnosticFactoryWithPsiElement.java index 89c1929ca7a..f11e699ea5a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/SimpleDiagnosticFactoryWithPsiElement.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/SimpleDiagnosticFactoryWithPsiElement.java @@ -7,22 +7,27 @@ import org.jetbrains.annotations.NotNull; /** * @author svtk */ -public abstract class SimpleDiagnosticFactoryWithPsiElement extends DiagnosticFactoryWithSeverity { +public abstract class SimpleDiagnosticFactoryWithPsiElement extends DiagnosticFactoryWithSeverity { - protected final String message; + protected final String message; - protected SimpleDiagnosticFactoryWithPsiElement(Severity severity, String message) { - super(severity); - this.message = message; - } + protected SimpleDiagnosticFactoryWithPsiElement(Severity severity, String message) { + super(severity); + this.message = message; + } - @NotNull - public Diagnostic on(@NotNull T element, @NotNull ASTNode node) { - return new DiagnosticWithPsiElementImpl(this, severity, message, element, node.getTextRange()); - } + @NotNull + public Diagnostic on(@NotNull T element, @NotNull ASTNode node) { + return new DiagnosticWithPsiElementImpl(this, severity, message, element, node.getTextRange()); + } - @NotNull - public Diagnostic on(@NotNull T element) { - return on(element, element.getNode()); - } + @NotNull + public Diagnostic on(@NotNull T element, @NotNull PsiElement psiElement) { + return new DiagnosticWithPsiElementImpl(this, severity, message, element, psiElement.getTextRange()); + } + + @NotNull + public Diagnostic on(@NotNull T element) { + return on(element, element.getNode()); + } } \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetClass.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetClass.java index 2433e1c17b4..176693cc17c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetClass.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetClass.java @@ -13,7 +13,7 @@ import java.util.List; /** * @author max */ -public class JetClass extends JetTypeParameterListOwner implements JetClassOrObject { +public class JetClass extends JetTypeParameterListOwner implements JetClassOrObject, JetModifierListOwner { public JetClass(@NotNull ASTNode node) { super(node); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunction.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunction.java index 52c987ea24f..09fee5a8b43 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunction.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunction.java @@ -14,7 +14,7 @@ import java.util.List; /** * @author abreslav */ -abstract public class JetFunction extends JetTypeParameterListOwner implements JetDeclarationWithBody, JetModifierListOwner { +abstract public class JetFunction extends JetTypeParameterListOwner implements JetFunctionOrPropertyAccessor { public JetFunction(@NotNull ASTNode node) { super(node); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunctionOrPropertyAccessor.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunctionOrPropertyAccessor.java new file mode 100644 index 00000000000..9ce62477999 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetFunctionOrPropertyAccessor.java @@ -0,0 +1,7 @@ +package org.jetbrains.jet.lang.psi; + +/** + * @author svtk + */ +public interface JetFunctionOrPropertyAccessor extends JetDeclarationWithBody, JetModifierListOwner { +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPropertyAccessor.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPropertyAccessor.java index 291c381e2d1..328ae7b3e68 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPropertyAccessor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPropertyAccessor.java @@ -12,7 +12,7 @@ import java.util.List; /** * @author max */ -public class JetPropertyAccessor extends JetDeclaration implements JetDeclarationWithBody, JetModifierListOwner { +public class JetPropertyAccessor extends JetDeclaration implements JetFunctionOrPropertyAccessor { public JetPropertyAccessor(@NotNull ASTNode node) { super(node); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiFactory.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiFactory.java index e58d0e51878..75f9a9a76d5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiFactory.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiFactory.java @@ -43,8 +43,8 @@ public class JetPsiFactory { return (JetFile) PsiFileFactory.getInstance(project).createFileFromText("dummy.jet", JetFileType.INSTANCE, text, LocalTimeCounter.currentTime(), true); } - public static JetProperty createProperty(Project project, String name, String type) { - String text = "val " + name + (type != null ? ":" + type : ""); + public static JetProperty createProperty(Project project, String name, String type, boolean isVar) { + String text = (isVar ? "var " : "val ") + name + (type != null ? ":" + type : ""); return createProperty(project, text); } @@ -63,7 +63,7 @@ public class JetPsiFactory { } public static PsiElement createNameIdentifier(Project project, String name) { - return createProperty(project, name, null).getNameIdentifier(); + return createProperty(project, name, null, false).getNameIdentifier(); } public static JetNamedFunction createFunction(Project project, String funDecl) { @@ -75,4 +75,9 @@ public class JetPsiFactory { JetProperty property = createProperty(project, text); return property.getModifierList(); } + + public static JetExpression createEmptyBody(Project project) { + JetNamedFunction function = createFunction(project, "fun foo() {}"); + return function.getBodyExpression(); + } } 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 64ceb724c88..ce6928ab8be 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java @@ -13,7 +13,6 @@ import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; -import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionCallableReceiver; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lexer.JetTokens; @@ -188,7 +187,7 @@ public class BodyResolver { } if (hasOverrideModifier && declaredFunction.getOverriddenDescriptors().size() == 0) { // context.getTrace().getErrorHandler().genericError(overrideNode, "Method " + declaredFunction.getName() + " overrides nothing"); - context.getTrace().report(NOTHING_TO_OVERRIDE.on(overrideNode, declaredFunction)); + context.getTrace().report(NOTHING_TO_OVERRIDE.on(function, overrideNode, declaredFunction)); } PsiElement nameIdentifier = function.getNameIdentifier(); if (!hasOverrideModifier && declaredFunction.getOverriddenDescriptors().size() > 0 && nameIdentifier != null) { @@ -196,7 +195,7 @@ public class BodyResolver { // context.getTrace().getErrorHandler().genericError(nameIdentifier.getNode(), // "Method '" + declaredFunction.getName() + "' overrides method '" + overriddenFunction.getName() + "' in class " + // overriddenFunction.getContainingDeclaration().getName() + " and needs 'override' modifier"); - context.getTrace().report(VIRTUAL_METHOD_HIDDEN.on(nameIdentifier, declaredFunction, overriddenFunction, overriddenFunction.getContainingDeclaration())); + context.getTrace().report(VIRTUAL_METHOD_HIDDEN.on(function, nameIdentifier, declaredFunction, overriddenFunction, overriddenFunction.getContainingDeclaration())); } } @@ -616,12 +615,14 @@ public class BodyResolver { if (abstractNode != null) { //has abstract modifier if (classDescriptor == null) { // context.getTrace().getErrorHandler().genericError(abstractNode, "A property may be abstract only when defined in a class or trait"); - context.getTrace().report(ABSTRACT_PROPERTY_NOT_IN_CLASS.on(abstractNode)); + context.getTrace().report(ABSTRACT_PROPERTY_NOT_IN_CLASS.on(property, abstractNode)); return; } if (!(classDescriptor.getModality() == Modality.ABSTRACT) && classDescriptor.getKind() != ClassKind.ENUM_CLASS) { // context.getTrace().getErrorHandler().genericError(abstractNode, "Abstract property " + property.getName() + " in non-abstract class " + classDescriptor.getName()); - context.getTrace().report(ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS.on(property, abstractNode, property.getName(), classDescriptor)); + PsiElement classElement = context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, classDescriptor); + assert classElement instanceof JetClass; + context.getTrace().report(ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS.on(property, abstractNode, property.getName(), classDescriptor, (JetClass) classElement)); return; } if (classDescriptor.getKind() == ClassKind.TRAIT) { @@ -631,18 +632,22 @@ public class BodyResolver { } if (propertyDescriptor.getModality() == Modality.ABSTRACT) { + JetType returnType = propertyDescriptor.getReturnType(); + //TODO We need ensure here that jet type is computed or pass it's computed name to quick fix instead + returnType.equals(new Object()); + JetExpression initializer = property.getInitializer(); if (initializer != null) { // context.getTrace().getErrorHandler().genericError(initializer.getNode(), "Property with initializer cannot be abstract"); - context.getTrace().report(ABSTRACT_PROPERTY_WITH_INITIALIZER.on(initializer)); + context.getTrace().report(ABSTRACT_PROPERTY_WITH_INITIALIZER.on(property, initializer, returnType)); } if (getter != null && getter.getBodyExpression() != null) { // context.getTrace().getErrorHandler().genericError(getter.getNode(), "Property with getter implementation cannot be abstract"); - context.getTrace().report(ABSTRACT_PROPERTY_WITH_GETTER.on(getter)); + context.getTrace().report(ABSTRACT_PROPERTY_WITH_GETTER.on(property, getter, returnType)); } if (setter != null && setter.getBodyExpression() != null) { // context.getTrace().getErrorHandler().genericError(setter.getNode(), "Property with setter implementation cannot be abstract"); - context.getTrace().report(ABSTRACT_PROPERTY_WITH_SETTER.on(setter)); + context.getTrace().report(ABSTRACT_PROPERTY_WITH_SETTER.on(property, setter, returnType)); } } } @@ -672,7 +677,7 @@ public class BodyResolver { context.getTrace().report(MUST_BE_INITIALIZED.on(nameNode)); } else { // context.getTrace().getErrorHandler().genericError(nameNode, "Property must be initialized or be abstract"); - context.getTrace().report(MUST_BE_INITIALIZED_OR_BE_ABSTRACT.on(nameNode)); + context.getTrace().report(MUST_BE_INITIALIZED_OR_BE_ABSTRACT.on(property, nameNode)); } } return; @@ -785,8 +790,8 @@ public class BodyResolver { else { throw new UnsupportedOperationException(); } - JetModifierListOwner modifierListOwner = (JetModifierListOwner) function; - JetModifierList modifierList = modifierListOwner.getModifierList(); + JetFunctionOrPropertyAccessor functionOrPropertyAccessor = (JetFunctionOrPropertyAccessor) function; + JetModifierList modifierList = functionOrPropertyAccessor.getModifierList(); ASTNode abstractNode = modifierList != null ? modifierList.getModifierNode(JetTokens.ABSTRACT_KEYWORD) : null; boolean hasAbstractModifier = abstractNode != null; if (containingDescriptor instanceof ClassDescriptor) { @@ -794,38 +799,32 @@ public class BodyResolver { boolean inTrait = classDescriptor.getKind() == ClassKind.TRAIT; boolean inEnum = classDescriptor.getKind() == ClassKind.ENUM_CLASS; boolean inAbstractClass = classDescriptor.getModality() == Modality.ABSTRACT; -// String methodName = function.getName() != null ? function.getName() + " " : ""; if (hasAbstractModifier && !inAbstractClass && !inTrait && !inEnum) { -// context.getTrace().getErrorHandler().genericError(abstractNode, "Abstract method " + methodName + " in non-abstract class " + classDescriptor.getName()); - context.getTrace().report(ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS.on(abstractNode, functionDescriptor.getName(), classDescriptor)); + PsiElement classElement = context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, classDescriptor); + assert classElement instanceof JetModifierListOwner; + context.getTrace().report(ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS.on(functionOrPropertyAccessor, abstractNode, functionDescriptor.getName(), classDescriptor, (JetModifierListOwner) classElement)); } if (hasAbstractModifier && inTrait && !isPropertyAccessor) { -// context.getTrace().getErrorHandler().genericWarning(abstractNode, "Abstract modifier is redundant in trait"); - context.getTrace().report(REDUNDANT_ABSTRACT.on(modifierListOwner, abstractNode)); + context.getTrace().report(REDUNDANT_ABSTRACT.on(functionOrPropertyAccessor, abstractNode)); } - if (function.getBodyExpression() != null && hasAbstractModifier) { -// context.getTrace().getErrorHandler().genericError(abstractNode, "Method " + methodName + "with body cannot be abstract"); - context.getTrace().report(ABSTRACT_FUNCTION_WITH_BODY.on(abstractNode, functionDescriptor)); + if (function.getBodyExpression() != null && hasAbstractModifier) { //TODO + context.getTrace().report(ABSTRACT_FUNCTION_WITH_BODY.on(functionOrPropertyAccessor, abstractNode, functionDescriptor)); } if (function.getBodyExpression() == null && !hasAbstractModifier && !inTrait && nameIdentifier != null && !isPropertyAccessor) { -// context.getTrace().getErrorHandler().genericError(nameIdentifier.getNode(), "Method " + function.getName() + " without body must be abstract"); - context.getTrace().report(NON_ABSTRACT_FUNCTION_WITH_NO_BODY.on(modifierListOwner, nameIdentifier, functionDescriptor)); + context.getTrace().report(NON_ABSTRACT_FUNCTION_WITH_NO_BODY.on(functionOrPropertyAccessor, nameIdentifier, functionDescriptor)); } return; } if (hasAbstractModifier) { if (!isPropertyAccessor) { -// context.getTrace().getErrorHandler().genericError(abstractNode, "Function " + function.getName() + " is not a member and cannot be abstract"); - context.getTrace().report(NON_MEMBER_ABSTRACT_FUNCTION.on(abstractNode, functionDescriptor)); + context.getTrace().report(NON_MEMBER_ABSTRACT_FUNCTION.on(functionOrPropertyAccessor, abstractNode, functionDescriptor)); } else { -// context.getTrace().getErrorHandler().genericError(abstractNode, "Property {0} is not a class or trait member and thus cannot have be abstract accessors"); - context.getTrace().report(NON_MEMBER_ABSTRACT_ACCESSOR.on(abstractNode)); + context.getTrace().report(NON_MEMBER_ABSTRACT_ACCESSOR.on(functionOrPropertyAccessor, abstractNode)); } } if (function.getBodyExpression() == null && !hasAbstractModifier && nameIdentifier != null && !isPropertyAccessor) { -// context.getTrace().getErrorHandler().genericError(nameIdentifier.getNode(), "Function " + function.getName() + " must have a body"); - context.getTrace().report(NON_MEMBER_FUNCTION_NO_BODY.on(nameIdentifier, functionDescriptor)); + context.getTrace().report(NON_MEMBER_FUNCTION_NO_BODY.on(functionOrPropertyAccessor, nameIdentifier, functionDescriptor)); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java index d46c0706303..0626401658c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java @@ -580,7 +580,7 @@ public class ClassDescriptorResolver { if (inType != null) { if (!semanticServices.getTypeChecker().equalTypes(type, inType)) { // trace.getErrorHandler().genericError(typeReference.getNode(), "Setter parameter type must be equal to the type of the property, i.e. " + inType); - trace.report(WRONG_SETTER_PARAMETER_TYPE.on(typeReference, inType)); + trace.report(WRONG_SETTER_PARAMETER_TYPE.on(setter, typeReference, inType)); } } else { @@ -602,7 +602,7 @@ public class ClassDescriptorResolver { 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(setter)); + trace.report(VAL_WITH_SETTER.on(property, setter)); } } return setterDescriptor; @@ -622,7 +622,7 @@ public class ClassDescriptorResolver { returnType = typeResolver.resolveType(scope, returnTypeReference); if (outType != null && !semanticServices.getTypeChecker().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(returnTypeReference, propertyDescriptor.getReturnType())); + trace.report(WRONG_GETTER_RETURN_TYPE.on(getter, returnTypeReference, propertyDescriptor.getReturnType())); } } @@ -693,7 +693,7 @@ public class ClassDescriptorResolver { 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(abstractNode)); + trace.report(ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS.on(parameter, abstractNode)); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index 440a0451e62..8ab82479045 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -217,7 +217,8 @@ public class JetTypeInferrer { return callResolver; } - private void checkNullSafety(@Nullable JetType receiverType, @NotNull ASTNode operationTokenNode, @Nullable FunctionDescriptor callee) { + //TODO JetElement -> JetWhenConditionCall || JetQualifiedExpression + private void checkNullSafety(@Nullable JetType receiverType, @NotNull ASTNode operationTokenNode, @Nullable FunctionDescriptor callee, @NotNull JetElement element) { if (receiverType != null && callee != null) { boolean namespaceType = receiverType instanceof NamespaceType; JetType calleeReceiverType = callee.getReceiverType(); @@ -237,7 +238,7 @@ public class JetTypeInferrer { else { // trace.getErrorHandler().genericWarning(operationTokenNode, "Unnecessary safe call on a non-null receiver of type " + receiverType); - trace.report(UNNECESSARY_SAFE_CALL.on(operationTokenNode, receiverType)); + trace.report(UNNECESSARY_SAFE_CALL.on(element, operationTokenNode, receiverType)); } } @@ -1180,7 +1181,7 @@ public class JetTypeInferrer { if (!typeChecker.isSubtypeOf(targetType, actualType)) { if (typeChecker.isSubtypeOf(actualType, targetType)) { // context.trace.getErrorHandler().genericWarning(expression.getOperationSign().getNode(), "No cast needed, use ':' instead"); - context.trace.report(USELESS_CAST_STATIC_ASSERT_IS_FINE.on(expression.getOperationSign())); + context.trace.report(USELESS_CAST_STATIC_ASSERT_IS_FINE.on(expression, expression.getOperationSign())); } else { // See JET-58 Make 'as never succeeds' a warning, or even never check for Java (external) types @@ -1191,7 +1192,7 @@ public class JetTypeInferrer { else { if (typeChecker.isSubtypeOf(actualType, targetType)) { // context.trace.getErrorHandler().genericWarning(expression.getOperationSign().getNode(), "No cast needed"); - context.trace.report(USELESS_CAST.on(expression.getOperationSign())); + context.trace.report(USELESS_CAST.on(expression, expression.getOperationSign())); } } } @@ -1397,7 +1398,7 @@ public class JetTypeInferrer { // JetType selectorReturnType = getType(compositeScope, callSuffixExpression, false, context); JetType selectorReturnType = getSelectorReturnType(subjectType, callSuffixExpression, context);//getType(compositeScope, callSuffixExpression, false, context); ensureBooleanResultWithCustomSubject(callSuffixExpression, selectorReturnType, "This expression", context); - context.services.checkNullSafety(subjectType, condition.getOperationTokenNode(), getCalleeFunctionDescriptor(callSuffixExpression, context)); + context.services.checkNullSafety(subjectType, condition.getOperationTokenNode(), getCalleeFunctionDescriptor(callSuffixExpression, context), condition); } } @@ -2060,7 +2061,7 @@ public class JetTypeInferrer { if (selectorExpression != null) { receiverType = context.services.enrichOutType(receiverExpression, receiverType, context); - context.services.checkNullSafety(receiverType, expression.getOperationTokenNode(), getCalleeFunctionDescriptor(selectorExpression, context)); + context.services.checkNullSafety(receiverType, expression.getOperationTokenNode(), getCalleeFunctionDescriptor(selectorExpression, context), expression); } } return context.services.checkType(result, expression, contextWithExpectedType); @@ -2362,7 +2363,7 @@ public class JetTypeInferrer { if (leftType != null) { if (!leftType.isNullable()) { // context.trace.getErrorHandler().genericWarning(left.getNode(), "Elvis operator (?:) always returns the left operand of non-nullable type " + leftType); - context.trace.report(USELESS_ELVIS.on(left, leftType)); + context.trace.report(USELESS_ELVIS.on(expression, left, leftType)); } if (rightType != null) { context.services.checkType(TypeUtils.makeNullableAsSpecified(leftType, rightType.isNullable()), left, contextWithExpectedType); diff --git a/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java b/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java index 29f8a1abe65..8350ecd9543 100644 --- a/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java +++ b/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java @@ -90,13 +90,15 @@ public class JetPsiChecker implements Annotator { DiagnosticWithPsiElement diagnosticWithPsiElement = (DiagnosticWithPsiElement) diagnostic; if (diagnostic.getFactory() instanceof PsiElementOnlyDiagnosticFactory) { PsiElementOnlyDiagnosticFactory factory = (PsiElementOnlyDiagnosticFactory) diagnostic.getFactory(); - IntentionActionFactory intentionActionFactory = QuickFixes.get(factory); - IntentionAction action = null; - if (intentionActionFactory != null) { - action = intentionActionFactory.createAction(diagnosticWithPsiElement); - } - if (action != null) { - annotation.registerFix(action); + Set intentionActionFactories = QuickFixes.get(factory); + for (IntentionActionFactory intentionActionFactory : intentionActionFactories) { + IntentionAction action = null; + if (intentionActionFactory != null) { + action = intentionActionFactory.createAction(diagnosticWithPsiElement); + } + if (action != null) { + annotation.registerFix(action); + } } } } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionBodyFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionBodyFix.java new file mode 100644 index 00000000000..f788b7b7698 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/AddFunctionBodyFix.java @@ -0,0 +1,61 @@ +package org.jetbrains.jet.plugin.quickfix; + +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +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.DiagnosticWithPsiElement; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lexer.JetTokens; + +/** + * @author svtk + */ +public class AddFunctionBodyFix extends IntentionActionForPsiElement { + public AddFunctionBodyFix(@NotNull JetFunctionOrPropertyAccessor element) { + super(element); + } + + @NotNull + @Override + public String getText() { + return "Add function body"; + } + + @NotNull + @Override + public String getFamilyName() { + return "Add function body"; + } + + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { + return super.isAvailable(project, editor, file) && + element.getBodyExpression() == null; + } + + @Override + public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + JetFunctionOrPropertyAccessor newElement = (JetFunctionOrPropertyAccessor) element.copy(); + JetExpression bodyExpression = newElement.getBodyExpression(); + if (!(newElement.getLastChild() instanceof PsiWhiteSpace)) { + newElement.add(JetPsiFactory.createWhiteSpace(project)); + } + if (bodyExpression == null) { + newElement.add(JetPsiFactory.createEmptyBody(project)); + } + element.replace(newElement); + } + + public static IntentionActionFactory createFactory() { + return new IntentionActionFactory() { + @Override + public IntentionActionForPsiElement createAction(DiagnosticWithPsiElement diagnostic) { + assert diagnostic.getPsiElement() instanceof JetFunctionOrPropertyAccessor; + return new AddFunctionBodyFix((JetFunctionOrPropertyAccessor) diagnostic.getPsiElement()); + } + }; + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/AddModifierFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/AddModifierFix.java index 84eca465b39..44ae3e5cae0 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/AddModifierFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/AddModifierFix.java @@ -7,7 +7,9 @@ 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.*; +import org.jetbrains.jet.lang.psi.JetModifierList; +import org.jetbrains.jet.lang.psi.JetModifierListOwner; +import org.jetbrains.jet.lang.psi.JetPsiFactory; import org.jetbrains.jet.lexer.JetKeywordToken; import org.jetbrains.jet.lexer.JetToken; import org.jetbrains.jet.lexer.JetTokens; @@ -17,27 +19,41 @@ import org.jetbrains.jet.lexer.JetTokens; */ public class AddModifierFix extends ModifierFix { private final JetToken[] modifiersThanCanBeReplaced; + private final JetToken[] conflictedModifiers; - private AddModifierFix(@NotNull JetModifierListOwner element, JetKeywordToken modifier, JetToken[] modifiersThanCanBeReplaced) { + private AddModifierFix(@NotNull JetModifierListOwner element, JetKeywordToken modifier, JetToken[] modifiersThanCanBeReplaced, JetToken[] conflictedModifiers) { super(element, modifier); this.modifiersThanCanBeReplaced = modifiersThanCanBeReplaced; + this.conflictedModifiers = conflictedModifiers; } - + + private static boolean checkConflictModifiers(JetModifierListOwner element, JetToken[] conflictedModifiers) { + for (JetToken conflictedModifier : conflictedModifiers) { + if (element.hasModifier(conflictedModifier)) { + return true; + } + } + return false; + } + @NotNull @Override public String getText() { - return "add." + modifier.getValue() + ".modifier.fix"; + if (modifier == JetTokens.ABSTRACT_KEYWORD) { + return "Make " + getElementName() + " " + modifier.getValue(); + } + return "Add '" + modifier.getValue() + "' modifier"; } @NotNull @Override public String getFamilyName() { - return "add." + modifier.getValue() + ".modifier.family"; + return "Add modifier"; } @Override public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return super.isAvailable(project, editor, file) && !element.hasModifier(JetTokens.FINAL_KEYWORD); + return element.isValid() && !checkConflictModifiers(element, conflictedModifiers); } @Override @@ -81,17 +97,17 @@ public class AddModifierFix extends ModifierFix { return true; } - public static IntentionActionFactory createFactory(final JetKeywordToken modifier, final JetToken[] modifiersThatCanBeReplaced) { + public static IntentionActionFactory createFactory(final JetKeywordToken modifier, final JetToken[] modifiersThatCanBeReplaced, final JetToken[] conflictedModifiers) { return new IntentionActionFactory() { @Override public IntentionActionForPsiElement createAction(DiagnosticWithPsiElement diagnostic) { assert diagnostic.getPsiElement() instanceof JetModifierListOwner; - return new AddModifierFix((JetModifierListOwner) diagnostic.getPsiElement(), modifier, modifiersThatCanBeReplaced); + return new AddModifierFix((JetModifierListOwner) diagnostic.getPsiElement(), modifier, modifiersThatCanBeReplaced, conflictedModifiers); } }; } public static IntentionActionFactory createFactory(final JetKeywordToken modifier) { - return createFactory(modifier, new JetToken[] {}); + return createFactory(modifier, new JetToken[0], new JetToken[0]); } } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeAccessorTypeFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeAccessorTypeFix.java new file mode 100644 index 00000000000..20a89e360ac --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeAccessorTypeFix.java @@ -0,0 +1,72 @@ +package org.jetbrains.jet.plugin.quickfix; + +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiFile; +import com.intellij.psi.impl.source.codeStyle.CodeEditUtil; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.diagnostics.DiagnosticWithAdditionalInfo; +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.jet.lang.types.JetType; + +/** + * @author svtk + */ +public class ChangeAccessorTypeFix extends IntentionActionForPsiElement { + private final JetType type; + + public ChangeAccessorTypeFix(@NotNull JetPropertyAccessor element, JetType type) { + super(element); + this.type = type; + } + + @NotNull + @Override + public String getText() { + return (element.isGetter() ? "Change getter " : "Change setter parameter ") + "type to " + type; + } + + @NotNull + @Override + public String getFamilyName() { + return "Change accessor type"; + } + + @Override + public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + JetPropertyAccessor newElement = (JetPropertyAccessor) element.copy(); + JetTypeReference newTypeReference = JetPsiFactory.createType(project, type.toString()); + + if (element.isGetter()) { + JetTypeReference returnTypeReference = newElement.getReturnTypeReference(); + assert returnTypeReference != null; + CodeEditUtil.replaceChild(newElement.getNode(), returnTypeReference.getNode(), newTypeReference.getNode()); + element.replace(newElement); + } + else { + JetParameter parameter = newElement.getParameter(); + assert parameter != null; + JetTypeReference typeReference = parameter.getTypeReference(); + assert typeReference != null; + CodeEditUtil.replaceChild(parameter.getNode(), typeReference.getNode(), newTypeReference.getNode()); + element.replace(newElement); + } + } + + public static IntentionActionFactory createFactory() { + return new IntentionActionFactory() { + @Override + public IntentionActionForPsiElement createAction(DiagnosticWithPsiElement diagnostic) { + assert diagnostic instanceof DiagnosticWithAdditionalInfo; + assert diagnostic.getPsiElement() instanceof JetPropertyAccessor; + assert ((DiagnosticWithAdditionalInfo) diagnostic).getInfo() instanceof JetType; + return new ChangeAccessorTypeFix((JetPropertyAccessor) diagnostic.getPsiElement(), (JetType) ((DiagnosticWithAdditionalInfo) diagnostic).getInfo()); + } + }; + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeVariableMutabilityFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeVariableMutabilityFix.java new file mode 100644 index 00000000000..cd3deb20e2a --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeVariableMutabilityFix.java @@ -0,0 +1,64 @@ +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.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; +import org.jetbrains.jet.lang.psi.JetProperty; +import org.jetbrains.jet.lang.psi.JetPsiFactory; +import org.jetbrains.jet.lexer.JetTokens; + +/** + * @author svtk + */ +public class ChangeVariableMutabilityFix extends IntentionActionForPsiElement { + public ChangeVariableMutabilityFix(@NotNull JetProperty element) { + super(element); + } + + @NotNull + @Override + public String getText() { + return "Make variable " + (element.isVar() ? "immutable" : "mutable"); + } + + @NotNull + @Override + public String getFamilyName() { + return "Change variable mutability"; + } + + @Override + public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + JetProperty newElement = (JetProperty) element.copy(); + if (newElement.isVar()) { + PsiElement varElement = newElement.getNode().findChildByType(JetTokens.VAR_KEYWORD).getPsi(); + + JetProperty valProperty = JetPsiFactory.createProperty(project, "x", "Any", false); + PsiElement valElement = valProperty.getNode().findChildByType(JetTokens.VAL_KEYWORD).getPsi(); + CodeEditUtil.replaceChild(newElement.getNode(), varElement.getNode(), valElement.getNode()); + } + else { + PsiElement valElement = newElement.getNode().findChildByType(JetTokens.VAL_KEYWORD).getPsi(); + + JetProperty varProperty = JetPsiFactory.createProperty(project, "x", "Any", true); + PsiElement varElement = varProperty.getNode().findChildByType(JetTokens.VAR_KEYWORD).getPsi(); + CodeEditUtil.replaceChild(newElement.getNode(), valElement.getNode(), varElement.getNode()); + } + element.replace(newElement); + } + + public static IntentionActionFactory createFactory() { + return new IntentionActionFactory() { + @Override + public IntentionActionForPsiElement createAction(DiagnosticWithPsiElement diagnostic) { + assert diagnostic.getPsiElement() instanceof JetProperty; + return new ChangeVariableMutabilityFix((JetProperty) diagnostic.getPsiElement()); + } + }; + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/IntentionActionFactory.java b/idea/src/org/jetbrains/jet/plugin/quickfix/IntentionActionFactory.java index aa50303a0c2..482449b559c 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/IntentionActionFactory.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/IntentionActionFactory.java @@ -8,6 +8,6 @@ import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; */ public interface IntentionActionFactory { - IntentionActionForPsiElement createAction(DiagnosticWithPsiElement diagnostic); + IntentionActionForPsiElement createAction(DiagnosticWithPsiElement diagnostic); } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/IntentionActionForPsiElement.java b/idea/src/org/jetbrains/jet/plugin/quickfix/IntentionActionForPsiElement.java index d7c9649333d..899b9105769 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/IntentionActionForPsiElement.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/IntentionActionForPsiElement.java @@ -1,7 +1,10 @@ package org.jetbrains.jet.plugin.quickfix; import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; /** @@ -13,4 +16,14 @@ public abstract class IntentionActionForPsiElement impleme public IntentionActionForPsiElement(@NotNull T element) { this.element = element; } + + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { + return element.isValid(); + } + + @Override + public boolean startInWriteAction() { + return true; + } } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ModifierFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ModifierFix.java index d6754a2d798..e3db2b5b660 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ModifierFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ModifierFix.java @@ -1,8 +1,7 @@ package org.jetbrains.jet.plugin.quickfix; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiNameIdentifierOwner; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.psi.JetModifierListOwner; import org.jetbrains.jet.lexer.JetKeywordToken; @@ -18,14 +17,14 @@ public abstract class ModifierFix extends IntentionActionForPsiElement IntentionActionFactory createFactoryRedirectingAdditionalInfoToAnotherFactory(final IntentionActionFactory factory) { + return new IntentionActionFactory() { + @Override + public IntentionActionForPsiElement createAction(DiagnosticWithPsiElement diagnostic) { + //no type check; should be followed manually + assert diagnostic instanceof DiagnosticWithAdditionalInfo; + Object info = ((DiagnosticWithAdditionalInfo) diagnostic).getInfo(); + T element = null; + try { + element = (T) info; + } + catch (ClassCastException ex) { + assert false : ex; + } + return factory.createAction(new DiagnosticWithPsiElementImpl(diagnostic.getFactory(), diagnostic.getSeverity(), diagnostic.getMessage(), element)); + } + }; + } + +} diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java index 120dce52ecb..4d5dfa51b46 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java @@ -1,39 +1,88 @@ package org.jetbrains.jet.plugin.quickfix; -import com.google.common.collect.Maps; +import com.google.common.collect.HashMultimap; import com.intellij.psi.PsiElement; import org.jetbrains.jet.lang.diagnostics.Errors; import org.jetbrains.jet.lang.diagnostics.PsiElementOnlyDiagnosticFactory; +import org.jetbrains.jet.lang.psi.JetFunctionOrPropertyAccessor; import org.jetbrains.jet.lang.psi.JetModifierListOwner; +import org.jetbrains.jet.lang.psi.JetProperty; +import org.jetbrains.jet.lang.psi.JetPropertyAccessor; import org.jetbrains.jet.lexer.JetToken; import org.jetbrains.jet.lexer.JetTokens; -import java.util.Map; +import java.util.Set; /** * @author svtk */ public class QuickFixes { - private static Map actionMap = Maps.newHashMap(); + private static HashMultimap actionMap = HashMultimap.create(); - public static IntentionActionFactory get(PsiElementOnlyDiagnosticFactory diagnosticFactory) { + public static Set get(PsiElementOnlyDiagnosticFactory diagnosticFactory) { return actionMap.get(diagnosticFactory); } private QuickFixes() {} - private static void add(PsiElementOnlyDiagnosticFactory diagnosticFactory, IntentionActionFactory actionFactory) { + private static void add(PsiElementOnlyDiagnosticFactory diagnosticFactory, IntentionActionFactory actionFactory) { actionMap.put(diagnosticFactory, actionFactory); } - static { IntentionActionFactory removeAbstractModifierFactory = RemoveModifierFix.createFactory(JetTokens.ABSTRACT_KEYWORD); - IntentionActionFactory addAbstractModifierFactory = AddModifierFix.createFactory(JetTokens.ABSTRACT_KEYWORD, new JetToken[]{JetTokens.OPEN_KEYWORD}); + IntentionActionFactory addAbstractModifierFactory = AddModifierFix.createFactory(JetTokens.ABSTRACT_KEYWORD, new JetToken[]{JetTokens.OPEN_KEYWORD}, new JetToken[] {JetTokens.FINAL_KEYWORD}); + add(Errors.ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS, removeAbstractModifierFactory); + add(Errors.ABSTRACT_PROPERTY_NOT_IN_CLASS, removeAbstractModifierFactory); + + IntentionActionFactory removePartsFromPropertyFactory = RemovePartsFromPropertyFix.createFactory(); + add(Errors.ABSTRACT_PROPERTY_WITH_INITIALIZER, removeAbstractModifierFactory); + add(Errors.ABSTRACT_PROPERTY_WITH_INITIALIZER, removePartsFromPropertyFactory); + + add(Errors.ABSTRACT_PROPERTY_WITH_GETTER, removeAbstractModifierFactory); + add(Errors.ABSTRACT_PROPERTY_WITH_GETTER, removePartsFromPropertyFactory); + + add(Errors.ABSTRACT_PROPERTY_WITH_SETTER, removeAbstractModifierFactory); + add(Errors.ABSTRACT_PROPERTY_WITH_SETTER, removePartsFromPropertyFactory); + + add(Errors.MUST_BE_INITIALIZED_OR_BE_ABSTRACT, addAbstractModifierFactory); add(Errors.REDUNDANT_ABSTRACT, removeAbstractModifierFactory); + + IntentionActionFactory addAbstractToClassFactory = QuickFixUtil.createFactoryRedirectingAdditionalInfoToAnotherFactory(addAbstractModifierFactory); add(Errors.ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS, removeAbstractModifierFactory); + add(Errors.ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS, addAbstractToClassFactory); + + IntentionActionFactory removeFunctionBodyFactory = RemoveFunctionBodyFix.createFactory(); + add(Errors.ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS, removeAbstractModifierFactory); + add(Errors.ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS, addAbstractToClassFactory); + + add(Errors.ABSTRACT_FUNCTION_WITH_BODY, removeAbstractModifierFactory); + add(Errors.ABSTRACT_FUNCTION_WITH_BODY, removeFunctionBodyFactory); + + IntentionActionFactory addFunctionBodyFactory = AddFunctionBodyFix.createFactory(); add(Errors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY, addAbstractModifierFactory); + add(Errors.NON_ABSTRACT_FUNCTION_WITH_NO_BODY, addFunctionBodyFactory); + + add(Errors.NON_MEMBER_ABSTRACT_FUNCTION, removeAbstractModifierFactory); + add(Errors.NON_MEMBER_ABSTRACT_ACCESSOR, removeAbstractModifierFactory); + add(Errors.NON_MEMBER_FUNCTION_NO_BODY, addFunctionBodyFactory); + + add(Errors.NOTHING_TO_OVERRIDE, RemoveModifierFix.createFactory(JetTokens.OVERRIDE_KEYWORD)); + add(Errors.VIRTUAL_METHOD_HIDDEN, AddModifierFix.createFactory(JetTokens.OVERRIDE_KEYWORD)); + + add(Errors.VAL_WITH_SETTER, ChangeVariableMutabilityFix.createFactory()); + + add(Errors.USELESS_CAST_STATIC_ASSERT_IS_FINE, ReplaceOperationInBinaryExpressionFix.createChangeCastToStaticAssertFactory()); + add(Errors.USELESS_CAST, RemoveRightPartOfBinaryExpressionFix.createRemoveCastFactory()); + + IntentionActionFactory changeAccessorTypeFactory = ChangeAccessorTypeFix.createFactory(); + add(Errors.WRONG_SETTER_PARAMETER_TYPE, changeAccessorTypeFactory); + add(Errors.WRONG_GETTER_RETURN_TYPE, changeAccessorTypeFactory); + + add(Errors.USELESS_ELVIS, RemoveRightPartOfBinaryExpressionFix.createRemoveElvisOperatorFactory()); + + add(Errors.UNNECESSARY_SAFE_CALL, ReplaceSafeCallToDotCall.createFactory()); } } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveFunctionBodyFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveFunctionBodyFix.java new file mode 100644 index 00000000000..b58fadef529 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveFunctionBodyFix.java @@ -0,0 +1,64 @@ +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.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lexer.JetTokens; + +/** + * @author svtk + */ +public class RemoveFunctionBodyFix extends IntentionActionForPsiElement { + + public RemoveFunctionBodyFix(@NotNull JetFunctionOrPropertyAccessor element) { + super(element); + } + + @NotNull + @Override + public String getText() { + return "Remove function body"; + } + + @NotNull + @Override + public String getFamilyName() { + return "Remove function body"; + } + + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { + return super.isAvailable(project, editor, file) && + element.getBodyExpression() != null; + } + + @Override + public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + JetFunctionOrPropertyAccessor newElement = (JetFunctionOrPropertyAccessor) element.copy(); + JetExpression bodyExpression = newElement.getBodyExpression(); + if (bodyExpression != null) { + PsiElement prevSibling = bodyExpression.getPrevSibling(); + if (prevSibling instanceof PsiWhiteSpace) { + ((JetElement)newElement).deleteChildInternal(prevSibling.getNode()); + } + ((JetElement)newElement).deleteChildInternal(bodyExpression.getNode()); + } + element.replace(newElement); + } + + public static IntentionActionFactory createFactory() { + return new IntentionActionFactory() { + @Override + public IntentionActionForPsiElement createAction(DiagnosticWithPsiElement diagnostic) { + assert diagnostic.getPsiElement() instanceof JetFunctionOrPropertyAccessor; + return new RemoveFunctionBodyFix((JetFunctionOrPropertyAccessor) diagnostic.getPsiElement()); + } + }; + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveModifierFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveModifierFix.java index 7de342f5cb0..c1e9edfb1e5 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveModifierFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveModifierFix.java @@ -5,13 +5,16 @@ 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.DiagnosticWithPsiElement; import org.jetbrains.jet.lang.psi.JetElement; +import org.jetbrains.jet.lang.psi.JetModifierList; import org.jetbrains.jet.lang.psi.JetModifierListOwner; import org.jetbrains.jet.lexer.JetKeywordToken; import org.jetbrains.jet.lexer.JetToken; +import org.jetbrains.jet.lexer.JetTokens; /** * @author svtk @@ -25,13 +28,21 @@ public class RemoveModifierFix extends ModifierFix { @NotNull @Override public String getText() { - return "remove." + modifier.getValue() + ".modifier.fix"; + if (modifier == JetTokens.ABSTRACT_KEYWORD) { + return "Make " + getElementName() + " not " + modifier.getValue(); + } + return "Remove '" + modifier.getValue() + "' modifier"; } @NotNull @Override public String getFamilyName() { - return "remove." + modifier.getValue() + "abstract.modifier.family"; + return "Remove modifier"; + } + + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { + return element.isValid(); } @Override @@ -40,14 +51,29 @@ public class RemoveModifierFix extends ModifierFix { } @NotNull - private static JetModifierListOwner removeModifier(PsiElement element, JetToken modifier) { - JetModifierListOwner newElement = (JetModifierListOwner) (element.copy()); + /*package*/ static T removeModifier(T element, JetToken modifier) { + T newElement = (T) (element.copy()); assert newElement.hasModifier(modifier); - ASTNode modifierNode = newElement.getModifierList().getModifierNode(modifier); + JetModifierList modifierList = newElement.getModifierList(); + ASTNode modifierNode = modifierList.getModifierNode(modifier); + PsiElement whiteSpace = modifierNode.getPsi().getNextSibling(); ((JetElement)newElement).deleteChildInternal(modifierNode); + if (modifierList.getChildren().length == 0) { + whiteSpace = modifierList.getNextSibling(); + ((JetElement) newElement).deleteChildInternal(modifierList.getNode()); + removeWhiteSpace(newElement, whiteSpace); + } + else { + removeWhiteSpace(newElement, whiteSpace); + } return newElement; } + private static void removeWhiteSpace(PsiElement element, PsiElement subElement) { + if (subElement instanceof PsiWhiteSpace) { + ((JetElement) element).deleteChildInternal(subElement.getNode()); + } + } public static IntentionActionFactory createFactory(final JetKeywordToken modifier) { return new IntentionActionFactory() { diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/RemovePartsFromPropertyFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/RemovePartsFromPropertyFix.java new file mode 100644 index 00000000000..b6878c0685e --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/RemovePartsFromPropertyFix.java @@ -0,0 +1,121 @@ +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.DiagnosticWithAdditionalInfo; +import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.types.JetType; + +/** + * @author svtk + */ +public class RemovePartsFromPropertyFix extends IntentionActionForPsiElement { + private final JetType type; + private final String partsToRemove; + + private RemovePartsFromPropertyFix(@NotNull JetProperty element, JetType type) { + super(element); + this.type = type; + partsToRemove = partsToRemove(element.getGetter() != null && element.getGetter().getBodyExpression() != null, + element.getSetter() != null && element.getSetter().getBodyExpression() != null, + element.getInitializer() != null); + } + + private static String partsToRemove(boolean hasGetter, boolean hasSetter, boolean hasInitializer) { + StringBuilder sb = new StringBuilder(); + if (hasGetter) { + sb.append("getter"); + if (hasSetter && hasInitializer) { + sb.append(", "); + } + else if (hasSetter || hasInitializer) { + sb.append(" and "); + } + } + if (hasSetter) { + sb.append("setter"); + if (hasInitializer) { + sb.append(" and "); + } + } + if (hasInitializer) { + sb.append("initializer"); + } + return sb.toString(); + } + + @NotNull + @Override + public String getText() { + return "Remove " + partsToRemove + " from property"; + } + + @NotNull + @Override + public String getFamilyName() { + return "Remove parts from property to make it abstract"; + } + + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { + return element.isValid(); + } + + @Override + public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + JetProperty newElement = (JetProperty) element.copy(); + JetPropertyAccessor getter = newElement.getGetter(); + if (getter != null) { + newElement.deleteChildInternal(getter.getNode()); + } + JetPropertyAccessor setter = newElement.getSetter(); + if (setter != null) { + newElement.deleteChildInternal(setter.getNode()); + } + JetExpression initializer = newElement.getInitializer(); + if (initializer != null) { + PsiElement nameIdentifier = newElement.getNameIdentifier(); + assert nameIdentifier != null; + PsiElement nextSibling = nameIdentifier.getNextSibling(); + assert nextSibling != null; + newElement.deleteChildRange(nextSibling, initializer); + + if (newElement.getPropertyTypeRef() == null) { + newElement = addPropertyType(project, newElement, type); + } + } + element.replace(newElement); + } + + public static JetProperty addPropertyType(Project project, JetProperty property, JetType type) { + JetProperty newProperty = (JetProperty) property.copy(); + JetTypeReference typeReference = JetPsiFactory.createType(project, type.toString()); + PsiElement[] colon = JetPsiFactory.createColon(project); + PsiElement nameIdentifier = newProperty.getNameIdentifier(); + assert nameIdentifier != null; + newProperty.addAfter(typeReference, nameIdentifier); + for (int i = colon.length - 1; i >= 0; i--) { + newProperty.addAfter(colon[i], nameIdentifier); + } + return newProperty; + } + + public static IntentionActionFactory createFactory() { + return new IntentionActionFactory() { + @Override + public IntentionActionForPsiElement createAction(DiagnosticWithPsiElement diagnostic) { + assert diagnostic.getPsiElement() instanceof JetProperty; + assert diagnostic instanceof DiagnosticWithAdditionalInfo; + + Object info = ((DiagnosticWithAdditionalInfo) diagnostic).getInfo(); + assert info instanceof JetType; + return new RemovePartsFromPropertyFix((JetProperty) diagnostic.getPsiElement(), (JetType) info); + } + }; + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveRightPartOfBinaryExpressionFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveRightPartOfBinaryExpressionFix.java new file mode 100644 index 00000000000..8be4f3a848b --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/RemoveRightPartOfBinaryExpressionFix.java @@ -0,0 +1,71 @@ +package org.jetbrains.jet.plugin.quickfix; + +import com.intellij.openapi.editor.Editor; +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.psi.JetBinaryExpression; +import org.jetbrains.jet.lang.psi.JetBinaryExpressionWithTypeRHS; +import org.jetbrains.jet.lang.psi.JetExpression; + +/** + * @author svtk + */ +public abstract class RemoveRightPartOfBinaryExpressionFix extends IntentionActionForPsiElement { + public RemoveRightPartOfBinaryExpressionFix(@NotNull T element) { + super(element); + } + + @NotNull + @Override + public String getFamilyName() { + return "Remove right part of a binary expression"; + } + + @Override + public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + if (element instanceof JetBinaryExpression) { + JetBinaryExpression newElement = (JetBinaryExpression) element.copy(); + element.replace(newElement.getLeft()); + } + else if (element instanceof JetBinaryExpressionWithTypeRHS) { + JetBinaryExpressionWithTypeRHS newElement = (JetBinaryExpressionWithTypeRHS) element.copy(); + element.replace(newElement.getLeft()); + } + } + + public static IntentionActionFactory createRemoveCastFactory() { + return new IntentionActionFactory() { + @Override + public IntentionActionForPsiElement createAction(DiagnosticWithPsiElement diagnostic) { + assert diagnostic.getPsiElement() instanceof JetBinaryExpressionWithTypeRHS; + return new RemoveRightPartOfBinaryExpressionFix((JetBinaryExpressionWithTypeRHS) diagnostic.getPsiElement()) { + @NotNull + @Override + public String getText() { + return "Remove cast"; + } + }; + } + }; + } + + public static IntentionActionFactory createRemoveElvisOperatorFactory() { + return new IntentionActionFactory() { + @Override + public IntentionActionForPsiElement createAction(DiagnosticWithPsiElement diagnostic) { + assert diagnostic.getPsiElement() instanceof JetBinaryExpression; + return new RemoveRightPartOfBinaryExpressionFix((JetBinaryExpression) diagnostic.getPsiElement()) { + @NotNull + @Override + public String getText() { + return "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 new file mode 100644 index 00000000000..640183a69e6 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ReplaceOperationInBinaryExpressionFix.java @@ -0,0 +1,57 @@ +package org.jetbrains.jet.plugin.quickfix; + +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiFile; +import com.intellij.psi.impl.source.codeStyle.CodeEditUtil; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; +import org.jetbrains.jet.lang.psi.JetBinaryExpressionWithTypeRHS; +import org.jetbrains.jet.lang.psi.JetExpression; +import org.jetbrains.jet.lang.psi.JetPsiFactory; + +/** + * @author svtk + */ +public abstract class ReplaceOperationInBinaryExpressionFix extends IntentionActionForPsiElement { + private final String expressionWithNecessaryOperation; + public ReplaceOperationInBinaryExpressionFix(@NotNull T element, String expressionWithNecessaryOperation) { + super(element); + this.expressionWithNecessaryOperation = expressionWithNecessaryOperation; + } + + @NotNull + @Override + public String getFamilyName() { + return "Replace operation in a binary expression"; + } + + @Override + public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + if (element instanceof JetBinaryExpressionWithTypeRHS) { + JetBinaryExpressionWithTypeRHS expression = (JetBinaryExpressionWithTypeRHS) JetPsiFactory.createExpression(project, expressionWithNecessaryOperation); + + JetBinaryExpressionWithTypeRHS newElement = (JetBinaryExpressionWithTypeRHS) element.copy(); + CodeEditUtil.replaceChild(newElement.getNode(), newElement.getOperationSign().getNode(), expression.getOperationSign().getNode()); + + element.replace(newElement); + } + } + + public static IntentionActionFactory createChangeCastToStaticAssertFactory() { + return new IntentionActionFactory() { + @Override + public IntentionActionForPsiElement createAction(DiagnosticWithPsiElement diagnostic) { + assert diagnostic.getPsiElement() instanceof JetBinaryExpressionWithTypeRHS; + return new ReplaceOperationInBinaryExpressionFix((JetBinaryExpressionWithTypeRHS) diagnostic.getPsiElement(), "2 : Int") { + @NotNull + @Override + public String getText() { + return "Replace a cast with a static assert"; + } + }; + } + }; + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ReplaceSafeCallToDotCall.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ReplaceSafeCallToDotCall.java new file mode 100644 index 00000000000..e7be969f17b --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ReplaceSafeCallToDotCall.java @@ -0,0 +1,62 @@ +package org.jetbrains.jet.plugin.quickfix; + +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiFile; +import com.intellij.psi.impl.source.codeStyle.CodeEditUtil; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; +import org.jetbrains.jet.lang.psi.*; + +/** + * @author svtk + */ +public class ReplaceSafeCallToDotCall extends IntentionActionForPsiElement { + + public ReplaceSafeCallToDotCall(@NotNull JetElement element) { + super(element); + } + + @NotNull + @Override + public String getText() { + return "Replace to dot call"; + } + + @NotNull + @Override + public String getFamilyName() { + return "Replace safe call to dot call"; + } + + @Override + public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + if (element instanceof JetSafeQualifiedExpression) { + JetSafeQualifiedExpression safeQualifiedExpression = (JetSafeQualifiedExpression) element; + JetDotQualifiedExpression newElement = (JetDotQualifiedExpression) JetPsiFactory.createExpression(project, "x.foo"); + + CodeEditUtil.replaceChild(newElement.getNode(), newElement.getSelectorExpression().getNode(), safeQualifiedExpression.getSelectorExpression().getNode()); + CodeEditUtil.replaceChild(newElement.getNode(), newElement.getReceiverExpression().getNode(), safeQualifiedExpression.getReceiverExpression().getNode()); + + element.replace(newElement); + } + else if (element instanceof JetWhenConditionCall) { + JetWhenConditionCall newElement = (JetWhenConditionCall) element; + JetDotQualifiedExpression callExpression = (JetDotQualifiedExpression) JetPsiFactory.createExpression(project, "x.foo"); + CodeEditUtil.replaceChild(newElement.getNode(), newElement.getOperationTokenNode(), callExpression.getOperationTokenNode()); + + element.replace(newElement); + } + } + + public static IntentionActionFactory createFactory() { + return new IntentionActionFactory() { + @Override + public IntentionActionForPsiElement createAction(DiagnosticWithPsiElement diagnostic) { + assert diagnostic.getPsiElement() instanceof JetElement; + return new ReplaceSafeCallToDotCall((JetElement) diagnostic.getPsiElement()); + } + }; + } +} diff --git a/idea/testData/quickfix/abstract/afterAbstractFunctionInNonAbstractClass.kt b/idea/testData/quickfix/abstract/afterAbstractFunctionInNonAbstractClass.kt new file mode 100644 index 00000000000..6ec19a0bac8 --- /dev/null +++ b/idea/testData/quickfix/abstract/afterAbstractFunctionInNonAbstractClass.kt @@ -0,0 +1,4 @@ +// "Make 'foo' not abstract" "true" +class A() { + fun foo() +} \ No newline at end of file diff --git a/idea/testData/quickfix/abstract/afterAbstractFunctionWithBody.kt b/idea/testData/quickfix/abstract/afterAbstractFunctionWithBody.kt new file mode 100644 index 00000000000..f2086d5f409 --- /dev/null +++ b/idea/testData/quickfix/abstract/afterAbstractFunctionWithBody.kt @@ -0,0 +1,4 @@ +// "Remove function body" "true" +abstract class A() { + abstract fun foo() +} diff --git a/idea/testData/quickfix/abstract/afterAbstractPropertyInNonAbstractClass1.kt b/idea/testData/quickfix/abstract/afterAbstractPropertyInNonAbstractClass1.kt new file mode 100644 index 00000000000..945ce429d17 --- /dev/null +++ b/idea/testData/quickfix/abstract/afterAbstractPropertyInNonAbstractClass1.kt @@ -0,0 +1,4 @@ +// "Make 'A' abstract" "true" +abstract class A() { + abstract var i : Int +} diff --git a/idea/testData/quickfix/abstract/afterAbstractPropertyInNonAbstractClass2.kt b/idea/testData/quickfix/abstract/afterAbstractPropertyInNonAbstractClass2.kt new file mode 100644 index 00000000000..6aa96573108 --- /dev/null +++ b/idea/testData/quickfix/abstract/afterAbstractPropertyInNonAbstractClass2.kt @@ -0,0 +1,4 @@ +// "Make 'i' not abstract" "true" +class A() { + var i : Int +} diff --git a/idea/testData/quickfix/abstract/afterAbstractPropertyInPrimaryConstructorParameters.kt b/idea/testData/quickfix/abstract/afterAbstractPropertyInPrimaryConstructorParameters.kt new file mode 100644 index 00000000000..8bb9648d6fa --- /dev/null +++ b/idea/testData/quickfix/abstract/afterAbstractPropertyInPrimaryConstructorParameters.kt @@ -0,0 +1,2 @@ +// "Make 'i' not abstract" "true" +class A(val i: Int) {} \ No newline at end of file diff --git a/idea/testData/quickfix/abstract/afterAbstractPropertyNotInClass.kt b/idea/testData/quickfix/abstract/afterAbstractPropertyNotInClass.kt new file mode 100644 index 00000000000..d4db626ee31 --- /dev/null +++ b/idea/testData/quickfix/abstract/afterAbstractPropertyNotInClass.kt @@ -0,0 +1,2 @@ +// "Make 'i' not abstract" "true" +val i: Int = 1 \ No newline at end of file diff --git a/idea/testData/quickfix/abstract/afterAbstractPropertyWIthInitializer2.kt b/idea/testData/quickfix/abstract/afterAbstractPropertyWIthInitializer2.kt new file mode 100644 index 00000000000..50e6e0f7847 --- /dev/null +++ b/idea/testData/quickfix/abstract/afterAbstractPropertyWIthInitializer2.kt @@ -0,0 +1,4 @@ +// "Remove initializer from property" "true" +abstract class A { + abstract var i : Int +} diff --git a/idea/testData/quickfix/abstract/afterAbstractPropertyWIthInitializer3.kt b/idea/testData/quickfix/abstract/afterAbstractPropertyWIthInitializer3.kt new file mode 100644 index 00000000000..50e6e0f7847 --- /dev/null +++ b/idea/testData/quickfix/abstract/afterAbstractPropertyWIthInitializer3.kt @@ -0,0 +1,4 @@ +// "Remove initializer from property" "true" +abstract class A { + abstract var i : Int +} diff --git a/idea/testData/quickfix/abstract/afterAbstractPropertyWithGetter1.kt b/idea/testData/quickfix/abstract/afterAbstractPropertyWithGetter1.kt new file mode 100644 index 00000000000..ccea9aaf50b --- /dev/null +++ b/idea/testData/quickfix/abstract/afterAbstractPropertyWithGetter1.kt @@ -0,0 +1,5 @@ +// "Make 'i' not abstract" "true" +class B { + val i: Int + get() = $i +} \ No newline at end of file diff --git a/idea/testData/quickfix/abstract/afterAbstractPropertyWithGetter2.kt b/idea/testData/quickfix/abstract/afterAbstractPropertyWithGetter2.kt new file mode 100644 index 00000000000..8e7404cd9e2 --- /dev/null +++ b/idea/testData/quickfix/abstract/afterAbstractPropertyWithGetter2.kt @@ -0,0 +1,5 @@ +// "Remove getter and initializer from property" "true" +abstract class B { + abstract val i : Int + +} \ No newline at end of file diff --git a/idea/testData/quickfix/abstract/afterAbstractPropertyWithInitializer1.kt b/idea/testData/quickfix/abstract/afterAbstractPropertyWithInitializer1.kt new file mode 100644 index 00000000000..01d5197a882 --- /dev/null +++ b/idea/testData/quickfix/abstract/afterAbstractPropertyWithInitializer1.kt @@ -0,0 +1,4 @@ +// "Make 'i' not abstract" "true" +class A { + var i = 0 +} diff --git a/idea/testData/quickfix/abstract/afterAbstractPropertyWithSetter.kt b/idea/testData/quickfix/abstract/afterAbstractPropertyWithSetter.kt new file mode 100644 index 00000000000..ffbac65767b --- /dev/null +++ b/idea/testData/quickfix/abstract/afterAbstractPropertyWithSetter.kt @@ -0,0 +1,5 @@ +// "Make 'j' not abstract" "true" +class B { + var j: Int + set(v: Int) {} +} diff --git a/idea/testData/quickfix/abstract/afterMustBeInitializedOrBeAbstract.kt b/idea/testData/quickfix/abstract/afterMustBeInitializedOrBeAbstract.kt new file mode 100644 index 00000000000..bdefbb28222 --- /dev/null +++ b/idea/testData/quickfix/abstract/afterMustBeInitializedOrBeAbstract.kt @@ -0,0 +1,4 @@ +// "Make 'i' abstract" "true" +abstract class A() { + abstract var i : Int +} diff --git a/idea/testData/quickfix/abstract/afterNonAbstractFunctionWithNoBody.kt b/idea/testData/quickfix/abstract/afterNonAbstractFunctionWithNoBody.kt new file mode 100644 index 00000000000..59958ef927e --- /dev/null +++ b/idea/testData/quickfix/abstract/afterNonAbstractFunctionWithNoBody.kt @@ -0,0 +1,4 @@ +// "Add function body" "true" +class A() { + fun foo() {} +} diff --git a/idea/testData/quickfix/abstract/afterNonMemberAbstractAccessor.kt b/idea/testData/quickfix/abstract/afterNonMemberAbstractAccessor.kt new file mode 100644 index 00000000000..c31be73c7df --- /dev/null +++ b/idea/testData/quickfix/abstract/afterNonMemberAbstractAccessor.kt @@ -0,0 +1,2 @@ +// "Make 'abstract get' not abstract" "true" +val i : Int = 0; get \ No newline at end of file diff --git a/idea/testData/quickfix/abstract/afterNonMemberAbstractFunction.kt b/idea/testData/quickfix/abstract/afterNonMemberAbstractFunction.kt new file mode 100644 index 00000000000..6724f07e1d7 --- /dev/null +++ b/idea/testData/quickfix/abstract/afterNonMemberAbstractFunction.kt @@ -0,0 +1,2 @@ +// "Make 'foo' not abstract" "true" +fun foo() \ No newline at end of file diff --git a/idea/testData/quickfix/abstract/afterNonMemberFunctionNoBody.kt b/idea/testData/quickfix/abstract/afterNonMemberFunctionNoBody.kt new file mode 100644 index 00000000000..2be242ece22 --- /dev/null +++ b/idea/testData/quickfix/abstract/afterNonMemberFunctionNoBody.kt @@ -0,0 +1,4 @@ +// "Add function body" "true" +namespace a { +fun foo() {} +} \ No newline at end of file diff --git a/idea/testData/quickfix/abstract/afterRedundantAbstract.kt b/idea/testData/quickfix/abstract/afterRedundantAbstract.kt new file mode 100644 index 00000000000..a6244c18332 --- /dev/null +++ b/idea/testData/quickfix/abstract/afterRedundantAbstract.kt @@ -0,0 +1,4 @@ +// "Make 'foo' not abstract" "true" +trait A { + fun foo() +} \ No newline at end of file diff --git a/idea/testData/quickfix/abstract/afterReplaceOpen.kt b/idea/testData/quickfix/abstract/afterReplaceOpen.kt new file mode 100644 index 00000000000..d9af1d8ce42 --- /dev/null +++ b/idea/testData/quickfix/abstract/afterReplaceOpen.kt @@ -0,0 +1,4 @@ +// "Make 'foo' abstract" "true" +abstract class B() { + abstract fun foo() +} diff --git a/idea/testData/quickfix/abstract/beforeAbstractFunctionInNonAbstractClass.kt b/idea/testData/quickfix/abstract/beforeAbstractFunctionInNonAbstractClass.kt new file mode 100644 index 00000000000..1e408668e99 --- /dev/null +++ b/idea/testData/quickfix/abstract/beforeAbstractFunctionInNonAbstractClass.kt @@ -0,0 +1,4 @@ +// "Make 'foo' not abstract" "true" +class A() { + abstract fun foo() +} \ No newline at end of file diff --git a/idea/testData/quickfix/abstract/beforeAbstractFunctionWithBody.kt b/idea/testData/quickfix/abstract/beforeAbstractFunctionWithBody.kt new file mode 100644 index 00000000000..0d0d468f1a0 --- /dev/null +++ b/idea/testData/quickfix/abstract/beforeAbstractFunctionWithBody.kt @@ -0,0 +1,4 @@ +// "Remove function body" "true" +abstract class A() { + abstract fun foo() {} +} diff --git a/idea/testData/quickfix/abstract/beforeAbstractPropertyInNonAbstractClass1.kt b/idea/testData/quickfix/abstract/beforeAbstractPropertyInNonAbstractClass1.kt new file mode 100644 index 00000000000..68fa4959c71 --- /dev/null +++ b/idea/testData/quickfix/abstract/beforeAbstractPropertyInNonAbstractClass1.kt @@ -0,0 +1,4 @@ +// "Make 'A' abstract" "true" +class A() { + abstract var i : Int +} diff --git a/idea/testData/quickfix/abstract/beforeAbstractPropertyInNonAbstractClass2.kt b/idea/testData/quickfix/abstract/beforeAbstractPropertyInNonAbstractClass2.kt new file mode 100644 index 00000000000..21218b3a76c --- /dev/null +++ b/idea/testData/quickfix/abstract/beforeAbstractPropertyInNonAbstractClass2.kt @@ -0,0 +1,4 @@ +// "Make 'i' not abstract" "true" +class A() { + abstract var i : Int +} diff --git a/idea/testData/quickfix/abstract/beforeAbstractPropertyInPrimaryConstructorParameters.kt b/idea/testData/quickfix/abstract/beforeAbstractPropertyInPrimaryConstructorParameters.kt new file mode 100644 index 00000000000..cfb081250c7 --- /dev/null +++ b/idea/testData/quickfix/abstract/beforeAbstractPropertyInPrimaryConstructorParameters.kt @@ -0,0 +1,2 @@ +// "Make 'i' not abstract" "true" +class A(abstract val i: Int) {} \ No newline at end of file diff --git a/idea/testData/quickfix/abstract/beforeAbstractPropertyNotInClass.kt b/idea/testData/quickfix/abstract/beforeAbstractPropertyNotInClass.kt new file mode 100644 index 00000000000..0355005d55c --- /dev/null +++ b/idea/testData/quickfix/abstract/beforeAbstractPropertyNotInClass.kt @@ -0,0 +1,2 @@ +// "Make 'i' not abstract" "true" +abstract val i: Int = 1 \ No newline at end of file diff --git a/idea/testData/quickfix/abstract/beforeAbstractPropertyWIthInitializer2.kt b/idea/testData/quickfix/abstract/beforeAbstractPropertyWIthInitializer2.kt new file mode 100644 index 00000000000..bfd6c3ad884 --- /dev/null +++ b/idea/testData/quickfix/abstract/beforeAbstractPropertyWIthInitializer2.kt @@ -0,0 +1,4 @@ +// "Remove initializer from property" "true" +abstract class A { + abstract var i = 0 +} diff --git a/idea/testData/quickfix/abstract/beforeAbstractPropertyWIthInitializer3.kt b/idea/testData/quickfix/abstract/beforeAbstractPropertyWIthInitializer3.kt new file mode 100644 index 00000000000..1cfb78a0ed2 --- /dev/null +++ b/idea/testData/quickfix/abstract/beforeAbstractPropertyWIthInitializer3.kt @@ -0,0 +1,4 @@ +// "Remove initializer from property" "true" +abstract class A { + abstract var i : Int = 0 +} diff --git a/idea/testData/quickfix/abstract/beforeAbstractPropertyWithGetter1.kt b/idea/testData/quickfix/abstract/beforeAbstractPropertyWithGetter1.kt new file mode 100644 index 00000000000..1270309c17a --- /dev/null +++ b/idea/testData/quickfix/abstract/beforeAbstractPropertyWithGetter1.kt @@ -0,0 +1,5 @@ +// "Make 'i' not abstract" "true" +class B { + abstract val i: Int + get() = $i +} \ No newline at end of file diff --git a/idea/testData/quickfix/abstract/beforeAbstractPropertyWithGetter2.kt b/idea/testData/quickfix/abstract/beforeAbstractPropertyWithGetter2.kt new file mode 100644 index 00000000000..4466a5712a5 --- /dev/null +++ b/idea/testData/quickfix/abstract/beforeAbstractPropertyWithGetter2.kt @@ -0,0 +1,5 @@ +// "Remove getter and initializer from property" "true" +abstract class B { + abstract val i = 0 + get() = $i +} \ No newline at end of file diff --git a/idea/testData/quickfix/abstract/beforeAbstractPropertyWithInitializer1.kt b/idea/testData/quickfix/abstract/beforeAbstractPropertyWithInitializer1.kt new file mode 100644 index 00000000000..c56a70cde06 --- /dev/null +++ b/idea/testData/quickfix/abstract/beforeAbstractPropertyWithInitializer1.kt @@ -0,0 +1,4 @@ +// "Make 'i' not abstract" "true" +class A { + abstract var i = 0 +} diff --git a/idea/testData/quickfix/abstract/beforeAbstractPropertyWithSetter.kt b/idea/testData/quickfix/abstract/beforeAbstractPropertyWithSetter.kt new file mode 100644 index 00000000000..eb13af31fce --- /dev/null +++ b/idea/testData/quickfix/abstract/beforeAbstractPropertyWithSetter.kt @@ -0,0 +1,5 @@ +// "Make 'j' not abstract" "true" +class B { + abstract var j: Int + set(v: Int) {} +} diff --git a/idea/testData/quickfix/abstract/beforeHasFinal.kt b/idea/testData/quickfix/abstract/beforeHasFinal.kt new file mode 100644 index 00000000000..6140b0d1c56 --- /dev/null +++ b/idea/testData/quickfix/abstract/beforeHasFinal.kt @@ -0,0 +1,4 @@ +// "Make 'foo' abstract" "false" +class B() { + final fun foo() +} diff --git a/idea/testData/quickfix/abstract/beforeMustBeInitializedOrBeAbstract.kt b/idea/testData/quickfix/abstract/beforeMustBeInitializedOrBeAbstract.kt new file mode 100644 index 00000000000..57e7f65c5f0 --- /dev/null +++ b/idea/testData/quickfix/abstract/beforeMustBeInitializedOrBeAbstract.kt @@ -0,0 +1,4 @@ +// "Make 'i' abstract" "true" +abstract class A() { + var i : Int +} diff --git a/idea/testData/quickfix/abstract/beforeNonAbstractFunctionWithNoBody.kt b/idea/testData/quickfix/abstract/beforeNonAbstractFunctionWithNoBody.kt new file mode 100644 index 00000000000..0e070005a49 --- /dev/null +++ b/idea/testData/quickfix/abstract/beforeNonAbstractFunctionWithNoBody.kt @@ -0,0 +1,4 @@ +// "Add function body" "true" +class A() { + fun foo() +} diff --git a/idea/testData/quickfix/abstract/beforeNonMemberAbstractAccessor.kt b/idea/testData/quickfix/abstract/beforeNonMemberAbstractAccessor.kt new file mode 100644 index 00000000000..872f637f879 --- /dev/null +++ b/idea/testData/quickfix/abstract/beforeNonMemberAbstractAccessor.kt @@ -0,0 +1,2 @@ +// "Make 'abstract get' not abstract" "true" +val i : Int = 0; abstract get \ No newline at end of file diff --git a/idea/testData/quickfix/abstract/beforeNonMemberAbstractFunction.kt b/idea/testData/quickfix/abstract/beforeNonMemberAbstractFunction.kt new file mode 100644 index 00000000000..f696d0ea6dd --- /dev/null +++ b/idea/testData/quickfix/abstract/beforeNonMemberAbstractFunction.kt @@ -0,0 +1,2 @@ +// "Make 'foo' not abstract" "true" +abstract fun foo() \ No newline at end of file diff --git a/idea/testData/quickfix/abstract/beforeNonMemberFunctionNoBody.kt b/idea/testData/quickfix/abstract/beforeNonMemberFunctionNoBody.kt new file mode 100644 index 00000000000..01680ddc843 --- /dev/null +++ b/idea/testData/quickfix/abstract/beforeNonMemberFunctionNoBody.kt @@ -0,0 +1,4 @@ +// "Add function body" "true" +namespace a { +fun foo() +} \ No newline at end of file diff --git a/idea/testData/quickfix/abstract/beforeRedundantAbstract.kt b/idea/testData/quickfix/abstract/beforeRedundantAbstract.kt new file mode 100644 index 00000000000..81599e7cefa --- /dev/null +++ b/idea/testData/quickfix/abstract/beforeRedundantAbstract.kt @@ -0,0 +1,4 @@ +// "Make 'foo' not abstract" "true" +trait A { + abstract fun foo() +} \ No newline at end of file diff --git a/idea/testData/quickfix/abstract/beforeReplaceOpen.kt b/idea/testData/quickfix/abstract/beforeReplaceOpen.kt new file mode 100644 index 00000000000..0eac584df28 --- /dev/null +++ b/idea/testData/quickfix/abstract/beforeReplaceOpen.kt @@ -0,0 +1,4 @@ +// "Make 'foo' abstract" "true" +abstract class B() { + open fun foo() +} diff --git a/idea/testData/quickfix/changeVariableMutability/afterValWithSetter.kt b/idea/testData/quickfix/changeVariableMutability/afterValWithSetter.kt new file mode 100644 index 00000000000..86d2423c318 --- /dev/null +++ b/idea/testData/quickfix/changeVariableMutability/afterValWithSetter.kt @@ -0,0 +1,5 @@ +// "Make variable mutable" "true" +class A() { + var a: Int = 0 + set(v: Int) {} +} diff --git a/idea/testData/quickfix/changeVariableMutability/beforeValWithSetter.kt b/idea/testData/quickfix/changeVariableMutability/beforeValWithSetter.kt new file mode 100644 index 00000000000..8cd3efeb193 --- /dev/null +++ b/idea/testData/quickfix/changeVariableMutability/beforeValWithSetter.kt @@ -0,0 +1,5 @@ +// "Make variable mutable" "true" +class A() { + val a: Int = 0 + set(v: Int) {} +} diff --git a/idea/testData/quickfix/expressions/afterUnnecessarySafeCall1.kt b/idea/testData/quickfix/expressions/afterUnnecessarySafeCall1.kt new file mode 100644 index 00000000000..7422cfd3f6b --- /dev/null +++ b/idea/testData/quickfix/expressions/afterUnnecessarySafeCall1.kt @@ -0,0 +1,4 @@ +// "Replace to dot call" "true" +fun foo(a: Any) { + a.equals(0) +} diff --git a/idea/testData/quickfix/expressions/afterUnnecessarySafeCall2.kt b/idea/testData/quickfix/expressions/afterUnnecessarySafeCall2.kt new file mode 100644 index 00000000000..f5efe05b2ea --- /dev/null +++ b/idea/testData/quickfix/expressions/afterUnnecessarySafeCall2.kt @@ -0,0 +1,7 @@ +// "Replace to dot call" "true" +fun foo(a: Any) { + when (a) { + .equals(0) => true + else => false + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/expressions/afterUselessCast.kt b/idea/testData/quickfix/expressions/afterUselessCast.kt new file mode 100644 index 00000000000..792e9c049bb --- /dev/null +++ b/idea/testData/quickfix/expressions/afterUselessCast.kt @@ -0,0 +1,4 @@ +// "Replace a cast with a static assert" "true" +fun foo(a: String) { + val b = a : Any +} diff --git a/idea/testData/quickfix/expressions/afterUselessCastStaticAssertIsFine.kt b/idea/testData/quickfix/expressions/afterUselessCastStaticAssertIsFine.kt new file mode 100644 index 00000000000..ff2e05cc364 --- /dev/null +++ b/idea/testData/quickfix/expressions/afterUselessCastStaticAssertIsFine.kt @@ -0,0 +1,4 @@ +// "Remove cast" "true" +fun foo(a: Any) { + val b = a +} diff --git a/idea/testData/quickfix/expressions/afterUselessElvis.kt b/idea/testData/quickfix/expressions/afterUselessElvis.kt new file mode 100644 index 00000000000..e76b3b56841 --- /dev/null +++ b/idea/testData/quickfix/expressions/afterUselessElvis.kt @@ -0,0 +1,4 @@ +// "Remove elvis operator" "true" +fun foo(a: String) { + val b : String = a +} diff --git a/idea/testData/quickfix/expressions/beforeUnnecessarySafeCall1.kt b/idea/testData/quickfix/expressions/beforeUnnecessarySafeCall1.kt new file mode 100644 index 00000000000..61063ff4cc4 --- /dev/null +++ b/idea/testData/quickfix/expressions/beforeUnnecessarySafeCall1.kt @@ -0,0 +1,4 @@ +// "Replace to dot call" "true" +fun foo(a: Any) { + a?.equals(0) +} diff --git a/idea/testData/quickfix/expressions/beforeUnnecessarySafeCall2.kt b/idea/testData/quickfix/expressions/beforeUnnecessarySafeCall2.kt new file mode 100644 index 00000000000..40f33005054 --- /dev/null +++ b/idea/testData/quickfix/expressions/beforeUnnecessarySafeCall2.kt @@ -0,0 +1,7 @@ +// "Replace to dot call" "true" +fun foo(a: Any) { + when (a) { + ?.equals(0) => true + else => false + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/expressions/beforeUselessCast.kt b/idea/testData/quickfix/expressions/beforeUselessCast.kt new file mode 100644 index 00000000000..ab4debc2fe2 --- /dev/null +++ b/idea/testData/quickfix/expressions/beforeUselessCast.kt @@ -0,0 +1,4 @@ +// "Replace a cast with a static assert" "true" +fun foo(a: String) { + val b = a as Any +} diff --git a/idea/testData/quickfix/expressions/beforeUselessCastStaticAssertIsFine.kt b/idea/testData/quickfix/expressions/beforeUselessCastStaticAssertIsFine.kt new file mode 100644 index 00000000000..3d29461c52e --- /dev/null +++ b/idea/testData/quickfix/expressions/beforeUselessCastStaticAssertIsFine.kt @@ -0,0 +1,4 @@ +// "Remove cast" "true" +fun foo(a: Any) { + val b = a as Any +} diff --git a/idea/testData/quickfix/expressions/beforeUselessElvis.kt b/idea/testData/quickfix/expressions/beforeUselessElvis.kt new file mode 100644 index 00000000000..3f046028f6c --- /dev/null +++ b/idea/testData/quickfix/expressions/beforeUselessElvis.kt @@ -0,0 +1,4 @@ +// "Remove elvis operator" "true" +fun foo(a: String) { + val b : String = a ?: "s" +} diff --git a/idea/testData/quickfix/override/afterNothingToOverride.kt b/idea/testData/quickfix/override/afterNothingToOverride.kt new file mode 100644 index 00000000000..54d60343c52 --- /dev/null +++ b/idea/testData/quickfix/override/afterNothingToOverride.kt @@ -0,0 +1,4 @@ +// "Remove 'override' modifier" "true" +class A() { + fun foo() {} +} diff --git a/idea/testData/quickfix/override/afterVirtualMethodHidden.kt b/idea/testData/quickfix/override/afterVirtualMethodHidden.kt new file mode 100644 index 00000000000..9bc0fa63ac2 --- /dev/null +++ b/idea/testData/quickfix/override/afterVirtualMethodHidden.kt @@ -0,0 +1,8 @@ +// "Add 'override' modifier" "true" +open class A() { + fun foo() {} +} + +class B() : A() { + override fun foo() {} +} diff --git a/idea/testData/quickfix/override/beforeNothingToOverride.kt b/idea/testData/quickfix/override/beforeNothingToOverride.kt new file mode 100644 index 00000000000..e33553d62a5 --- /dev/null +++ b/idea/testData/quickfix/override/beforeNothingToOverride.kt @@ -0,0 +1,4 @@ +// "Remove 'override' modifier" "true" +class A() { + override fun foo() {} +} diff --git a/idea/testData/quickfix/override/beforeVirtualMethodHidden.kt b/idea/testData/quickfix/override/beforeVirtualMethodHidden.kt new file mode 100644 index 00000000000..682cdee3abd --- /dev/null +++ b/idea/testData/quickfix/override/beforeVirtualMethodHidden.kt @@ -0,0 +1,8 @@ +// "Add 'override' modifier" "true" +open class A() { + fun foo() {} +} + +class B() : A() { + fun foo() {} +} diff --git a/idea/testData/quickfix/typeAddition/afterWrongGetterParameterType.kt b/idea/testData/quickfix/typeAddition/afterWrongGetterParameterType.kt new file mode 100644 index 00000000000..bd4fd0c6519 --- /dev/null +++ b/idea/testData/quickfix/typeAddition/afterWrongGetterParameterType.kt @@ -0,0 +1,5 @@ +// "Change getter type to Int" "true" +class A() { + val i: Int + get(): Int = 1 +} diff --git a/idea/testData/quickfix/typeAddition/afterWrongSetterParameterType.kt b/idea/testData/quickfix/typeAddition/afterWrongSetterParameterType.kt new file mode 100644 index 00000000000..99e86a2179d --- /dev/null +++ b/idea/testData/quickfix/typeAddition/afterWrongSetterParameterType.kt @@ -0,0 +1,5 @@ +// "Change setter parameter type to Int" "true" +class A() { + var i: Int = 0 + set(v: Int) {} +} diff --git a/idea/testData/quickfix/typeAddition/beforeWrongGetterParameterType.kt b/idea/testData/quickfix/typeAddition/beforeWrongGetterParameterType.kt new file mode 100644 index 00000000000..5e9d12911c8 --- /dev/null +++ b/idea/testData/quickfix/typeAddition/beforeWrongGetterParameterType.kt @@ -0,0 +1,5 @@ +// "Change getter type to Int" "true" +class A() { + val i: Int + get(): Any = 1 +} diff --git a/idea/testData/quickfix/typeAddition/beforeWrongSetterParameterType.kt b/idea/testData/quickfix/typeAddition/beforeWrongSetterParameterType.kt new file mode 100644 index 00000000000..b84c2887217 --- /dev/null +++ b/idea/testData/quickfix/typeAddition/beforeWrongSetterParameterType.kt @@ -0,0 +1,5 @@ +// "Change setter parameter type to Int" "true" +class A() { + var i: Int = 0 + set(v: Any) {} +} diff --git a/idea/tests/org/jetbrains/jet/plugin/quickfix/AbstractModifierTest.java b/idea/tests/org/jetbrains/jet/plugin/quickfix/AbstractModifierTest.java new file mode 100644 index 00000000000..2f137b3a941 --- /dev/null +++ b/idea/tests/org/jetbrains/jet/plugin/quickfix/AbstractModifierTest.java @@ -0,0 +1,24 @@ +package org.jetbrains.jet.plugin.quickfix; + +import com.intellij.codeInsight.daemon.quickFix.LightQuickFixTestCase; +import org.jetbrains.jet.JetTestCaseBase; + +/** + * @author svtk + */ +public class AbstractModifierTest extends LightQuickFixTestCase { + + public void test() throws Exception { + doAllTests(); + } + + @Override + protected String getBasePath() { + return "/quickfix/abstract"; + } + + @Override + protected String getTestDataPath() { + return JetTestCaseBase.getTestDataPathBase(); + } +} diff --git a/idea/tests/org/jetbrains/jet/plugin/quickfix/ChangeVariableMutabilityTest.java b/idea/tests/org/jetbrains/jet/plugin/quickfix/ChangeVariableMutabilityTest.java new file mode 100644 index 00000000000..1690f3a1e66 --- /dev/null +++ b/idea/tests/org/jetbrains/jet/plugin/quickfix/ChangeVariableMutabilityTest.java @@ -0,0 +1,24 @@ +package org.jetbrains.jet.plugin.quickfix; + +import com.intellij.codeInsight.daemon.quickFix.LightQuickFixTestCase; +import org.jetbrains.jet.JetTestCaseBase; + +/** + * @author svtk + */ +public class ChangeVariableMutabilityTest extends LightQuickFixTestCase { + + public void test() throws Exception { + doAllTests(); + } + + @Override + protected String getBasePath() { + return "/quickfix/changeVariableMutability"; + } + + @Override + protected String getTestDataPath() { + return JetTestCaseBase.getTestDataPathBase(); + } +} diff --git a/idea/tests/org/jetbrains/jet/plugin/quickfix/ExpressionsTest.java b/idea/tests/org/jetbrains/jet/plugin/quickfix/ExpressionsTest.java new file mode 100644 index 00000000000..d02253c22ec --- /dev/null +++ b/idea/tests/org/jetbrains/jet/plugin/quickfix/ExpressionsTest.java @@ -0,0 +1,24 @@ +package org.jetbrains.jet.plugin.quickfix; + +import com.intellij.codeInsight.daemon.quickFix.LightQuickFixTestCase; +import org.jetbrains.jet.JetTestCaseBase; + +/** + * @author svtk + */ +public class ExpressionsTest extends LightQuickFixTestCase { + + public void test() throws Exception { + doAllTests(); + } + + @Override + protected String getBasePath() { + return "/quickfix/expressions"; + } + + @Override + protected String getTestDataPath() { + return JetTestCaseBase.getTestDataPathBase(); + } +} diff --git a/idea/tests/org/jetbrains/jet/plugin/quickfix/OverrideModifierTest.java b/idea/tests/org/jetbrains/jet/plugin/quickfix/OverrideModifierTest.java new file mode 100644 index 00000000000..4aad9e4c4ff --- /dev/null +++ b/idea/tests/org/jetbrains/jet/plugin/quickfix/OverrideModifierTest.java @@ -0,0 +1,25 @@ +package org.jetbrains.jet.plugin.quickfix; + +import com.intellij.codeInsight.daemon.quickFix.LightQuickFixTestCase; +import org.jetbrains.jet.JetTestCaseBase; + +/** + * @author svtk + */ +public class OverrideModifierTest extends LightQuickFixTestCase { + + public void test() throws Exception { + doAllTests(); + } + + @Override + protected String getBasePath() { + return "/quickfix/override"; + } + + @Override + protected String getTestDataPath() { + return JetTestCaseBase.getTestDataPathBase(); + } +} + diff --git a/idea/tests/org/jetbrains/jet/plugin/quickfix/TypeAdditionTests.java b/idea/tests/org/jetbrains/jet/plugin/quickfix/TypeAdditionTests.java new file mode 100644 index 00000000000..c45adf043e9 --- /dev/null +++ b/idea/tests/org/jetbrains/jet/plugin/quickfix/TypeAdditionTests.java @@ -0,0 +1,25 @@ +package org.jetbrains.jet.plugin.quickfix; + +import com.intellij.codeInsight.daemon.quickFix.LightQuickFixTestCase; +import org.jetbrains.jet.JetTestCaseBase; + +/** + * @author svtk + */ +public class TypeAdditionTests extends LightQuickFixTestCase { + + public void test() throws Exception { + doAllTests(); + } + + @Override + protected String getBasePath() { + return "/quickfix/typeAddition"; + } + + @Override + protected String getTestDataPath() { + return JetTestCaseBase.getTestDataPathBase(); + } +} +