1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Bug 511229 - RFE: Add quick fixes for some basic gcc errors

- change codanMarkerResolution schema to support translatable
  regex statements for matching
- bump cdt.codan.ui version
- add additional codanMarkerResolution extensions to codan.checkers.ui
  to handle some basic gcc error messages with quick fixes
- add QuickFixAddSemicolon, QuickFixRenameMember,
  QuickFixUseDotOperator, and QuickFixUsePointer classes
- add new QuickFixMessages
- add plugin.properties to cdt.codan.checkers.ui to allow the quick
  fix regex matchers to be translated in the future
- change the generic error message for gcc error parser so that the
  column is reported as the problem variable (useful for certain
  quick fix resolutions)
- bump up cdt.core

Change-Id: Ibb24c1a79c4d91ead3fc629ea3d4e7425b4e7f23
This commit is contained in:
Jeff Johnston 2017-01-27 13:02:05 -05:00 committed by Gerrit Code Review @ Eclipse.org
parent e93de453f8
commit 7d0117d24e
17 changed files with 441 additions and 9 deletions

View file

@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Bundle-SymbolicName: org.eclipse.cdt.codan.checkers.ui;singleton:=true
Bundle-Version: 3.2.0.qualifier
Bundle-Version: 3.2.1.qualifier
Bundle-Activator: org.eclipse.cdt.codan.internal.checkers.ui.CheckersUiActivator
Require-Bundle: org.eclipse.core.resources,
org.eclipse.core.runtime,
@ -19,6 +19,7 @@ Require-Bundle: org.eclipse.core.resources,
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-Vendor: %Bundle-Vendor
Bundle-Localization: plugin
Export-Package: org.eclipse.cdt.codan.internal.checkers.ui;x-internal:=true,
org.eclipse.cdt.codan.internal.checkers.ui.quickfix;x-friends:="org.eclipse.cdt.codan.checkers.ui.test"

View file

@ -0,0 +1,6 @@
GCCFixitNoMember.errormsg=\u2018(.*)\u2019 has no member named \u2018(.*)\u2019.*did you mean \u2018(.*)\u2019.*
GCCFixitMissingSemicolon.errormsg=expected \u2018;\u2019 before \u2018(.*)\u2019.*
GCCFixitNoPointerOpCPP=request for member \u2018.*\u2019 in \u2018(.*)\u2019, which is of pointer type \u2018.*\u2019.*maybe you meant to use \u2018->\u2019.*
GCCFixitNoPointerOperator.errormsg=\u2018(.*)\u2019 is a pointer(.*)did you mean to use \u2018->\u2019.*
GCCFixitInvalidPtrTypeCPP=base operand of \u2018->\u2019 has non-pointer type \u2018(.*)\u2019.*
GCCFixitInvalidPtrStruct.errormsg=invalid type argument of \u2018->\u2019.*have \u2018struct (.*)\u2019.*

View file

@ -31,6 +31,30 @@
class="org.eclipse.cdt.codan.internal.checkers.ui.quickfix.QuickFixCreateLocalVariable"
messagePattern="`(.*)' undeclared \(first use in this function\)">
</resolution>
<resolution
class="org.eclipse.cdt.codan.internal.checkers.ui.quickfix.QuickFixRenameMember"
messagePattern="%GCCFixitNoMember.errormsg">
</resolution>
<resolution
class="org.eclipse.cdt.codan.internal.checkers.ui.quickfix.QuickFixAddSemicolon"
messagePattern="%GCCFixitMissingSemicolon.errormsg">
</resolution>
<resolution
class="org.eclipse.cdt.codan.internal.checkers.ui.quickfix.QuickFixUsePointer"
messagePattern="%GCCFixitNoPointerOpCPP">
</resolution>
<resolution
class="org.eclipse.cdt.codan.internal.checkers.ui.quickfix.QuickFixUsePointer"
messagePattern="%GCCFixitNoPointerOperator.errormsg">
</resolution>
<resolution
class="org.eclipse.cdt.codan.internal.checkers.ui.quickfix.QuickFixUseDotOperator"
messagePattern="%GCCFixitInvalidPtrTypeCPP">
</resolution>
<resolution
class="org.eclipse.cdt.codan.internal.checkers.ui.quickfix.QuickFixUseDotOperator"
messagePattern="%GCCFixitInvalidPtrStruct.errormsg">
</resolution>
<resolution
class="org.eclipse.cdt.codan.internal.checkers.ui.quickfix.QuickFixCreateField"
problemId="org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem">

View file

@ -11,7 +11,7 @@
<relativePath>../../pom.xml</relativePath>
</parent>
<version>3.2.0-SNAPSHOT</version>
<version>3.2.1-SNAPSHOT</version>
<artifactId>org.eclipse.cdt.codan.checkers.ui</artifactId>
<packaging>eclipse-plugin</packaging>
</project>

View file

@ -0,0 +1,178 @@
/*******************************************************************************
* Copyright (c) 2017 Red Hat Inc.
* 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:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.internal.checkers.ui.quickfix;
import org.eclipse.cdt.codan.internal.checkers.ui.CheckersUiActivator;
import org.eclipse.cdt.codan.ui.AbstractAstRewriteQuickFix;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
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.jface.text.BadLocationException;
import org.eclipse.jface.text.FindReplaceDocumentAdapter;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
public class QuickFixAddSemicolon extends AbstractAstRewriteQuickFix {
@Override
public String getLabel() {
return QuickFixMessages.QuickFixAddSemicolon_add_semicolon;
}
@Override
public void modifyAST(IIndex index, IMarker marker) {
IASTTranslationUnit ast;
try {
ITranslationUnit tu = getTranslationUnitViaEditor(marker);
ast = tu.getAST(index, ITranslationUnit.AST_SKIP_INDEXED_HEADERS);
} catch (CoreException e) {
CheckersUiActivator.log(e);
return;
}
IASTNode astNode = null;
if (isCodanProblem())
return;
// We need to back up in the file
// Start by finding the original reported position and line number
int lineNum = marker.getAttribute(IMarker.LINE_NUMBER, 0) - 1;
if (lineNum < 1) {
return;
}
IDocument document = getDocument();
int lineOffset;
int lineLength;
try {
lineOffset = document.getLineOffset(lineNum);
lineLength = document.getLineLength(lineNum);
} catch (BadLocationException e2) {
return;
}
// find the position of the reported token
int pos = getOffset(marker, getDocument());
String name = null;
try {
name = getProblemArgument(marker, 0);
} catch (Exception e) {
return;
}
if (name == null)
return;
FindReplaceDocumentAdapter dad = new FindReplaceDocumentAdapter(getDocument());
IRegion region;
try {
region = dad.find(pos, name,
/* forwardSearch */true, /* caseSensitive */true,
/* wholeWord */false, /* regExSearch */false);
} catch (BadLocationException e) {
return;
}
if (region == null)
return;
// now we have the offset
int offset = region.getOffset();
IASTNode prevNode = null;
// see if there are previous nodes on same line
if (lineOffset < offset) {
astNode = getASTFirstContainedNodeFromPosition(ast, lineOffset, lineLength);
if (astNode != null) {
IASTFileLocation fileLoc = astNode.getFileLocation();
if (fileLoc == null)
return;
int length = lineLength;
while (fileLoc.getNodeOffset() < offset) {
prevNode = astNode;
astNode = getASTFirstContainedNodeFromPosition(ast, fileLoc.getNodeOffset() + fileLoc.getNodeLength(), length);
fileLoc = astNode.getFileLocation();
if (fileLoc == null)
return;
length -= fileLoc.getNodeLength();
}
}
}
// if we didn't find the previous node on the same line, go back a line at a time and find last node on line
while (prevNode == null) {
lineNum -= 1;
if (lineNum < 0)
return; // don't bother once we have reached start of file
try {
lineOffset = document.getLineOffset(lineNum);
lineLength = document.getLineLength(lineNum);
} catch (BadLocationException e) {
return;
}
int x = lineOffset;
int leftover = lineLength;
// get a node at a time from line and keep track of last node found
while (x < lineOffset + lineLength) {
astNode = getASTFirstContainedNodeFromPosition(ast, x, leftover);
if (astNode == null)
break;
prevNode = astNode;
IASTFileLocation fileLoc = astNode.getFileLocation();
if (fileLoc == null)
break;
x += fileLoc.getNodeLength();
leftover -= fileLoc.getNodeLength();
}
}
IASTFileLocation location = prevNode.getFileLocation();
if (location == null)
return;
int replacementLoc = location.getNodeOffset() + location.getNodeLength();
// in the case of a Problem statement, it might include \n or \r\n as part
// of the node, so we must just assume the semi-colon belongs at the end of
// the line
if (replacementLoc == offset)
replacementLoc -= System.lineSeparator().length();
try {
// insert the semi-colon
document.replace(replacementLoc, 0, ";"); //$NON-NLS-1$
} catch (BadLocationException e1) {
return;
}
try {
// remove marker now that has been dealt with
marker.delete();
} catch (CoreException e) {
CheckersUiActivator.log(e);
}
}
/**
* @param ast
* @param charStart
* @param length
* @return
*/
private IASTNode getASTFirstContainedNodeFromPosition(IASTTranslationUnit ast, final int charStart, final int length) {
IASTNode node = ast.getNodeSelector(null).findFirstContainedNode(charStart, length);
return node;
}
}

