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 6be2b0227d3..7c4770a21e5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -140,7 +140,7 @@ public interface Errors { SimpleDiagnosticFactory PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT = SimpleDiagnosticFactory.create(ERROR, "Projections are not allowed on type arguments of functions and properties"); // TODO : better positioning SimpleDiagnosticFactory SUPERTYPE_NOT_INITIALIZED = SimpleDiagnosticFactory.create(ERROR, "This type has a constructor, and thus must be initialized here"); - SimpleDiagnosticFactory SUPERTYPE_NOT_INITIALIZED_DEFAULT = SimpleDiagnosticFactory.create(ERROR, "Constructor invocation should be explicitly specified"); + SimplePsiElementOnlyDiagnosticFactory SUPERTYPE_NOT_INITIALIZED_DEFAULT = SimplePsiElementOnlyDiagnosticFactory.create(ERROR, "Constructor invocation should be explicitly specified"); SimpleDiagnosticFactory SECONDARY_CONSTRUCTOR_BUT_NO_PRIMARY = SimpleDiagnosticFactory.create(ERROR, "A secondary constructor may appear only in a class that has a primary constructor"); SimpleDiagnosticFactory SECONDARY_CONSTRUCTOR_NO_INITIALIZER_LIST = SimpleDiagnosticFactory.create(ERROR, "Secondary constructors must have an initializer list"); SimpleDiagnosticFactory BY_IN_SECONDARY_CONSTRUCTOR = SimpleDiagnosticFactory.create(ERROR, "'by'-clause is only supported for primary constructors"); 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 17efe9e1075..3753cd23271 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java @@ -148,26 +148,23 @@ public class BodyResolver { JetTypeReference typeReference = specifier.getTypeReference(); JetType supertype = context.getTrace().getBindingContext().get(BindingContext.TYPE, typeReference); recordSupertype(typeReference, supertype); - if (supertype != null) { - ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype); - if (classDescriptor != null) { - if (descriptor.getKind() != ClassKind.TRAIT) { - if (classDescriptor.hasConstructors() && !ErrorUtils.isError(classDescriptor.getTypeConstructor()) && classDescriptor.getKind() != ClassKind.TRAIT) { - boolean hasConstructorWithoutParams = false; - for (ConstructorDescriptor constructor : classDescriptor.getConstructors()) { - if (constructor.getValueParameters().isEmpty()) { - hasConstructorWithoutParams = true; - } - } - if (!hasConstructorWithoutParams) { - context.getTrace().report(SUPERTYPE_NOT_INITIALIZED.on(specifier)); - } - else { - context.getTrace().report(SUPERTYPE_NOT_INITIALIZED_DEFAULT.on(specifier)); - } - } + if (supertype == null) return; + ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype); + if (classDescriptor == null) return; + if (descriptor.getKind() != ClassKind.TRAIT && classDescriptor.hasConstructors() && + !ErrorUtils.isError(classDescriptor.getTypeConstructor()) && classDescriptor.getKind() != ClassKind.TRAIT) { + boolean hasConstructorWithoutParams = false; + for (ConstructorDescriptor constructor : classDescriptor.getConstructors()) { + if (constructor.getValueParameters().isEmpty()) { + hasConstructorWithoutParams = true; } } + if (!hasConstructorWithoutParams) { + context.getTrace().report(SUPERTYPE_NOT_INITIALIZED.on(specifier)); + } + else { + context.getTrace().report(SUPERTYPE_NOT_INITIALIZED_DEFAULT.on(specifier)); + } } } diff --git a/idea/src/org/jetbrains/jet/plugin/JetBundle.properties b/idea/src/org/jetbrains/jet/plugin/JetBundle.properties index 8b19a79b430..e539390534e 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetBundle.properties +++ b/idea/src/org/jetbrains/jet/plugin/JetBundle.properties @@ -1,7 +1,6 @@ #quick fix messages add.function.body=Add function body -add.primary.constructor=Add primary constructor to {0} -add.primary.constructor.family=Add primary constructor +change.to.constructor.invocation=Change to constructor invocation add.return.type=Add return type declaration change.accessor.type=Change accessor type change.getter.type=Change getter type to {0} diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/AddPrimaryConstructorFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/AddPrimaryConstructorFix.java deleted file mode 100644 index 050bb5eac7f..00000000000 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/AddPrimaryConstructorFix.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.jetbrains.jet.plugin.quickfix; - -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.util.IncorrectOperationException; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; -import org.jetbrains.jet.lang.psi.JetClass; -import org.jetbrains.jet.lang.psi.JetPsiFactory; -import org.jetbrains.jet.plugin.JetBundle; - -/** - * @author svtk - */ -public class AddPrimaryConstructorFix extends JetIntentionAction { - - public AddPrimaryConstructorFix(@NotNull JetClass element) { - super(element); - } - - @NotNull - @Override - public String getText() { - return JetBundle.message("add.primary.constructor", element.getName()); - } - - @NotNull - @Override - public String getFamilyName() { - return JetBundle.message("add.primary.constructor.family"); - } - - @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - JetClass newClass = (JetClass) element.copy(); - assert !newClass.hasPrimaryConstructor(); - PsiElement primaryConstructor = JetPsiFactory.createPrimaryConstructor(project); - newClass.addAfter(primaryConstructor, newClass.getNameIdentifier()); - element.replace(newClass); - } - - public static JetIntentionActionFactory createFactory() { - return new JetIntentionActionFactory() { - @Override - public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { - assert diagnostic.getPsiElement() instanceof JetClass; - return new AddPrimaryConstructorFix((JetClass) diagnostic.getPsiElement()); - } - }; - } -} diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToInvocationFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToInvocationFix.java new file mode 100644 index 00000000000..6d6158ac31b --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeToInvocationFix.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.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement; +import org.jetbrains.jet.lang.psi.JetClass; +import org.jetbrains.jet.lang.psi.JetDelegationSpecifier; +import org.jetbrains.jet.lang.psi.JetDelegatorToSuperClass; +import org.jetbrains.jet.lang.psi.JetPsiFactory; +import org.jetbrains.jet.plugin.JetBundle; + +import java.util.List; + +/** + * @author svtk + */ +public class ChangeToInvocationFix extends JetIntentionAction { + + public ChangeToInvocationFix(@NotNull JetDelegatorToSuperClass element) { + super(element); + } + + @NotNull + @Override + public String getText() { + return JetBundle.message("change.to.constructor.invocation"); + } + + @NotNull + @Override + public String getFamilyName() { + return JetBundle.message("change.to.constructor.invocation"); + } + + @Override + public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + JetDelegatorToSuperClass delegator = (JetDelegatorToSuperClass) element.copy(); + JetClass aClass = JetPsiFactory.createClass(project, "class A : " + delegator.getText() + "()"); + List delegationSpecifiers = aClass.getDelegationSpecifiers(); + assert delegationSpecifiers.size() == 1; + JetDelegationSpecifier specifier = delegationSpecifiers.iterator().next(); + element.replace(specifier); + } + + public static JetIntentionActionFactory createFactory() { + return new JetIntentionActionFactory() { + @Override + public JetIntentionAction createAction(DiagnosticWithPsiElement diagnostic) { + assert diagnostic.getPsiElement() instanceof JetDelegatorToSuperClass; + return new ChangeToInvocationFix((JetDelegatorToSuperClass) diagnostic.getPsiElement()); + } + }; + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java index 6cc4203a50d..26e14ddf8a9 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java @@ -87,7 +87,6 @@ public class QuickFixes { add(Errors.USELESS_ELVIS, RemoveRightPartOfBinaryExpressionFix.createRemoveElvisOperatorFactory()); - JetIntentionActionFactory removeRedundantModifierFactory = RemoveModifierFix.createRemoveModifierFromListFactory(true); add(Errors.REDUNDANT_MODIFIER, removeRedundantModifierFactory); add(Errors.REDUNDANT_MODIFIER_IN_TRAIT, removeRedundantModifierFactory); @@ -112,6 +111,8 @@ public class QuickFixes { JetIntentionActionFactory unresolvedReferenceFactory = ImportClassFix.createFactory(); add(Errors.UNRESOLVED_REFERENCE, unresolvedReferenceFactory); + add(Errors.SUPERTYPE_NOT_INITIALIZED_DEFAULT, ChangeToInvocationFix.createFactory()); + ImplementMethodsHandler implementMethodsHandler = new ImplementMethodsHandler(); actionMap.put(Errors.ABSTRACT_MEMBER_NOT_IMPLEMENTED, implementMethodsHandler); actionMap.put(Errors.MANY_IMPL_MEMBER_NOT_IMPLEMENTED, implementMethodsHandler); diff --git a/idea/testData/quickfix/override/afterChangeToInvocation.kt b/idea/testData/quickfix/override/afterChangeToInvocation.kt new file mode 100644 index 00000000000..51b2c2a5568 --- /dev/null +++ b/idea/testData/quickfix/override/afterChangeToInvocation.kt @@ -0,0 +1,7 @@ +// "Change to constructor invocation" "true" + +open class A { + +} + +class B : A() {} diff --git a/idea/testData/quickfix/override/beforeChangeToInvocation.kt b/idea/testData/quickfix/override/beforeChangeToInvocation.kt new file mode 100644 index 00000000000..88924e45826 --- /dev/null +++ b/idea/testData/quickfix/override/beforeChangeToInvocation.kt @@ -0,0 +1,7 @@ +// "Change to constructor invocation" "true" + +open class A { + +} + +class B : A {}