mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-25 18:05:33 +02:00
Bug 532120: Catch by const reference ignores const placement setting
The original implementation used plain-text string manipulation of the IDocument. This changeset changes the implementation to make use of the ASTRewrite infrastructure, which automatically honors the const placement setting. Change-Id: Ib5ae9381b93ca8ab4d1ad3e16b1c3c8b1ec62d78 Signed-off-by: Felix Morgner <fmorgner@hsr.ch>
This commit is contained in:
parent
5c5ce995f6
commit
5ec251a791
3 changed files with 139 additions and 52 deletions
|
@ -11,22 +11,26 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.codan.internal.checkers.ui.quickfix;
|
package org.eclipse.cdt.codan.internal.checkers.ui.quickfix;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.eclipse.cdt.codan.internal.checkers.ui.Messages;
|
import org.eclipse.cdt.codan.internal.checkers.ui.Messages;
|
||||||
import org.eclipse.cdt.codan.ui.AbstractCodanCMarkerResolution;
|
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
|
||||||
import org.eclipse.core.resources.IMarker;
|
import org.eclipse.cdt.core.dom.ast.IASTNode.CopyStyle;
|
||||||
import org.eclipse.jface.text.IDocument;
|
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Quick fix for catch by value
|
* Quick fix for catch by value
|
||||||
*/
|
*/
|
||||||
public class CatchByConstReferenceQuickFix extends AbstractCodanCMarkerResolution {
|
public class CatchByConstReferenceQuickFix extends CatchByReferenceQuickFix {
|
||||||
@Override
|
@Override
|
||||||
public String getLabel() {
|
public String getLabel() {
|
||||||
return Messages.CatchByConstReferenceQuickFix_Message;
|
return Messages.CatchByConstReferenceQuickFix_Message;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
protected Optional<IASTDeclSpecifier> getNewDeclSpecifier(IASTSimpleDeclaration declaration) {
|
||||||
public void apply(IMarker marker, IDocument document) {
|
IASTDeclSpecifier declSpecifier = declaration.getDeclSpecifier();
|
||||||
CatchByReferenceQuickFix.applyCatchByReferenceQuickFix(marker, document, true);
|
IASTDeclSpecifier replacement = declSpecifier.copy(CopyStyle.withLocations);
|
||||||
}
|
replacement.setConst(true);
|
||||||
|
return Optional.of(replacement);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,65 +10,97 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.codan.internal.checkers.ui.quickfix;
|
package org.eclipse.cdt.codan.internal.checkers.ui.quickfix;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.eclipse.cdt.codan.internal.checkers.ui.CheckersUiActivator;
|
import org.eclipse.cdt.codan.internal.checkers.ui.CheckersUiActivator;
|
||||||
import org.eclipse.cdt.codan.internal.checkers.ui.Messages;
|
import org.eclipse.cdt.codan.internal.checkers.ui.Messages;
|
||||||
import org.eclipse.cdt.codan.ui.AbstractCodanCMarkerResolution;
|
import org.eclipse.cdt.codan.ui.AbstractAstRewriteQuickFix;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.ASTNodeFactoryFactory;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTNode.CopyStyle;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTReferenceOperator;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNodeFactory;
|
||||||
|
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.resources.IMarker;
|
||||||
import org.eclipse.jface.text.BadLocationException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
import org.eclipse.jface.text.IDocument;
|
import org.eclipse.core.runtime.NullProgressMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Quick fix for catch by value
|
* Quick fix for catch by value
|
||||||
*/
|
*/
|
||||||
public class CatchByReferenceQuickFix extends AbstractCodanCMarkerResolution {
|
public class CatchByReferenceQuickFix extends AbstractAstRewriteQuickFix {
|
||||||
@Override
|
@Override
|
||||||
public String getLabel() {
|
public String getLabel() {
|
||||||
return Messages.CatchByReferenceQuickFix_Message;
|
return Messages.CatchByReferenceQuickFix_Message;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void apply(IMarker marker, IDocument document) {
|
public void modifyAST(IIndex index, IMarker marker) {
|
||||||
applyCatchByReferenceQuickFix(marker, document, false);
|
IASTSimpleDeclaration declaration = getDeclaration(index, marker);
|
||||||
}
|
if (declaration == null) {
|
||||||
|
CheckersUiActivator.log("Could not find declaration"); //$NON-NLS-1$
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IASTTranslationUnit ast = declaration.getTranslationUnit();
|
||||||
|
ASTRewrite rewrite = ASTRewrite.create(ast);
|
||||||
|
|
||||||
|
getNewDeclSpecifier(declaration).ifPresent(ds -> rewrite.replace(declaration.getDeclSpecifier(), ds, null));
|
||||||
|
rewrite.replace(declaration.getDeclarators()[0], getNewDeclarator(declaration), null);
|
||||||
|
|
||||||
static void applyCatchByReferenceQuickFix(IMarker marker, IDocument document, boolean addConst) {
|
|
||||||
try {
|
try {
|
||||||
int left = marker.getAttribute(IMarker.CHAR_START, -1);
|
rewrite.rewriteAST().perform(new NullProgressMonitor());
|
||||||
int right = marker.getAttribute(IMarker.CHAR_END, -1);
|
} catch (CoreException e) {
|
||||||
String inStr = document.get(left, right - left);
|
|
||||||
document.replace(left, right - left, getCatchByReferenceString(inStr, addConst));
|
|
||||||
} catch (BadLocationException e) {
|
|
||||||
CheckersUiActivator.log(e);
|
CheckersUiActivator.log(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a catch by reference string from a catch by value string
|
* Calculate the new IASTDeclSpecifier for the changed declaration
|
||||||
|
* <p>
|
||||||
|
* Subclasses can override this method to provide custom behavior.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param declaration The original declaration
|
||||||
|
* @return A, possibly empty, {@link Optional} containing the new
|
||||||
|
* IASTDeclSpecifier
|
||||||
*/
|
*/
|
||||||
static private String getCatchByReferenceString(String inStr, boolean addConst) {
|
protected Optional<IASTDeclSpecifier> getNewDeclSpecifier(IASTSimpleDeclaration declaration) {
|
||||||
StringBuilder stringBuilder = new StringBuilder(inStr.length() + 10);
|
return Optional.empty();
|
||||||
if (addConst) {
|
|
||||||
stringBuilder.append("const "); //$NON-NLS-1$
|
|
||||||
}
|
|
||||||
|
|
||||||
String typename;
|
|
||||||
int space = inStr.lastIndexOf(' ');
|
|
||||||
boolean hasDeclName = space != -1;
|
|
||||||
if (hasDeclName) {
|
|
||||||
typename = inStr.substring(0,space);
|
|
||||||
} else {
|
|
||||||
typename = inStr;
|
|
||||||
}
|
|
||||||
stringBuilder.append(typename);
|
|
||||||
|
|
||||||
stringBuilder.append(" &"); //$NON-NLS-1$
|
|
||||||
|
|
||||||
if (hasDeclName) {
|
|
||||||
stringBuilder.append(" "); //$NON-NLS-1$
|
|
||||||
String declname = inStr.substring(space+1);
|
|
||||||
stringBuilder.append(declname);
|
|
||||||
}
|
|
||||||
|
|
||||||
return stringBuilder.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static IASTDeclarator getNewDeclarator(IASTSimpleDeclaration declaration) {
|
||||||
|
ICPPNodeFactory nodeFactory = ASTNodeFactoryFactory.getDefaultCPPNodeFactory();
|
||||||
|
ICPPASTReferenceOperator reference = nodeFactory.newReferenceOperator(false);
|
||||||
|
IASTDeclarator declarator = declaration.getDeclarators()[0];
|
||||||
|
IASTDeclarator replacement = declarator.copy(CopyStyle.withLocations);
|
||||||
|
replacement.addPointerOperator(reference);
|
||||||
|
return replacement;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IASTSimpleDeclaration getDeclaration(IIndex index, IMarker marker) {
|
||||||
|
try {
|
||||||
|
ITranslationUnit tu = getTranslationUnitViaEditor(marker);
|
||||||
|
IASTTranslationUnit ast = tu.getAST(index, ITranslationUnit.AST_SKIP_ALL_HEADERS);
|
||||||
|
int start = marker.getAttribute(IMarker.CHAR_START, -1);
|
||||||
|
int end = marker.getAttribute(IMarker.CHAR_END, -1);
|
||||||
|
if (start != -1 && end != -1) {
|
||||||
|
IASTNode node = ast.getNodeSelector(null).findNode(start, end - start);
|
||||||
|
while (node != null && !(node instanceof IASTSimpleDeclaration)) {
|
||||||
|
node = node.getParent();
|
||||||
|
}
|
||||||
|
return (IASTSimpleDeclaration) node;
|
||||||
|
}
|
||||||
|
} catch (CoreException e) {
|
||||||
|
CheckersUiActivator.log(e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,10 @@ package org.eclipse.cdt.codan.internal.checkers.ui.quickfix;
|
||||||
|
|
||||||
import org.eclipse.cdt.codan.internal.checkers.CatchByReference;
|
import org.eclipse.cdt.codan.internal.checkers.CatchByReference;
|
||||||
import org.eclipse.cdt.codan.ui.AbstractCodanCMarkerResolution;
|
import org.eclipse.cdt.codan.ui.AbstractCodanCMarkerResolution;
|
||||||
|
import org.eclipse.cdt.core.CCorePlugin;
|
||||||
|
import org.eclipse.cdt.core.CCorePreferenceConstants;
|
||||||
|
import org.eclipse.core.resources.ProjectScope;
|
||||||
|
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Tomasz Wesolowski
|
* @author Tomasz Wesolowski
|
||||||
|
@ -29,6 +33,16 @@ public class CatchByReferenceQuickFixTest extends QuickFixTestCase {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean setPlaceConstRight(boolean placeRight) {
|
||||||
|
IEclipsePreferences node = new ProjectScope(cproject.getProject()).getNode(CCorePlugin.PLUGIN_ID);
|
||||||
|
boolean before = node.getBoolean(CCorePreferenceConstants.PLACE_CONST_RIGHT_OF_TYPE,
|
||||||
|
CCorePreferenceConstants.DEFAULT_PLACE_CONST_RIGHT_OF_TYPE);
|
||||||
|
node.putBoolean(CCorePreferenceConstants.PLACE_CONST_RIGHT_OF_TYPE, placeRight);
|
||||||
|
CCorePreferenceConstants.getPreference(CCorePreferenceConstants.PLACE_CONST_RIGHT_OF_TYPE, cproject,
|
||||||
|
CCorePreferenceConstants.DEFAULT_PLACE_CONST_RIGHT_OF_TYPE);
|
||||||
|
return before;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AbstractCodanCMarkerResolution createQuickFix() {
|
protected AbstractCodanCMarkerResolution createQuickFix() {
|
||||||
return null; // quick fix to be chosen per test
|
return null; // quick fix to be chosen per test
|
||||||
|
@ -45,7 +59,7 @@ public class CatchByReferenceQuickFixTest extends QuickFixTestCase {
|
||||||
setQuickFix(new CatchByReferenceQuickFix());
|
setQuickFix(new CatchByReferenceQuickFix());
|
||||||
loadcode(getAboveComment());
|
loadcode(getAboveComment());
|
||||||
String result = runQuickFixOneFile();
|
String result = runQuickFixOneFile();
|
||||||
assertContainedIn("catch (C & exception)", result); //$NON-NLS-1$
|
assertContainedIn("catch (C &exception)", result); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
|
|
||||||
// struct C {
|
// struct C {
|
||||||
|
@ -59,7 +73,7 @@ public class CatchByReferenceQuickFixTest extends QuickFixTestCase {
|
||||||
setQuickFix(new CatchByReferenceQuickFix());
|
setQuickFix(new CatchByReferenceQuickFix());
|
||||||
loadcode(getAboveComment());
|
loadcode(getAboveComment());
|
||||||
String result = runQuickFixOneFile();
|
String result = runQuickFixOneFile();
|
||||||
assertContainedIn("catch (C &)", result); //$NON-NLS-1$
|
assertContainedIn("catch (C&)", result); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
|
|
||||||
// struct C {
|
// struct C {
|
||||||
|
@ -73,7 +87,25 @@ public class CatchByReferenceQuickFixTest extends QuickFixTestCase {
|
||||||
setQuickFix(new CatchByConstReferenceQuickFix());
|
setQuickFix(new CatchByConstReferenceQuickFix());
|
||||||
loadcode(getAboveComment());
|
loadcode(getAboveComment());
|
||||||
String result = runQuickFixOneFile();
|
String result = runQuickFixOneFile();
|
||||||
assertContainedIn("catch (const C & exception)", result); //$NON-NLS-1$
|
assertContainedIn("catch (const C &exception)", result); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
// struct C {
|
||||||
|
// };
|
||||||
|
// void foo() {
|
||||||
|
// try {
|
||||||
|
// } catch (C exception) {
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
public void testCatchByConstReferenceHonorsConstPlacementSettings_532120() throws Exception {
|
||||||
|
setQuickFix(new CatchByConstReferenceQuickFix());
|
||||||
|
loadcode(getAboveComment());
|
||||||
|
|
||||||
|
boolean before = setPlaceConstRight(true);
|
||||||
|
String result = runQuickFixOneFile();
|
||||||
|
setPlaceConstRight(before);
|
||||||
|
|
||||||
|
assertContainedIn("catch (C const &exception)", result); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
|
|
||||||
// struct C {
|
// struct C {
|
||||||
|
@ -87,6 +119,25 @@ public class CatchByReferenceQuickFixTest extends QuickFixTestCase {
|
||||||
setQuickFix(new CatchByConstReferenceQuickFix());
|
setQuickFix(new CatchByConstReferenceQuickFix());
|
||||||
loadcode(getAboveComment());
|
loadcode(getAboveComment());
|
||||||
String result = runQuickFixOneFile();
|
String result = runQuickFixOneFile();
|
||||||
assertContainedIn("catch (const C &)", result); //$NON-NLS-1$
|
assertContainedIn("catch (const C&)", result); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// struct C {
|
||||||
|
// };
|
||||||
|
// void foo() {
|
||||||
|
// try {
|
||||||
|
// } catch (C) {
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
public void testCatchByConstReferenceNoDeclNameHonorsConstPlacementSettings_532120() throws Exception {
|
||||||
|
setQuickFix(new CatchByConstReferenceQuickFix());
|
||||||
|
loadcode(getAboveComment());
|
||||||
|
|
||||||
|
boolean before = setPlaceConstRight(true);
|
||||||
|
String result = runQuickFixOneFile();
|
||||||
|
setPlaceConstRight(before);
|
||||||
|
|
||||||
|
assertContainedIn("catch (C const &)", result); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue