/*******************************************************************************
* Copyright (c) 2011 Gil Barash
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Gil Barash - Initial implementation
*******************************************************************************/
package org.eclipse.cdt.codan.internal.checkers.ui.quickfix;
import org.eclipse.cdt.codan.core.cxx.CxxAstUtils;
import org.eclipse.cdt.codan.internal.checkers.ui.CheckersUiActivator;
import org.eclipse.cdt.codan.ui.AbstractAstRewriteQuickFix;
import org.eclipse.cdt.core.dom.ast.IASTBreakStatement;
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTNodeSelector;
import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IASTSwitchStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IRegion;
import org.eclipse.ltk.core.refactoring.Change;
public class CaseBreakQuickFixBreak extends AbstractAstRewriteQuickFix {
@Override
public boolean isApplicable(IMarker marker) {
int line = marker.getAttribute(IMarker.LINE_NUMBER, -1) - 1;
if (line < 0)
return false;
return true;
}
public String getLabel() {
return Messages.CaseBreakQuickFixBreak_Label;
}
protected IASTStatement getStmtBeforeBreak(IMarker marker, IASTTranslationUnit ast) throws BadLocationException {
int line = marker.getAttribute(IMarker.LINE_NUMBER, -1) - 1;
if (line < 0)
return null;
IRegion lineInformation = getDocument().getLineInformation(line);
IASTNodeSelector nodeSelector = ast.getNodeSelector(null);
IASTNode containedNode = nodeSelector.findFirstContainedNode(lineInformation.getOffset(), lineInformation.getLength());
IASTNode beforeBreakNode = null;
if (containedNode != null)
beforeBreakNode = CxxAstUtils.getInstance().getEnclosingStatement(containedNode);
else
beforeBreakNode = nodeSelector.findEnclosingNode(lineInformation.getOffset(), lineInformation.getLength());
if (beforeBreakNode instanceof IASTCompoundStatement) {
while (beforeBreakNode != null) {
if (beforeBreakNode.getParent() instanceof IASTCompoundStatement
&& beforeBreakNode.getParent().getParent() instanceof IASTSwitchStatement) {
if (beforeBreakNode instanceof IASTCompoundStatement) {
IASTStatement[] statements = ((IASTCompoundStatement) beforeBreakNode).getStatements();
return statements[statements.length - 1]; // return last one
}
return (IASTStatement) beforeBreakNode;
}
beforeBreakNode = beforeBreakNode.getParent();
}
}
if (beforeBreakNode instanceof IASTStatement)
return (IASTStatement) beforeBreakNode;
return null;
}
@Override
public void modifyAST(IIndex index, IMarker marker) {
try {
IASTTranslationUnit ast = getTranslationUnitViaEditor(marker).getAST(index, ITranslationUnit.AST_SKIP_INDEXED_HEADERS);
IASTStatement beforeBreak = getStmtBeforeBreak(marker, ast);
if (beforeBreak.getParent() instanceof IASTCompoundStatement) {
IASTCompoundStatement enclosingStatement = (IASTCompoundStatement) beforeBreak.getParent();
IASTStatement after = getAfterStatement(beforeBreak);
ASTRewrite r = ASTRewrite.create(enclosingStatement.getTranslationUnit());
IASTBreakStatement breakStatement = ast.getASTNodeFactory().newBreakStatement();
r.insertBefore(enclosingStatement, after, breakStatement, null);
Change c = r.rewriteAST();
c.perform(new NullProgressMonitor());
}
} catch (CoreException e) {
CheckersUiActivator.log(e);
} catch (BadLocationException e) {
CheckersUiActivator.log(e);
}
}
private IASTStatement getAfterStatement(IASTStatement beforeBreak) {
IASTCompoundStatement enclosingStatement = (IASTCompoundStatement) beforeBreak.getParent();
IASTStatement after = null;
IASTStatement[] statements = enclosingStatement.getStatements();
for (int i = 0; i < statements.length; i++) {
IASTStatement st = statements[i];
if (st == beforeBreak) {
if (i < statements.length - 1) {
after = statements[i + 1];
break;
}
}
}
return after;
}
}