/* * Copyright 2013 Guidewire Software, Inc. */ package gw.plugin.ij.intentions; import com.intellij.codeInsight.CodeInsightUtilBase; import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement; 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.codeStyle.CodeStyleManager; import com.intellij.psi.util.PsiMatcherImpl; import gw.lang.parser.statements.IClassFileStatement; import gw.lang.reflect.gs.IGosuClass; import gw.plugin.ij.lang.GosuTokenTypes; import gw.plugin.ij.lang.psi.IGosuPsiElement; import gw.plugin.ij.lang.psi.api.statements.IGosuStatementList; import gw.plugin.ij.lang.psi.api.statements.typedef.IGosuMethod; import gw.plugin.ij.lang.psi.impl.AbstractGosuClassFileImpl; import gw.plugin.ij.lang.psi.impl.GosuClassParseData; import gw.plugin.ij.lang.psi.util.GosuPsiParseUtil; import gw.plugin.ij.lang.psi.util.LeafPsiMatcher; import gw.plugin.ij.util.ClassLord; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.LinkedHashMap; import java.util.Map; import static com.intellij.psi.util.PsiMatchers.hasClass; import static com.intellij.psi.util.PsiMatchers.hasText; import static gw.plugin.ij.util.ClassLord.purgeClassName; import static java.lang.String.format; public class ChangeMethodTypeFix extends LocalQuickFixAndIntentionActionOnPsiElement { private final String typeName; public ChangeMethodTypeFix(@Nullable PsiElement element, @NotNull String typeName) { super(element); this.typeName = typeName; } @Override public void invoke(@NotNull Project project, @NotNull PsiFile file, @Nullable Editor editor, @NotNull PsiElement startElement, @NotNull PsiElement endElement) { if( !CodeInsightUtilBase.prepareFileForWrite(startElement.getContainingFile()) ) { return; } IGosuStatementList stmtList = (IGosuStatementList) new PsiMatcherImpl(startElement) .ancestor(hasClass(IGosuMethod.class)) .descendant(hasClass(IGosuStatementList.class)) .getElement(); if (stmtList == null) { return; } String typeName = this.typeName; Map<String, String> imports = new LinkedHashMap<String, String>(); typeName = ClassLord.simplifyTypes(typeName, (IGosuPsiElement) file, true, imports); PsiElement returnLiteral = GosuPsiParseUtil.parseTypeLiteral(typeName, file); PsiElement func = stmtList.getParent(); func.getNode().addLeaf(GosuTokenTypes.TT_OP_colon, ":", stmtList.getNode()); func.addBefore(returnLiteral, stmtList); for (String imp : imports.values()) { ClassLord.doImportAndStick(imp, file); } PsiElement closingBrace = new LeafPsiMatcher(startElement) .ancestor(hasClass(IGosuMethod.class)) .descendant(hasText(")")).getElement(); CodeStyleManager styleManager = CodeStyleManager.getInstance(project); if (closingBrace != null) { styleManager.reformatText(file, closingBrace.getTextOffset() + closingBrace.getTextLength(), stmtList.getTextOffset()); } } private PsiFile getFile() { return getStartElement().getContainingFile(); } public IGosuClass getGosuClass() { PsiFile file = getFile(); if( !(file instanceof AbstractGosuClassFileImpl) ) { return null; } AbstractGosuClassFileImpl gosuClassFile = (AbstractGosuClassFileImpl) file; GosuClassParseData parseData = gosuClassFile.getParseData(); if (parseData != null) { IClassFileStatement classFileStatement = parseData.getClassFileStatement(); if (classFileStatement != null) { return classFileStatement.getGosuClass(); } } return null; } @NotNull @Override public String getText() { return format("Change method return type to '%s'", purgeClassName(typeName)); } @NotNull @Override public String getFamilyName() { return "Change method return type"; } }