From 8fbc1113b18d0042e446ec10e601ee20c2cb1149 Mon Sep 17 00:00:00 2001 From: wannabe Date: Sun, 9 Oct 2016 09:25:26 +1000 Subject: [PATCH] Move to struct assignment intention fixes #2702 --- resources/META-INF/gogland.xml | 5 + .../after.go.template | 1 + .../before.go.template | 2 + .../description.html | 21 ++ .../GoStructInitializationInspection.java | 2 +- ...GoMoveToStructInitializationIntention.java | 292 ++++++++++++++++++ src/com/goide/psi/impl/GoElementFactory.java | 4 +- src/com/goide/psi/impl/GoPsiImplUtil.java | 20 ++ .../anonymousField-after.go | 11 + .../anonymousField.go | 11 + .../caretAtValue-after.go | 13 + .../caretAtValue.go | 13 + .../duplicateFields-after.go | 12 + .../duplicateFields.go | 12 + .../existingDeclaration.go | 11 + .../existingField-after.go | 12 + .../existingField.go | 12 + .../fieldExchange-after.go | 12 + .../fieldExchange.go | 12 + .../invalidAssignment-after.go | 17 + .../invalidAssignment.go | 17 + .../justAssignedVar-after.go | 15 + .../justAssignedVar.go | 15 + .../justAssignedVarWrongCaret.go | 15 + .../justInitializedVar-after.go | 12 + .../justInitializedVar.go | 12 + .../justInitializedVarWrongCaret.go | 13 + .../multiReturnFunction.go | 16 + .../multipleAssignmentsLeftmost-after.go | 14 + .../multipleAssignmentsLeftmost.go | 14 + .../multipleAssignmentsMiddle-after.go | 14 + .../multipleAssignmentsMiddle.go | 14 + .../multipleAssignmentsRightmost-after.go | 14 + .../multipleAssignmentsRightmost.go | 14 + .../multipleFields-after.go | 16 + .../multipleFields.go | 16 + .../multipleFieldsPartlyAssigned-after.go | 12 + .../multipleFieldsPartlyAssigned.go | 12 + ...leFieldsSameStructureCaretAtValue-after.go | 14 + ...multipleFieldsSameStructureCaretAtValue.go | 14 + .../notExistingField.go | 11 + .../oneLineFieldDeclaration-after.go | 11 + .../oneLineFieldDeclaration.go | 11 + .../simple-after.go | 11 + .../move-to-struct-initialization/simple.go | 11 + .../structAssignment-after.go | 12 + .../structAssignment.go | 12 + .../structAssignmentMultipleAssignee-after.go | 15 + .../structAssignmentMultipleAssignee.go | 15 + .../twoSameStructures-after.go | 12 + .../twoSameStructures.go | 12 + .../twoSameStructuresAssignment-after.go | 13 + .../twoSameStructuresAssignment.go | 13 + .../withParens-after.go | 11 + .../withParens.go | 11 + .../wrongStruct.go | 16 + ...veToStructInitializationIntentionTest.java | 61 ++++ 57 files changed, 1033 insertions(+), 3 deletions(-) create mode 100644 resources/intentionDescriptions/GoMoveToStructInitializationIntention/after.go.template create mode 100644 resources/intentionDescriptions/GoMoveToStructInitializationIntention/before.go.template create mode 100644 resources/intentionDescriptions/GoMoveToStructInitializationIntention/description.html create mode 100644 src/com/goide/intentions/GoMoveToStructInitializationIntention.java create mode 100644 testData/intentions/move-to-struct-initialization/anonymousField-after.go create mode 100644 testData/intentions/move-to-struct-initialization/anonymousField.go create mode 100644 testData/intentions/move-to-struct-initialization/caretAtValue-after.go create mode 100644 testData/intentions/move-to-struct-initialization/caretAtValue.go create mode 100644 testData/intentions/move-to-struct-initialization/duplicateFields-after.go create mode 100644 testData/intentions/move-to-struct-initialization/duplicateFields.go create mode 100644 testData/intentions/move-to-struct-initialization/existingDeclaration.go create mode 100644 testData/intentions/move-to-struct-initialization/existingField-after.go create mode 100644 testData/intentions/move-to-struct-initialization/existingField.go create mode 100644 testData/intentions/move-to-struct-initialization/fieldExchange-after.go create mode 100644 testData/intentions/move-to-struct-initialization/fieldExchange.go create mode 100644 testData/intentions/move-to-struct-initialization/invalidAssignment-after.go create mode 100644 testData/intentions/move-to-struct-initialization/invalidAssignment.go create mode 100644 testData/intentions/move-to-struct-initialization/justAssignedVar-after.go create mode 100644 testData/intentions/move-to-struct-initialization/justAssignedVar.go create mode 100644 testData/intentions/move-to-struct-initialization/justAssignedVarWrongCaret.go create mode 100644 testData/intentions/move-to-struct-initialization/justInitializedVar-after.go create mode 100644 testData/intentions/move-to-struct-initialization/justInitializedVar.go create mode 100644 testData/intentions/move-to-struct-initialization/justInitializedVarWrongCaret.go create mode 100644 testData/intentions/move-to-struct-initialization/multiReturnFunction.go create mode 100644 testData/intentions/move-to-struct-initialization/multipleAssignmentsLeftmost-after.go create mode 100644 testData/intentions/move-to-struct-initialization/multipleAssignmentsLeftmost.go create mode 100644 testData/intentions/move-to-struct-initialization/multipleAssignmentsMiddle-after.go create mode 100644 testData/intentions/move-to-struct-initialization/multipleAssignmentsMiddle.go create mode 100644 testData/intentions/move-to-struct-initialization/multipleAssignmentsRightmost-after.go create mode 100644 testData/intentions/move-to-struct-initialization/multipleAssignmentsRightmost.go create mode 100644 testData/intentions/move-to-struct-initialization/multipleFields-after.go create mode 100644 testData/intentions/move-to-struct-initialization/multipleFields.go create mode 100644 testData/intentions/move-to-struct-initialization/multipleFieldsPartlyAssigned-after.go create mode 100644 testData/intentions/move-to-struct-initialization/multipleFieldsPartlyAssigned.go create mode 100644 testData/intentions/move-to-struct-initialization/multipleFieldsSameStructureCaretAtValue-after.go create mode 100644 testData/intentions/move-to-struct-initialization/multipleFieldsSameStructureCaretAtValue.go create mode 100644 testData/intentions/move-to-struct-initialization/notExistingField.go create mode 100644 testData/intentions/move-to-struct-initialization/oneLineFieldDeclaration-after.go create mode 100644 testData/intentions/move-to-struct-initialization/oneLineFieldDeclaration.go create mode 100644 testData/intentions/move-to-struct-initialization/simple-after.go create mode 100644 testData/intentions/move-to-struct-initialization/simple.go create mode 100644 testData/intentions/move-to-struct-initialization/structAssignment-after.go create mode 100644 testData/intentions/move-to-struct-initialization/structAssignment.go create mode 100644 testData/intentions/move-to-struct-initialization/structAssignmentMultipleAssignee-after.go create mode 100644 testData/intentions/move-to-struct-initialization/structAssignmentMultipleAssignee.go create mode 100644 testData/intentions/move-to-struct-initialization/twoSameStructures-after.go create mode 100644 testData/intentions/move-to-struct-initialization/twoSameStructures.go create mode 100644 testData/intentions/move-to-struct-initialization/twoSameStructuresAssignment-after.go create mode 100644 testData/intentions/move-to-struct-initialization/twoSameStructuresAssignment.go create mode 100644 testData/intentions/move-to-struct-initialization/withParens-after.go create mode 100644 testData/intentions/move-to-struct-initialization/withParens.go create mode 100644 testData/intentions/move-to-struct-initialization/wrongStruct.go create mode 100644 tests/com/goide/quickfix/GoMoveToStructInitializationIntentionTest.java diff --git a/resources/META-INF/gogland.xml b/resources/META-INF/gogland.xml index fb4e74e2e2..e8a4eac564 100644 --- a/resources/META-INF/gogland.xml +++ b/resources/META-INF/gogland.xml @@ -181,6 +181,11 @@ go.intentions.category com.goide.intentions.GoAddFunctionBlockIntention + + com.goide.GoBundle + go.intentions.category + com.goide.intentions.GoMoveToStructInitializationIntention + foo: `bar`} \ No newline at end of file diff --git a/resources/intentionDescriptions/GoMoveToStructInitializationIntention/before.go.template b/resources/intentionDescriptions/GoMoveToStructInitializationIntention/before.go.template new file mode 100644 index 0000000000..67408ed3b4 --- /dev/null +++ b/resources/intentionDescriptions/GoMoveToStructInitializationIntention/before.go.template @@ -0,0 +1,2 @@ +s := S{} +s.foo = `bar` \ No newline at end of file diff --git a/resources/intentionDescriptions/GoMoveToStructInitializationIntention/description.html b/resources/intentionDescriptions/GoMoveToStructInitializationIntention/description.html new file mode 100644 index 0000000000..772e668122 --- /dev/null +++ b/resources/intentionDescriptions/GoMoveToStructInitializationIntention/description.html @@ -0,0 +1,21 @@ + + + + +This intention moves struct field assignment to struct initialization block. + + \ No newline at end of file diff --git a/src/com/goide/inspections/GoStructInitializationInspection.java b/src/com/goide/inspections/GoStructInitializationInspection.java index d99f6a61c9..67ffd12833 100644 --- a/src/com/goide/inspections/GoStructInitializationInspection.java +++ b/src/com/goide/inspections/GoStructInitializationInspection.java @@ -108,7 +108,7 @@ public GoReplaceWithNamedStructFieldQuickFix(@NotNull String structField) { public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { PsiElement startElement = descriptor.getStartElement(); if (startElement instanceof GoElement) { - startElement.replace(GoElementFactory.createNamedStructField(project, myStructField, startElement.getText())); + startElement.replace(GoElementFactory.createLiteralValueElement(project, myStructField, startElement.getText())); } } } diff --git a/src/com/goide/intentions/GoMoveToStructInitializationIntention.java b/src/com/goide/intentions/GoMoveToStructInitializationIntention.java new file mode 100644 index 0000000000..2e747fe672 --- /dev/null +++ b/src/com/goide/intentions/GoMoveToStructInitializationIntention.java @@ -0,0 +1,292 @@ +/* + * Copyright 2013-2016 Sergey Ignatov, Alexander Zolotov, Florin Patan + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.goide.intentions; + +import com.goide.psi.*; +import com.goide.psi.impl.GoElementFactory; +import com.goide.psi.impl.GoPsiImplUtil; +import com.intellij.codeInsight.intention.BaseElementAtCaretIntentionAction; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.IncorrectOperationException; +import com.intellij.util.ObjectUtils; +import com.intellij.util.containers.MultiMap; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Set; + +import static com.intellij.util.containers.ContainerUtil.*; + +public class GoMoveToStructInitializationIntention extends BaseElementAtCaretIntentionAction { + public static final String NAME = "Move field assignment to struct initialization"; + + public GoMoveToStructInitializationIntention() { + setText(NAME); + } + + @Nls + @NotNull + @Override + public String getFamilyName() { + return NAME; + } + + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) { + return getData(element) != null; + } + + @Nullable + private static Data getData(@NotNull PsiElement element) { + if (!element.isValid() || !element.isWritable()) return null; + GoAssignmentStatement assignment = getValidAssignmentParent(element); + GoReferenceExpression selectedFieldReference = assignment != null ? getFieldReferenceExpression(element, assignment) : null; + GoCompositeLit compositeLit = selectedFieldReference != null ? getStructLiteralByReference(selectedFieldReference, assignment) : null; + if (compositeLit == null) return null; + + List references = getUninitializedSingleFieldReferences(assignment, selectedFieldReference, compositeLit); + return !references.isEmpty() ? new Data(assignment, compositeLit, references) : null; + } + + @Nullable + private static GoAssignmentStatement getValidAssignmentParent(@Nullable PsiElement element) { + GoAssignmentStatement assignment = PsiTreeUtil.getNonStrictParentOfType(element, GoAssignmentStatement.class); + return assignment != null && assignment.isValid() && getLeftHandElements(assignment).size() == assignment.getExpressionList().size() + ? assignment : null; + } + + @Nullable + private static GoReferenceExpression getFieldReferenceExpression(@NotNull PsiElement selectedElement, + @NotNull GoAssignmentStatement assignment) { + GoReferenceExpression selectedReferenceExpression = PsiTreeUtil.getTopmostParentOfType(selectedElement, GoReferenceExpression.class); + if (isFieldReferenceExpression(selectedReferenceExpression)) { + return !isAssignedInPreviousStatement(selectedReferenceExpression, assignment) ? selectedReferenceExpression : null; + } + + List fieldReferenceExpressions = getFieldReferenceExpressions(assignment); + if (exists(fieldReferenceExpressions, expression -> isAssignedInPreviousStatement(expression, assignment))) return null; + + Set resolvedFields = map2Set(fieldReferenceExpressions, GoMoveToStructInitializationIntention::resolveQualifier); + return resolvedFields.size() == 1 ? getFirstItem(fieldReferenceExpressions) : null; + } + + @NotNull + private static List getFieldReferenceExpressions(@NotNull GoAssignmentStatement assignment) { + return filter(map(getLeftHandElements(assignment), GoMoveToStructInitializationIntention::unwrapParensAndCast), + GoMoveToStructInitializationIntention::isFieldReferenceExpression); + } + + @Nullable + private static GoReferenceExpression unwrapParensAndCast(@NotNull PsiElement e) { + while (e instanceof GoParenthesesExpr) { + e = ((GoParenthesesExpr)e).getExpression(); + } + return ObjectUtils.tryCast(e, GoReferenceExpression.class); + } + + @Contract("null -> false") + private static boolean isFieldReferenceExpression(@Nullable PsiElement element) { + return element instanceof GoReferenceExpression && isFieldDefinition(((GoReferenceExpression)element).resolve()); + } + + @Contract("null -> false") + private static boolean isFieldDefinition(@Nullable PsiElement element) { + return element instanceof GoFieldDefinition || element instanceof GoAnonymousFieldDefinition; + } + + private static boolean isAssignedInPreviousStatement(@NotNull GoExpression referenceExpression, + @NotNull GoAssignmentStatement assignment) { + GoReferenceExpression rightExpression = ObjectUtils.tryCast(GoPsiImplUtil.getRightExpression(assignment, referenceExpression), + GoReferenceExpression.class); + + PsiElement resolve = rightExpression != null ? rightExpression.resolve() : null; + GoStatement previousElement = resolve != null ? PsiTreeUtil.getPrevSiblingOfType(assignment, GoStatement.class) : null; + return previousElement != null && exists(getLeftHandElements(previousElement), e -> isResolvedTo(e, resolve)); + } + + private static boolean isResolvedTo(@Nullable PsiElement e, @Nullable PsiElement resolve) { + if (e instanceof GoVarDefinition) return resolve == e; + + GoReferenceExpression refExpression = ObjectUtils.tryCast(e, GoReferenceExpression.class); + return refExpression != null && refExpression.resolve() == resolve; + } + + @NotNull + private static List getUninitializedSingleFieldReferences(@NotNull GoAssignmentStatement assignment, + @NotNull GoReferenceExpression fieldReferenceExpression, + @NotNull GoCompositeLit compositeLit) { + PsiElement resolve = resolveQualifier(fieldReferenceExpression); + List uninitializedFieldReferencesByQualifier = + filter(getUninitializedFieldReferenceExpressions(assignment, compositeLit), e -> isResolvedTo(e.getQualifier(), resolve)); + MultiMap resolved = groupBy(uninitializedFieldReferencesByQualifier, GoReferenceExpression::resolve); + return map(filter(resolved.entrySet(), set -> set.getValue().size() == 1), set -> getFirstItem(set.getValue())); + } + + @Nullable + private static GoCompositeLit getStructLiteralByReference(@NotNull GoReferenceExpression fieldReferenceExpression, + @NotNull GoAssignmentStatement assignment) { + GoStatement previousStatement = PsiTreeUtil.getPrevSiblingOfType(assignment, GoStatement.class); + if (previousStatement instanceof GoSimpleStatement) { + return getStructLiteral(fieldReferenceExpression, (GoSimpleStatement)previousStatement); + } + if (previousStatement instanceof GoAssignmentStatement) { + return getStructLiteral(fieldReferenceExpression, (GoAssignmentStatement)previousStatement); + } + return null; + } + + @Nullable + private static GoCompositeLit getStructLiteral(@NotNull GoReferenceExpression fieldReferenceExpression, + @NotNull GoSimpleStatement structDeclaration) { + GoShortVarDeclaration varDeclaration = structDeclaration.getShortVarDeclaration(); + if (varDeclaration == null) return null; + + PsiElement resolve = resolveQualifier(fieldReferenceExpression); + GoVarDefinition structVarDefinition = find(varDeclaration.getVarDefinitionList(), definition -> resolve == definition); + return structVarDefinition != null ? ObjectUtils.tryCast(structVarDefinition.getValue(), GoCompositeLit.class) : null; + } + + @Nullable + private static PsiElement resolveQualifier(@NotNull GoReferenceExpression fieldReferenceExpression) { + GoReferenceExpression qualifier = fieldReferenceExpression.getQualifier(); + return qualifier != null ? qualifier.resolve() : null; + } + + @Nullable + private static GoCompositeLit getStructLiteral(@NotNull GoReferenceExpression fieldReferenceExpression, + @NotNull GoAssignmentStatement structAssignment) { + GoVarDefinition varDefinition = ObjectUtils.tryCast(resolveQualifier(fieldReferenceExpression), GoVarDefinition.class); + PsiElement field = fieldReferenceExpression.resolve(); + if (varDefinition == null || !isFieldDefinition(field) || !hasStructTypeWithField(varDefinition, (GoNamedElement)field)) { + return null; + } + + GoExpression structReferenceExpression = find(structAssignment.getLeftHandExprList().getExpressionList(), + expression -> isResolvedTo(expression, varDefinition)); + if (structReferenceExpression == null) return null; + GoExpression compositeLit = GoPsiImplUtil.getRightExpression(structAssignment, structReferenceExpression); + return ObjectUtils.tryCast(compositeLit, GoCompositeLit.class); + } + + private static boolean hasStructTypeWithField(@NotNull GoVarDefinition structVarDefinition, @NotNull GoNamedElement field) { + GoType type = structVarDefinition.getGoType(null); + GoStructType structType = type != null ? ObjectUtils.tryCast(type.getUnderlyingType(), GoStructType.class) : null; + return structType != null && PsiTreeUtil.isAncestor(structType, field, true); + } + + private static boolean isFieldInitialization(@NotNull GoElement element, @NotNull PsiElement field) { + GoKey key = element.getKey(); + GoFieldName fieldName = key != null ? key.getFieldName() : null; + return fieldName != null && fieldName.resolve() == field; + } + + @NotNull + private static List getUninitializedFieldReferenceExpressions(@NotNull GoAssignmentStatement assignment, + @NotNull GoCompositeLit structLiteral) { + return filter(getFieldReferenceExpressions(assignment), expression -> + isUninitializedFieldReferenceExpression(expression, structLiteral) && !isAssignedInPreviousStatement(expression, assignment)); + } + + @Contract("null, _-> false") + private static boolean isUninitializedFieldReferenceExpression(@Nullable GoReferenceExpression fieldReferenceExpression, + @NotNull GoCompositeLit structLiteral) { + if (fieldReferenceExpression == null) return false; + GoLiteralValue literalValue = structLiteral.getLiteralValue(); + PsiElement resolve = fieldReferenceExpression.resolve(); + return literalValue != null && isFieldDefinition(resolve) && + !exists(literalValue.getElementList(), element -> isFieldInitialization(element, resolve)); + } + + @NotNull + private static List getLeftHandElements(@NotNull GoStatement statement) { + if (statement instanceof GoSimpleStatement) { + GoShortVarDeclaration varDeclaration = ((GoSimpleStatement)statement).getShortVarDeclaration(); + return varDeclaration != null ? varDeclaration.getVarDefinitionList() : emptyList(); + } + if (statement instanceof GoAssignmentStatement) { + return ((GoAssignmentStatement)statement).getLeftHandExprList().getExpressionList(); + } + return emptyList(); + } + + @Override + public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { + Data data = getData(element); + if (data == null) return; + moveFieldReferenceExpressions(data); + } + + private static void moveFieldReferenceExpressions(@NotNull Data data) { + GoLiteralValue literalValue = data.getCompositeLit().getLiteralValue(); + if (literalValue == null) return; + + for (GoReferenceExpression expression : data.getReferenceExpressions()) { + GoExpression parentExpression = PsiTreeUtil.getTopmostParentOfType(expression, GoExpression.class); + GoExpression anchor = parentExpression != null ? parentExpression : expression; + GoExpression fieldValue = GoPsiImplUtil.getRightExpression(data.getAssignment(), anchor); + if (fieldValue == null) continue; + + GoPsiImplUtil.deleteExpressionFromAssignment(data.getAssignment(), anchor); + addFieldDefinition(literalValue, expression.getIdentifier().getText(), fieldValue.getText()); + } + } + + private static void addFieldDefinition(@NotNull GoLiteralValue literalValue, @NotNull String name, @NotNull String value) { + Project project = literalValue.getProject(); + PsiElement newField = GoElementFactory.createLiteralValueElement(project, name, value); + GoElement lastElement = getLastItem(literalValue.getElementList()); + if (lastElement == null) { + literalValue.addAfter(newField, literalValue.getLbrace()); + } + else { + lastElement.add(GoElementFactory.createComma(project)); + lastElement.add(newField); + } + } + + private static class Data { + private final GoCompositeLit myCompositeLit; + private final GoAssignmentStatement myAssignment; + private final List myReferenceExpressions; + + public Data(@NotNull GoAssignmentStatement assignment, + @NotNull GoCompositeLit compositeLit, + @NotNull List referenceExpressions) { + myCompositeLit = compositeLit; + myAssignment = assignment; + myReferenceExpressions = referenceExpressions; + } + + public GoCompositeLit getCompositeLit() { + return myCompositeLit; + } + + public GoAssignmentStatement getAssignment() { + return myAssignment; + } + + public List getReferenceExpressions() { + return myReferenceExpressions; + } + } +} diff --git a/src/com/goide/psi/impl/GoElementFactory.java b/src/com/goide/psi/impl/GoElementFactory.java index e33518a42a..a9c4939ad2 100644 --- a/src/com/goide/psi/impl/GoElementFactory.java +++ b/src/com/goide/psi/impl/GoElementFactory.java @@ -256,8 +256,8 @@ public static GoType createType(@NotNull Project project, @NotNull String text) return PsiTreeUtil.findChildOfType(file, GoType.class); } - public static PsiElement createNamedStructField(@NotNull Project project, @NotNull String field, @NotNull String element) { - GoFile file = createFileFromText(project, "package a; var _ = struct { a string } { " + field + ": " + element + " }"); + public static PsiElement createLiteralValueElement(@NotNull Project project, @NotNull String key, @NotNull String value) { + GoFile file = createFileFromText(project, "package a; var _ = struct { a string } { " + key + ": " + value + " }"); return PsiTreeUtil.findChildOfType(file, GoElement.class); } diff --git a/src/com/goide/psi/impl/GoPsiImplUtil.java b/src/com/goide/psi/impl/GoPsiImplUtil.java index 6f76e0142c..9a64f17293 100644 --- a/src/com/goide/psi/impl/GoPsiImplUtil.java +++ b/src/com/goide/psi/impl/GoPsiImplUtil.java @@ -1354,6 +1354,20 @@ public static void deleteSpec(@NotNull GoConstDeclaration declaration, @NotNull specToDelete.delete(); } + public static void deleteExpressionFromAssignment(@NotNull GoAssignmentStatement assignment, + @NotNull GoExpression expressionToDelete) { + GoExpression expressionValue = getRightExpression(assignment, expressionToDelete); + if (expressionValue != null) { + if (assignment.getExpressionList().size() == 1) { + assignment.delete(); + } + else { + deleteElementFromCommaSeparatedList(expressionToDelete); + deleteElementFromCommaSeparatedList(expressionValue); + } + } + } + public static void deleteDefinition(@NotNull GoVarSpec spec, @NotNull GoVarDefinition definitionToDelete) { List definitionList = spec.getVarDefinitionList(); int index = definitionList.indexOf(definitionToDelete); @@ -1679,4 +1693,10 @@ private static PsiElement getNotNullElement(@Nullable PsiElement... elements) { public static boolean isSingleCharLiteral(@NotNull GoStringLiteral literal) { return literal.getDecodedText().length() == 1; } + + @Nullable + public static GoExpression getRightExpression(@NotNull GoAssignmentStatement assignment, @NotNull GoExpression leftExpression) { + int fieldIndex = assignment.getLeftHandExprList().getExpressionList().indexOf(leftExpression); + return getByIndex(assignment.getExpressionList(), fieldIndex); + } } diff --git a/testData/intentions/move-to-struct-initialization/anonymousField-after.go b/testData/intentions/move-to-struct-initialization/anonymousField-after.go new file mode 100644 index 0000000000..e4d0498ed5 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/anonymousField-after.go @@ -0,0 +1,11 @@ +package main + +type S struct { + string +} + +func main() { + s := S{string: "bar"} + _ = "foo" + print(s.string) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/anonymousField.go b/testData/intentions/move-to-struct-initialization/anonymousField.go new file mode 100644 index 0000000000..0e511a337b --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/anonymousField.go @@ -0,0 +1,11 @@ +package main + +type S struct { + string +} + +func main() { + s := S{} + _, s.string = "foo", "bar" + print(s.string) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/caretAtValue-after.go b/testData/intentions/move-to-struct-initialization/caretAtValue-after.go new file mode 100644 index 0000000000..7c7a282ee7 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/caretAtValue-after.go @@ -0,0 +1,13 @@ +package main + +type S struct { + foo string +} + +func main() { + var b string + s := S{foo: "bar"} + b = "b" + print(s.foo) + print(b) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/caretAtValue.go b/testData/intentions/move-to-struct-initialization/caretAtValue.go new file mode 100644 index 0000000000..66e6a641e9 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/caretAtValue.go @@ -0,0 +1,13 @@ +package main + +type S struct { + foo string +} + +func main() { + var b string + s := S{} + s.foo, b = "bar", "b" + print(s.foo) + print(b) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/duplicateFields-after.go b/testData/intentions/move-to-struct-initialization/duplicateFields-after.go new file mode 100644 index 0000000000..54211ba34b --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/duplicateFields-after.go @@ -0,0 +1,12 @@ +package main + +type S struct { + foo string + bar string +} + +func main() { + s := S{bar: "bar"} + s.foo, s.foo = "foo", "bar1" + print(s.foo) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/duplicateFields.go b/testData/intentions/move-to-struct-initialization/duplicateFields.go new file mode 100644 index 0000000000..8f93269c4d --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/duplicateFields.go @@ -0,0 +1,12 @@ +package main + +type S struct { + foo string + bar string +} + +func main() { + s := S{} + s.foo, s.foo, s.bar= "foo", "bar1", "bar" + print(s.foo) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/existingDeclaration.go b/testData/intentions/move-to-struct-initialization/existingDeclaration.go new file mode 100644 index 0000000000..4c33d15504 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/existingDeclaration.go @@ -0,0 +1,11 @@ +package main + +type S struct { + foo string +} + +func main() { + s := S{foo: "foo"} + s.foo = "bar" + print(s.foo) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/existingField-after.go b/testData/intentions/move-to-struct-initialization/existingField-after.go new file mode 100644 index 0000000000..23b5291430 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/existingField-after.go @@ -0,0 +1,12 @@ +package main + +type S struct { + foo string + b string +} + +func main() { + s := S{b: "a", foo: "bar"} + + print(s.foo) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/existingField.go b/testData/intentions/move-to-struct-initialization/existingField.go new file mode 100644 index 0000000000..2d12e731dd --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/existingField.go @@ -0,0 +1,12 @@ +package main + +type S struct { + foo string + b string +} + +func main() { + s := S{b: "a"} + s.foo = "bar" + print(s.foo) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/fieldExchange-after.go b/testData/intentions/move-to-struct-initialization/fieldExchange-after.go new file mode 100644 index 0000000000..131fa8ccff --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/fieldExchange-after.go @@ -0,0 +1,12 @@ +package main + +type S struct { + foo string +} + +func main() { + var b, s S + s, b.foo = S{foo: "bar"}, "foo" + + print(s.foo) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/fieldExchange.go b/testData/intentions/move-to-struct-initialization/fieldExchange.go new file mode 100644 index 0000000000..0073c57fb7 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/fieldExchange.go @@ -0,0 +1,12 @@ +package main + +type S struct { + foo string +} + +func main() { + var b, s S + s, b.foo = S{}, "foo" + s.foo = "bar" + print(s.foo) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/invalidAssignment-after.go b/testData/intentions/move-to-struct-initialization/invalidAssignment-after.go new file mode 100644 index 0000000000..f2198ad58f --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/invalidAssignment-after.go @@ -0,0 +1,17 @@ +package main + +type S struct { + foo string + bar string +} + +func str2() (string, string) { + return "foo", "bar" +} + +func main() { + var a string + s := S{foo: str2(), bar: "bar"} + + print(s.foo) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/invalidAssignment.go b/testData/intentions/move-to-struct-initialization/invalidAssignment.go new file mode 100644 index 0000000000..fabc8e57ee --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/invalidAssignment.go @@ -0,0 +1,17 @@ +package main + +type S struct { + foo string + bar string +} + +func str2() (string, string) { + return "foo", "bar" +} + +func main() { + var a string + s := S{} + s.foo, s.bar = str2(), "bar" + print(s.foo) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/justAssignedVar-after.go b/testData/intentions/move-to-struct-initialization/justAssignedVar-after.go new file mode 100644 index 0000000000..80b5a35fe3 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/justAssignedVar-after.go @@ -0,0 +1,15 @@ +package main + +type S struct { + foo string + bar string +} + +func main() { + var s S + var str string + s, str = S{foo: "foo"}, "bar" + s.bar = str + print(s.foo) + print(str) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/justAssignedVar.go b/testData/intentions/move-to-struct-initialization/justAssignedVar.go new file mode 100644 index 0000000000..6cad8dc808 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/justAssignedVar.go @@ -0,0 +1,15 @@ +package main + +type S struct { + foo string + bar string +} + +func main() { + var s S + var str string + s, str = S{}, "bar" + s.foo, s.bar = "foo", str + print(s.foo) + print(str) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/justAssignedVarWrongCaret.go b/testData/intentions/move-to-struct-initialization/justAssignedVarWrongCaret.go new file mode 100644 index 0000000000..3d3455751e --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/justAssignedVarWrongCaret.go @@ -0,0 +1,15 @@ +package main + +type S struct { + foo string + bar string +} + +func main() { + var s S + var str string + s, str = S{}, "bar" + s.foo, s.bar = "foo", str + print(s.foo) + print(str) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/justInitializedVar-after.go b/testData/intentions/move-to-struct-initialization/justInitializedVar-after.go new file mode 100644 index 0000000000..e95b1e8e47 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/justInitializedVar-after.go @@ -0,0 +1,12 @@ +package main + +type S struct { + foo string + bar string +} + +func main() { + s, str := S{foo: "foo"}, "bar" + s.bar = str + print(s.foo) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/justInitializedVar.go b/testData/intentions/move-to-struct-initialization/justInitializedVar.go new file mode 100644 index 0000000000..d8abcc0b82 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/justInitializedVar.go @@ -0,0 +1,12 @@ +package main + +type S struct { + foo string + bar string +} + +func main() { + s, str := S{}, "bar" + s.foo, s.bar = "foo", str + print(s.foo) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/justInitializedVarWrongCaret.go b/testData/intentions/move-to-struct-initialization/justInitializedVarWrongCaret.go new file mode 100644 index 0000000000..8f357ee9cc --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/justInitializedVarWrongCaret.go @@ -0,0 +1,13 @@ +package main + +type S struct { + foo string + bar string +} + + +func main() { + s, str := S{}, "bar" + s.foo, s.bar = "foo", str + print(s.foo) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/multiReturnFunction.go b/testData/intentions/move-to-struct-initialization/multiReturnFunction.go new file mode 100644 index 0000000000..2bb67374f8 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/multiReturnFunction.go @@ -0,0 +1,16 @@ +package main + +type S struct { + foo int + bar int +} + +func int2() (int, int) { + return 1, 2 +} + +func main() { + s := S{} + s.foo, s.bar= int2() + print(s.foo) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/multipleAssignmentsLeftmost-after.go b/testData/intentions/move-to-struct-initialization/multipleAssignmentsLeftmost-after.go new file mode 100644 index 0000000000..028057d908 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/multipleAssignmentsLeftmost-after.go @@ -0,0 +1,14 @@ +package main + +type S struct { + foo string +} + +func main() { + var b, a string + s := S{foo: "bar"} + b, a = "b", "a" + print(s.foo) + print(b) + print(a) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/multipleAssignmentsLeftmost.go b/testData/intentions/move-to-struct-initialization/multipleAssignmentsLeftmost.go new file mode 100644 index 0000000000..7f489ee8f4 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/multipleAssignmentsLeftmost.go @@ -0,0 +1,14 @@ +package main + +type S struct { + foo string +} + +func main() { + var b, a string + s := S{} + s.foo, b, a = "bar", "b", "a" + print(s.foo) + print(b) + print(a) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/multipleAssignmentsMiddle-after.go b/testData/intentions/move-to-struct-initialization/multipleAssignmentsMiddle-after.go new file mode 100644 index 0000000000..be22fd6b67 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/multipleAssignmentsMiddle-after.go @@ -0,0 +1,14 @@ +package main + +type S struct { + foo string +} + +func main() { + var b, a string + s := S{foo: "bar"} + a, b = "a", "c" + print(s.foo) + print(b) + print(a) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/multipleAssignmentsMiddle.go b/testData/intentions/move-to-struct-initialization/multipleAssignmentsMiddle.go new file mode 100644 index 0000000000..ddbe9f9c36 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/multipleAssignmentsMiddle.go @@ -0,0 +1,14 @@ +package main + +type S struct { + foo string +} + +func main() { + var b, a string + s := S{} + a, s.foo, b = "a", "bar", "c" + print(s.foo) + print(b) + print(a) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/multipleAssignmentsRightmost-after.go b/testData/intentions/move-to-struct-initialization/multipleAssignmentsRightmost-after.go new file mode 100644 index 0000000000..b3f41dbe87 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/multipleAssignmentsRightmost-after.go @@ -0,0 +1,14 @@ +package main + +type S struct { + foo string +} + +func main() { + var b, a string + s := S{foo: "bar"} + a, b = "a", "b" + print(s.foo) + print(b) + print(a) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/multipleAssignmentsRightmost.go b/testData/intentions/move-to-struct-initialization/multipleAssignmentsRightmost.go new file mode 100644 index 0000000000..b8f57591ee --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/multipleAssignmentsRightmost.go @@ -0,0 +1,14 @@ +package main + +type S struct { + foo string +} + +func main() { + var b, a string + s := S{} + a, b, s.foo = "a", "b", "bar" + print(s.foo) + print(b) + print(a) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/multipleFields-after.go b/testData/intentions/move-to-struct-initialization/multipleFields-after.go new file mode 100644 index 0000000000..0c058a291a --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/multipleFields-after.go @@ -0,0 +1,16 @@ +package main + +type S struct { + foo string + bar string +} + +type B struct { + x int +} + +func main() { + s, b := S{foo: "foo", bar: "bar"}, B{} + b.x = 3 + print(s.foo) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/multipleFields.go b/testData/intentions/move-to-struct-initialization/multipleFields.go new file mode 100644 index 0000000000..ee1238644e --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/multipleFields.go @@ -0,0 +1,16 @@ +package main + +type S struct { + foo string + bar string +} + +type B struct { + x int +} + +func main() { + s, b := S{}, B{} + s.foo, b.x, s.bar= "foo", 3, "bar" + print(s.foo) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/multipleFieldsPartlyAssigned-after.go b/testData/intentions/move-to-struct-initialization/multipleFieldsPartlyAssigned-after.go new file mode 100644 index 0000000000..bfd47e2d94 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/multipleFieldsPartlyAssigned-after.go @@ -0,0 +1,12 @@ +package main + +type S struct { + foo string + bar string +} + +func main() { + s := S{foo: "oof", bar: "bar"} + s.foo = "foo" + print(s.foo) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/multipleFieldsPartlyAssigned.go b/testData/intentions/move-to-struct-initialization/multipleFieldsPartlyAssigned.go new file mode 100644 index 0000000000..b0a386b69c --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/multipleFieldsPartlyAssigned.go @@ -0,0 +1,12 @@ +package main + +type S struct { + foo string + bar string +} + +func main() { + s := S{foo: "oof"} + s.foo, s.bar = "foo", "bar" + print(s.foo) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/multipleFieldsSameStructureCaretAtValue-after.go b/testData/intentions/move-to-struct-initialization/multipleFieldsSameStructureCaretAtValue-after.go new file mode 100644 index 0000000000..a7d3ccf814 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/multipleFieldsSameStructureCaretAtValue-after.go @@ -0,0 +1,14 @@ +package main + +type S struct { + foo string + bar string +} + +func main() { + var a int + s := S{foo: "foo", bar: "bar"} + a = 3 + print(s.foo) + print(a) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/multipleFieldsSameStructureCaretAtValue.go b/testData/intentions/move-to-struct-initialization/multipleFieldsSameStructureCaretAtValue.go new file mode 100644 index 0000000000..2239ea38eb --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/multipleFieldsSameStructureCaretAtValue.go @@ -0,0 +1,14 @@ +package main + +type S struct { + foo string + bar string +} + +func main() { + var a int + s := S{} + s.foo, a, s.bar = "foo", 3, "bar" + print(s.foo) + print(a) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/notExistingField.go b/testData/intentions/move-to-struct-initialization/notExistingField.go new file mode 100644 index 0000000000..d9d78a6201 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/notExistingField.go @@ -0,0 +1,11 @@ +package main + +type S struct { + foo string +} + +func main() { + s := S{} + s.x = "bar" + print(s.foo) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/oneLineFieldDeclaration-after.go b/testData/intentions/move-to-struct-initialization/oneLineFieldDeclaration-after.go new file mode 100644 index 0000000000..9b120bc206 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/oneLineFieldDeclaration-after.go @@ -0,0 +1,11 @@ +package main + +type S struct { + bar, foo string +} + +func main() { + s := S{foo: "bar"} + + print(s.foo) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/oneLineFieldDeclaration.go b/testData/intentions/move-to-struct-initialization/oneLineFieldDeclaration.go new file mode 100644 index 0000000000..7bdd767673 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/oneLineFieldDeclaration.go @@ -0,0 +1,11 @@ +package main + +type S struct { + bar, foo string +} + +func main() { + s := S{} + s.foo = "bar" + print(s.foo) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/simple-after.go b/testData/intentions/move-to-struct-initialization/simple-after.go new file mode 100644 index 0000000000..18f6832ca8 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/simple-after.go @@ -0,0 +1,11 @@ +package main + +type S struct { + foo string +} + +func main() { + s := S{foo: "bar"} + + print(s.foo) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/simple.go b/testData/intentions/move-to-struct-initialization/simple.go new file mode 100644 index 0000000000..83bba1fbf8 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/simple.go @@ -0,0 +1,11 @@ +package main + +type S struct { + foo string +} + +func main() { + s := S{} + s.foo = "bar" + print(s.foo) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/structAssignment-after.go b/testData/intentions/move-to-struct-initialization/structAssignment-after.go new file mode 100644 index 0000000000..0ae8edf962 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/structAssignment-after.go @@ -0,0 +1,12 @@ +package main + +type S struct { + foo string +} + +func main() { + var s S + s = S{foo: "bar"} + + print(s.foo) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/structAssignment.go b/testData/intentions/move-to-struct-initialization/structAssignment.go new file mode 100644 index 0000000000..249eb04169 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/structAssignment.go @@ -0,0 +1,12 @@ +package main + +type S struct { + foo string +} + +func main() { + var s S + s = S{} + s.foo = "bar" + print(s.foo) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/structAssignmentMultipleAssignee-after.go b/testData/intentions/move-to-struct-initialization/structAssignmentMultipleAssignee-after.go new file mode 100644 index 0000000000..8c69a261d8 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/structAssignmentMultipleAssignee-after.go @@ -0,0 +1,15 @@ +package main + +type S struct { + foo string +} + +func main() { + var s S + var a, b string + a, s, b = "a", S{foo: "bar"}, "b" + + print(s.foo) + print(a) + print(b) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/structAssignmentMultipleAssignee.go b/testData/intentions/move-to-struct-initialization/structAssignmentMultipleAssignee.go new file mode 100644 index 0000000000..6114ee4b97 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/structAssignmentMultipleAssignee.go @@ -0,0 +1,15 @@ +package main + +type S struct { + foo string +} + +func main() { + var s S + var a, b string + a, s, b = "a", S{}, "b" + s.foo = "bar" + print(s.foo) + print(a) + print(b) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/twoSameStructures-after.go b/testData/intentions/move-to-struct-initialization/twoSameStructures-after.go new file mode 100644 index 0000000000..fbd0835587 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/twoSameStructures-after.go @@ -0,0 +1,12 @@ +package main + +type S struct { + foo string +} + +func main() { + s, b := S{}, S{foo: "foo"} + s.foo = "bar" + print(s.foo) + print(b.foo) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/twoSameStructures.go b/testData/intentions/move-to-struct-initialization/twoSameStructures.go new file mode 100644 index 0000000000..2e54129344 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/twoSameStructures.go @@ -0,0 +1,12 @@ +package main + +type S struct { + foo string +} + +func main() { + s, b := S{}, S{} + s.foo, b.foo = "bar", "foo" + print(s.foo) + print(b.foo) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/twoSameStructuresAssignment-after.go b/testData/intentions/move-to-struct-initialization/twoSameStructuresAssignment-after.go new file mode 100644 index 0000000000..68a75222f5 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/twoSameStructuresAssignment-after.go @@ -0,0 +1,13 @@ +package main + +type S struct { + foo string +} + +func main() { + var s, b S + s, b = S{}, S{foo: "foo"} + s.foo = "bar" + print(s.foo) + print(b.foo) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/twoSameStructuresAssignment.go b/testData/intentions/move-to-struct-initialization/twoSameStructuresAssignment.go new file mode 100644 index 0000000000..f4355d8cde --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/twoSameStructuresAssignment.go @@ -0,0 +1,13 @@ +package main + +type S struct { + foo string +} + +func main() { + var s, b S + s, b = S{}, S{} + s.foo, b.foo = "bar", "foo" + print(s.foo) + print(b.foo) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/withParens-after.go b/testData/intentions/move-to-struct-initialization/withParens-after.go new file mode 100644 index 0000000000..c503fbdd72 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/withParens-after.go @@ -0,0 +1,11 @@ +package main + +type S struct { + string +} + +func main() { + s := S{string: "bar"} + (_) = "foo" + print(s.string) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/withParens.go b/testData/intentions/move-to-struct-initialization/withParens.go new file mode 100644 index 0000000000..13ebe498b9 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/withParens.go @@ -0,0 +1,11 @@ +package main + +type S struct { + string +} + +func main() { + s := S{} + (_), ((s.string)) = "foo", "bar" + print(s.string) +} \ No newline at end of file diff --git a/testData/intentions/move-to-struct-initialization/wrongStruct.go b/testData/intentions/move-to-struct-initialization/wrongStruct.go new file mode 100644 index 0000000000..7e2e91cfc4 --- /dev/null +++ b/testData/intentions/move-to-struct-initialization/wrongStruct.go @@ -0,0 +1,16 @@ +package main + +type S struct { + foo string +} + +type B struct { + bar string +} + +func main() { + var s S + b := B{} + s.foo = "bar" + print(b.foo) +} \ No newline at end of file diff --git a/tests/com/goide/quickfix/GoMoveToStructInitializationIntentionTest.java b/tests/com/goide/quickfix/GoMoveToStructInitializationIntentionTest.java new file mode 100644 index 0000000000..e3b4a25b44 --- /dev/null +++ b/tests/com/goide/quickfix/GoMoveToStructInitializationIntentionTest.java @@ -0,0 +1,61 @@ +/* + * Copyright 2013-2016 Sergey Ignatov, Alexander Zolotov, Florin Patan + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.goide.quickfix; + +import com.goide.intentions.GoMoveToStructInitializationIntention; +import org.jetbrains.annotations.NotNull; + +public class GoMoveToStructInitializationIntentionTest extends GoQuickFixTestBase { + @NotNull + @Override + protected String getBasePath() { + return "intentions/move-to-struct-initialization"; + } + + private void doTest() { doTest(GoMoveToStructInitializationIntention.NAME); } + private void doTestNoFix() { doTestNoFix(GoMoveToStructInitializationIntention.NAME); } + + public void testSimple() { doTest(); } + public void testFieldExchange() { doTest(); } + public void testCaretAtValue() { doTest(); } + public void testAnonymousField() { doTest(); } + public void testStructAssignment() { doTest(); } + public void testStructAssignmentMultipleAssignee() { doTest(); } + public void testMultipleFieldsSameStructureCaretAtValue() { doTest(); } + public void testOneLineFieldDeclaration() { doTest(); } + public void testMultipleFields() { doTest(); } + public void testTwoSameStructures() { doTest(); } + public void testTwoSameStructuresAssignment() { doTest(); } + public void testJustAssignedVar() { doTest(); } + public void testJustInitializedVar() { doTest(); } + public void testInvalidAssignment() { doTest(); } + public void testExistingField() { doTest(); } + public void testMultipleAssignmentsLeftmost() { doTest(); } + public void testMultipleAssignmentsRightmost() { doTest(); } + public void testMultipleAssignmentsMiddle() { doTest(); } + public void testMultipleFieldsPartlyAssigned() { doTest(); } + public void testWithParens() { doTest(); } + + public void testDuplicateFields() { doTest(); } + public void testMultiReturnFunction() { doTestNoFix(); } + public void testWrongStruct() { doTestNoFix(); } + public void testExistingDeclaration() { doTestNoFix(); } + public void testNotExistingField() { doTestNoFix(); } + public void testJustAssignedVarWrongCaret() { doTestNoFix(); } + public void testJustInitializedVarWrongCaret() { doTestNoFix(); } +} +