View file

@ -19,6 +19,11 @@ public class QuickFixMessages extends NLS {
public static String QuickFixCreateField_create_field;
public static String QuickFixCreateLocalVariable_create_local_variable;
public static String QuickFixCreateParameter_create_parameter;
public static String QuickFixRenameMember_rename_member;
public static String QuickFixAddSemicolon_add_semicolon;
public static String QuickFixUsePointer_replace_dot;
public static String QuickFixUseDotOperator_replace_ptr;
public static String QuickFixForFixit_apply_fixit;
static {
NLS.initializeMessages(QuickFixMessages.class.getName(), QuickFixMessages.class);

View file

@ -13,4 +13,9 @@ CaseBreakQuickFixComment_Label=Add suppressing comment
QuickFixCreateClass_CreateNewClass=Create new class
QuickFixCreateField_create_field=Create field
QuickFixCreateLocalVariable_create_local_variable=Create local variable
QuickFixCreateParameter_create_parameter=Create parameter
QuickFixCreateParameter_create_parameter=Create parameter
QuickFixRenameMember_rename_member=Rename to suggested member
QuickFixAddSemicolon_add_semicolon=Add semicolon
QuickFixUsePointer_replace_dot=Replace '.' with '->'
QuickFixUseDotOperator_replace_ptr=Replace '->' with '.'
QuickFixForFixit_apply_fixit=Apply compiler recommended fix-it

View file

@ -0,0 +1,75 @@
/*******************************************************************************
* Copyright (c) 2017 Red Hat Inc.
* 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:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.internal.checkers.ui.quickfix;
import org.eclipse.cdt.codan.internal.checkers.ui.CheckersUiActivator;
import org.eclipse.cdt.codan.internal.core.model.CodanProblemMarker;
import org.eclipse.cdt.codan.ui.AbstractAstRewriteQuickFix;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.INodeFactory;
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.ltk.core.refactoring.Change;
public class QuickFixRenameMember extends AbstractAstRewriteQuickFix {
@Override
public String getLabel() {
return QuickFixMessages.QuickFixRenameMember_rename_member;
}
@Override
public void modifyAST(IIndex index, IMarker marker) {
IASTTranslationUnit ast;
try {
ITranslationUnit tu = getTranslationUnitViaEditor(marker);
ast = tu.getAST(index, ITranslationUnit.AST_SKIP_INDEXED_HEADERS);
} catch (CoreException e) {
CheckersUiActivator.log(e);
return;
}
IASTName astName;
if (isCodanProblem()) {
astName = getASTNameFromMarker(marker, ast);
} else {
astName = getAstNameFromProblemArgument(marker, ast, 1);
}
if (astName == null) {
return;
}
ASTRewrite r = ASTRewrite.create(ast);
INodeFactory factory = ast.getASTNodeFactory();
String[] args = CodanProblemMarker.getProblemArguments(marker);
if (args == null || args.length < 3)
return;
IASTName newName = factory.newName(args[2]);
r.replace(astName, newName, null);
Change c = r.rewriteAST();
try {
c.perform(new NullProgressMonitor());
} catch (CoreException e) {
CheckersUiActivator.log(e);
return;
}
try {
marker.delete();
} catch (CoreException e) {
CheckersUiActivator.log(e);
}
}
}

View file

@ -0,0 +1,64 @@
/*******************************************************************************
* Copyright (c) 2017 Red Hat Inc.
* 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:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.internal.checkers.ui.quickfix;
import org.eclipse.cdt.codan.internal.checkers.ui.CheckersUiActivator;
import org.eclipse.cdt.codan.ui.AbstractCodanCMarkerResolution;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.FindReplaceDocumentAdapter;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
public class QuickFixUseDotOperator extends AbstractCodanCMarkerResolution {
@Override
public String getLabel() {
return QuickFixMessages.QuickFixUseDotOperator_replace_ptr;
}
@Override
public void apply(IMarker marker, IDocument document) {
int lineNum = marker.getAttribute(IMarker.LINE_NUMBER, -1);
try {
if (lineNum >= 0) {
FindReplaceDocumentAdapter dad = new FindReplaceDocumentAdapter(document);
int lineOffset = document.getLineOffset(lineNum - 1);
int columnOffset = getColumnOffset(marker);
IRegion region;
try {
region = dad.find(lineOffset + columnOffset, "->", //$NON-NLS-1$
/* forwardSearch */true, /* caseSensitive */true,
/* wholeWord */true, /* regExSearch */false);
document.replace(region.getOffset(), 2, "."); //$NON-NLS-1$
} catch (BadLocationException e) {
return;
}
}
marker.delete();
} catch (BadLocationException | CoreException e) {
CheckersUiActivator.log(e);
}
}
private int getColumnOffset(IMarker marker) {
// Get the column offset from the problem.variable attribute which is set for
// the generic C/C++ error message in cdt.core.
String offset = marker.getAttribute("problem.variable", "1:"); //$NON-NLS-1$ //$NON-NLS-2$
if (offset.charAt(offset.length() - 1) == ':') {
String strToParse = offset.substring(0, offset.length() - 1);
return Integer.parseInt(strToParse) - 1;
}
return 0;
}
}

