/* * 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.PsiWhiteSpace; import com.intellij.psi.util.PsiMatcherImpl; import gw.internal.gosu.parser.Expression; import gw.internal.gosu.parser.expressions.NumericLiteral; import gw.lang.parser.IStatement; import gw.lang.parser.statements.IAssignmentStatement; import gw.lang.parser.statements.IStatementList; import gw.lang.parser.statements.IWhileStatement; import gw.plugin.ij.lang.psi.api.statements.IGosuVariable; import gw.plugin.ij.lang.psi.impl.statements.GosuForEachStatementImpl; import gw.plugin.ij.lang.psi.impl.statements.GosuWhileStatementImpl; import gw.plugin.ij.lang.psi.util.GosuPsiParseUtil; import gw.plugin.ij.util.GosuBundle; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import static com.intellij.psi.util.PsiMatchers.hasClass; public class WhileToForFix extends LocalQuickFixAndIntentionActionOnPsiElement { String ident; Expression rhs; private IGosuVariable declarationEqualToZero; private IAssignmentStatement increment; public WhileToForFix(PsiElement whileStmt, String ident, Expression rhs, IGosuVariable declarationEqualToZero, IAssignmentStatement increment) { super(whileStmt); this.ident = ident; this.rhs = rhs; this.declarationEqualToZero = declarationEqualToZero; this.increment = increment; } @Override public void invoke(@NotNull Project project, @NotNull PsiFile file, @Nullable("is null when called from inspection") Editor editor, @NotNull PsiElement startElement, @NotNull PsiElement endElement) { if (!CodeInsightUtilBase.prepareFileForWrite(startElement.getContainingFile())) { return; } IWhileStatement parsedElement = ((GosuWhileStatementImpl) startElement).getParsedElement(); if (parsedElement == null) { return; } IStatement statement = parsedElement.getStatement(); IStatement[] statements = ((IStatementList) statement).getStatements(); StringBuilder forStmt = new StringBuilder(); forStmt.append("for ("); forStmt.append(ident); forStmt.append(" in 0.."); if(rhs instanceof NumericLiteral) { Object res = rhs.evaluate(); if(res instanceof Integer) { forStmt.append(((Integer)res)-1); } } else { forStmt.append("|" + rhs); } forStmt.append(") {\n"); String indent = getIndet(parsedElement, statements); for (IStatement statement1 : statements) { if (statement1 != increment) { forStmt.append(indent); forStmt.append(statement1.getLocation().getTextFromTokens()); forStmt.append("\n"); } } forStmt.append("}"); PsiElement stub = GosuPsiParseUtil.parseProgramm(forStmt.toString(), startElement, file.getManager(), null); PsiElement newForStmt = new PsiMatcherImpl(stub) .descendant(hasClass(GosuForEachStatementImpl.class)) .getElement(); if (newForStmt != null) { declarationEqualToZero.delete(); startElement.replace(newForStmt); } } private String getIndet(IWhileStatement parsedElement, IStatement[] statements) { int whileColum = parsedElement.getLocation().getColumn(); int column = statements[1].getLocation().getColumn() - whileColum; if(column < 0) { return " "; } StringBuilder out = new StringBuilder(); for(int i = 0; i <= column; i++) { out.append(" "); } return out.toString(); } private void removeVarDecl(PsiElement whileStmt, String ident) { PsiElement prev = whileStmt.getPrevSibling(); while (prev instanceof PsiWhiteSpace) { prev = prev.getPrevSibling(); } if (prev instanceof IGosuVariable && ((IGosuVariable) prev).getName().equals(ident)) { prev.delete(); } } @Override public boolean isAvailable(@NotNull Project project, @NotNull PsiFile file, @NotNull PsiElement startElement, @NotNull PsiElement endElement) { return startElement instanceof GosuWhileStatementImpl; } @NotNull @Override public String getText() { return GosuBundle.message("inspection.while.to.for"); } @NotNull @Override public String getFamilyName() { return GosuBundle.message("inspection.group.name.statement.issues"); } }