View file

@ -0,0 +1,64 @@
/*******************************************************************************
* Copyright (c) 2017 Red Hat Inc.
* 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:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.codan.internal.checkers.ui.quickfix;
import org.eclipse.cdt.codan.internal.checkers.ui.CheckersUiActivator;
import org.eclipse.cdt.codan.ui.AbstractCodanCMarkerResolution;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.FindReplaceDocumentAdapter;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
public class QuickFixUsePointer extends AbstractCodanCMarkerResolution {
@Override
public String getLabel() {
return QuickFixMessages.QuickFixUsePointer_replace_dot;
}
@Override
public void apply(IMarker marker, IDocument document) {
int lineNum = marker.getAttribute(IMarker.LINE_NUMBER, -1);
try {
if (lineNum >= 0) {
FindReplaceDocumentAdapter dad = new FindReplaceDocumentAdapter(document);
int lineOffset = document.getLineOffset(lineNum - 1);
int columnOffset = getColumnOffset(marker);
IRegion region;
try {
region = dad.find(lineOffset + columnOffset - 1, ".", //$NON-NLS-1$
/* forwardSearch */true, /* caseSensitive */true,
/* wholeWord */true, /* regExSearch */false);
document.replace(region.getOffset(), 1, "->"); //$NON-NLS-1$
} catch (BadLocationException e) {
return;
}
}
marker.delete();
} catch (BadLocationException | CoreException e) {
CheckersUiActivator.log(e);
}
}
private int getColumnOffset(IMarker marker) {
// Get the column offset from the problem.variable attribute which is set for
// the generic C/C++ error message in cdt.core.
String offset = marker.getAttribute("problem.variable", "1:"); //$NON-NLS-1$ //$NON-NLS-2$
if (offset.charAt(offset.length() - 1) == ':') {
String strToParse = offset.substring(0, offset.length() - 1);
return Integer.parseInt(strToParse) - 1;
}
return 0;
}
}

View file

@ -102,5 +102,5 @@ public abstract class AbstractAstRewriteQuickFix extends AbstractCodanCMarkerRes
}
astName = getASTNameFromPositions(ast, region.getOffset(), region.getLength());
return astName;
}
}
}

View file

@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Bundle-SymbolicName: org.eclipse.cdt.codan.ui; singleton:=true
Bundle-Version: 3.2.0.qualifier
Bundle-Version: 3.2.1.qualifier
Bundle-Activator: org.eclipse.cdt.codan.internal.ui.CodanUIActivator
Bundle-Vendor: %Bundle-Vendor
Require-Bundle: org.eclipse.cdt.codan.core,

View file

@ -11,7 +11,7 @@
<relativePath>../../pom.xml</relativePath>
</parent>
<version>3.2.0-SNAPSHOT</version>
<version>3.2.1-SNAPSHOT</version>
<artifactId>org.eclipse.cdt.codan.ui</artifactId>
<packaging>eclipse-plugin</packaging>
</project>

View file

@ -80,6 +80,9 @@ If this is not codan problem (for example gcc error), it can be ommitted. Messag
<documentation>
If problem id is not enought to identity the fix messagePattern can be used to apply fix for given message
</documentation>
<appinfo>
<meta.attribute translatable="true"/>
</appinfo>
</annotation>
</attribute>
</complexType>

View file

@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.cdt.core; singleton:=true
Bundle-Version: 6.3.0.qualifier
Bundle-Version: 6.3.1.qualifier
Bundle-Activator: org.eclipse.cdt.core.CCorePlugin
Bundle-Vendor: %providerName
Bundle-Localization: plugin

View file

@ -169,7 +169,14 @@
<pattern description-expr="$4" eat-processed-line="true" file-expr="$1" line-expr="$2" regex="%CDTGNUCErrorParser.regex.WarningConflictingTypesFor" severity="Warning" variable-expr="$5"/>
<pattern description-expr="$5" eat-processed-line="true" file-expr="$1" line-expr="$2" regex="%CDTGNULinkerErrorParser.regex.WarningDangerousFunction" severity="Warning" variable-expr="$6"/>
<pattern description-expr="$4" eat-processed-line="true" file-expr="$1" line-expr="$2" regex="%CDTGNUCErrorParser.regex.InstantiatedFromHere" severity="Info"/>
<pattern description-expr="$7" eat-processed-line="true" file-expr="$1" line-expr="$2" regex="%CDTGNUCErrorParser.regex.GenericError" severity="Error"/>
<pattern
description-expr="$7"
eat-processed-line="true"
file-expr="$1"
line-expr="$2"
regex="%CDTGNUCErrorParser.regex.GenericError"
severity="Error"
variable-expr="$3"/>
<pattern description-expr="$7" eat-processed-line="true" file-expr="$1" line-expr="$2" regex="%CDTGNUCErrorParser.regex.GenericWarning" severity="Warning"/>
<pattern description-expr="$9" eat-processed-line="true" file-expr="$1" line-expr="$2" regex="%CDTGNUCErrorParser.regex.GenericInfo" severity="Info"/>
<pattern description-expr="$4" eat-processed-line="true" file-expr="$1" line-expr="$2" regex="%CDTGNUCErrorParser.regex.OtherError" severity="Error"/>

View file

@ -11,7 +11,7 @@
<relativePath>../../pom.xml</relativePath>
</parent>
<version>6.3.0-SNAPSHOT</version>
<version>6.3.1-SNAPSHOT</version>
<artifactId>org.eclipse.cdt.core</artifactId>
<packaging>eclipse-plugin</packaging>
</project>