mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-22 06:02:11 +02:00
Bug 383576 - Ability to ignore codan errors using line comments
Change-Id: I806e1787fb6cc3be8865cee1d397d581ae4acd8e Signed-off-by: Alena Laskavaia <elaskavaia.cdt@gmail.com>
This commit is contained in:
parent
12843ef1d7
commit
05daa126a0
10 changed files with 176 additions and 22 deletions
|
@ -2,7 +2,7 @@ Manifest-Version: 1.0
|
|||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: %Bundle-Name
|
||||
Bundle-SymbolicName: org.eclipse.cdt.codan.core.cxx;singleton:=true
|
||||
Bundle-Version: 3.3.0.qualifier
|
||||
Bundle-Version: 3.4.0.qualifier
|
||||
Bundle-Activator: org.eclipse.cdt.codan.core.cxx.Activator
|
||||
Require-Bundle: org.eclipse.core.runtime,
|
||||
org.eclipse.cdt.core,
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<version>3.3.0-SNAPSHOT</version>
|
||||
<version>3.4.0-SNAPSHOT</version>
|
||||
<artifactId>org.eclipse.cdt.codan.core.cxx</artifactId>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
</project>
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.codan.core.cxx.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.cdt.codan.core.cxx.Activator;
|
||||
import org.eclipse.cdt.codan.core.model.AbstractCheckerWithProblemPreferences;
|
||||
import org.eclipse.cdt.codan.core.model.ICheckerInvocationContext;
|
||||
|
@ -18,6 +21,7 @@ import org.eclipse.cdt.codan.core.model.IProblem;
|
|||
import org.eclipse.cdt.codan.core.model.IProblemLocation;
|
||||
import org.eclipse.cdt.codan.core.model.IProblemLocationFactory;
|
||||
import org.eclipse.cdt.codan.core.model.IRunnableInEditorChecker;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTComment;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTImageLocation;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTMacroExpansionLocation;
|
||||
|
@ -35,7 +39,8 @@ import org.eclipse.core.runtime.CoreException;
|
|||
import org.eclipse.core.runtime.OperationCanceledException;
|
||||
|
||||
/**
|
||||
* Convenience implementation of checker that works on index-based AST of a C/C++
|
||||
* Convenience implementation of checker that works on index-based AST of a
|
||||
* C/C++
|
||||
* program.
|
||||
*
|
||||
* Clients may extend this class.
|
||||
|
@ -50,7 +55,6 @@ public abstract class AbstractIndexAstChecker extends AbstractCheckerWithProblem
|
|||
return false;
|
||||
if (!(resource instanceof IFile))
|
||||
return true;
|
||||
|
||||
processFile((IFile) resource);
|
||||
return false;
|
||||
}
|
||||
|
@ -68,7 +72,6 @@ public abstract class AbstractIndexAstChecker extends AbstractCheckerWithProblem
|
|||
context.add(modelCache);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// Run the checker only if the index is fully initialized. Otherwise it may produce
|
||||
// false positives.
|
||||
|
@ -87,8 +90,11 @@ public abstract class AbstractIndexAstChecker extends AbstractCheckerWithProblem
|
|||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see IRunnableInEditorChecker#processModel(Object, ICheckerInvocationContext)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see IRunnableInEditorChecker#processModel(Object,
|
||||
* ICheckerInvocationContext)
|
||||
*/
|
||||
@Override
|
||||
public synchronized void processModel(Object model, ICheckerInvocationContext context) {
|
||||
|
@ -98,7 +104,6 @@ public abstract class AbstractIndexAstChecker extends AbstractCheckerWithProblem
|
|||
// Otherwise the checker may produce false positives.
|
||||
if (ast.isBasedOnIncompleteIndex())
|
||||
return;
|
||||
|
||||
setContext(context);
|
||||
synchronized (context) {
|
||||
modelCache = context.get(CxxModelsCache.class);
|
||||
|
@ -110,7 +115,7 @@ public abstract class AbstractIndexAstChecker extends AbstractCheckerWithProblem
|
|||
try {
|
||||
processAst(ast);
|
||||
} finally {
|
||||
modelCache = null;
|
||||
modelCache = null;
|
||||
setContext(null);
|
||||
}
|
||||
}
|
||||
|
@ -133,6 +138,49 @@ public abstract class AbstractIndexAstChecker extends AbstractCheckerWithProblem
|
|||
reportProblem(problem, loc, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if problem should be reported, in this case it will check line
|
||||
* comments, later can add filters or what not.
|
||||
*
|
||||
* @param problem - problem kind
|
||||
* @param loc - location
|
||||
* @param args - arguments
|
||||
* @since 3.4
|
||||
*/
|
||||
@Override
|
||||
protected boolean shouldProduceProblem(IProblem problem, IProblemLocation loc, Object... args) {
|
||||
String suppressionComment = (String) getSuppressionCommentPreference(problem).getValue();
|
||||
if (suppressionComment.isEmpty())
|
||||
return true;
|
||||
List<IASTComment> lineComments = getLineCommentsForLocation(loc);
|
||||
for (IASTComment astComment : lineComments) {
|
||||
if (astComment.getRawSignature().contains(suppressionComment))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected List<IASTComment> getLineCommentsForLocation(IProblemLocation loc) {
|
||||
ArrayList<IASTComment> lineComments = new ArrayList<>();
|
||||
try {
|
||||
IASTComment[] commentsArray = modelCache.getAST().getComments();
|
||||
for (IASTComment comm : commentsArray) {
|
||||
IASTFileLocation fileLocation = comm.getFileLocation();
|
||||
if (fileLocation.getStartingLineNumber() == loc.getLineNumber()) {
|
||||
//XXX check on windows portable or os?
|
||||
String problemFile = loc.getFile().getLocation().toPortableString();
|
||||
String commentFile = fileLocation.getFileName();
|
||||
if (problemFile.equals(commentFile)) {
|
||||
lineComments.add(comm);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (OperationCanceledException | CoreException e) {
|
||||
Activator.log(e);
|
||||
}
|
||||
return lineComments;
|
||||
}
|
||||
|
||||
protected IProblemLocation getProblemLocation(IASTNode astNode) {
|
||||
IASTFileLocation astLocation = astNode.getFileLocation();
|
||||
return getProblemLocation(astNode, astLocation);
|
||||
|
|
|
@ -107,4 +107,44 @@ public class AssignmentInConditionCheckerTest extends CheckerTestCase {
|
|||
String arg = CodanProblemMarker.getProblemArgument(marker, 0);
|
||||
assertEquals("a=b", arg); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
// main() {
|
||||
// int i;
|
||||
// while (i=b()) { // @suppress("Assignment in condition")
|
||||
// }
|
||||
// }
|
||||
public void test_while2supp() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkNoErrors();
|
||||
}
|
||||
|
||||
// main() {
|
||||
// int i;
|
||||
// while (i=b()) { /* @suppress("Assignment in condition") */
|
||||
// }
|
||||
// }
|
||||
public void test_while3supp() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkNoErrors();
|
||||
}
|
||||
|
||||
// #define LOOP() while (i=b() /* @suppress("Assignment in condition") */ ) { }
|
||||
// main() {
|
||||
// int i;
|
||||
// LOOP();
|
||||
// }
|
||||
public void test_whileMacroSupp() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLine(4); // TODO: suppression does not work in macro body now
|
||||
}
|
||||
|
||||
// #define LOOP() while (i=b()) { }
|
||||
// main() {
|
||||
// int i;
|
||||
// LOOP(); // err
|
||||
// }
|
||||
public void test_whileMacro() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLine(4);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ public abstract class AbstractChecker implements IChecker {
|
|||
* internationalization)
|
||||
*/
|
||||
public void reportProblem(String id, IFile file, int lineNumber, Object... args) {
|
||||
getProblemReporter().reportProblem(id, createProblemLocation(file, lineNumber), args);
|
||||
reportProblem(id, createProblemLocation(file, lineNumber), args);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -103,7 +103,7 @@ public abstract class AbstractChecker implements IChecker {
|
|||
* - line
|
||||
*/
|
||||
public void reportProblem(String id, IFile file, int lineNumber) {
|
||||
getProblemReporter().reportProblem(id, createProblemLocation(file, lineNumber), EMPTY_OBJECT_ARRAY);
|
||||
reportProblem(id, createProblemLocation(file, lineNumber), EMPTY_OBJECT_ARRAY);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.eclipse.cdt.codan.core.param.LaunchModeProblemPreference;
|
|||
import org.eclipse.cdt.codan.core.param.ListProblemPreference;
|
||||
import org.eclipse.cdt.codan.core.param.MapProblemPreference;
|
||||
import org.eclipse.cdt.codan.core.param.RootProblemPreference;
|
||||
import org.eclipse.cdt.codan.core.param.SuppressionCommentProblemPreference;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
|
||||
|
@ -43,6 +44,7 @@ public abstract class AbstractCheckerWithProblemPreferences extends AbstractChec
|
|||
CheckerLaunchMode.RUN_ON_DEMAND,
|
||||
CheckerLaunchMode.RUN_ON_FULL_BUILD,
|
||||
CheckerLaunchMode.RUN_ON_INC_BUILD);
|
||||
getSuppressionCommentPreference(problem).setValue(SuppressionCommentProblemPreference.generateDefaultComment(problem));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -65,10 +67,19 @@ public abstract class AbstractCheckerWithProblemPreferences extends AbstractChec
|
|||
return getTopLevelPreference(problem).getLaunchModePreference();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param problem - problem for which preference is extracted
|
||||
* @return suppression comment preference
|
||||
* @since 4.0
|
||||
*/
|
||||
public SuppressionCommentProblemPreference getSuppressionCommentPreference(IProblem problem) {
|
||||
return getTopLevelPreference(problem).getSuppressionCommentPreference();
|
||||
}
|
||||
|
||||
/**
|
||||
* User can scope out some resources for this checker. Checker can use this
|
||||
* call to test if it should run on this resource at all or not. Test should
|
||||
* be done within processResource method not in enabledInContext.
|
||||
* be done within processResource method.
|
||||
* This test uses user "scope" preference for the all problems that this
|
||||
* checker can produce.
|
||||
*
|
||||
|
@ -109,10 +120,7 @@ public abstract class AbstractCheckerWithProblemPreferences extends AbstractChec
|
|||
|
||||
@Override
|
||||
public void reportProblem(String problemId, IProblemLocation loc, Object... args) {
|
||||
if (shouldProduceProblem(getProblemById(problemId, loc.getFile()),
|
||||
loc.getFile().getFullPath())) {
|
||||
super.reportProblem(problemId, loc, args);
|
||||
}
|
||||
reportProblem(getProblemById(problemId, loc.getFile()), loc, args);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -125,10 +133,25 @@ public abstract class AbstractCheckerWithProblemPreferences extends AbstractChec
|
|||
* @since 2.0
|
||||
*/
|
||||
public void reportProblem(IProblem pr, IProblemLocation loc, Object... args) {
|
||||
if (shouldProduceProblem(pr, loc.getFile().getFullPath()))
|
||||
if (shouldProduceProblem(pr, loc, args))
|
||||
super.reportProblem(pr.getId(), loc, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if problem should be reported, this implementation only checks
|
||||
* suppression by scope, but subclass should override,
|
||||
* to implement any other filtering, such as suppression by filter or by comment.
|
||||
* Call super to check for scope suppression as well.
|
||||
*
|
||||
* @param problem - problem kind
|
||||
* @param loc - location
|
||||
* @param args - arguments
|
||||
* @since 4.0
|
||||
*/
|
||||
protected boolean shouldProduceProblem(IProblem problem, IProblemLocation loc, Object... args) {
|
||||
return shouldProduceProblem(problem, loc.getFile().getFullPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a parameter
|
||||
*
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.eclipse.osgi.util.NLS;
|
|||
*/
|
||||
class Messages extends NLS {
|
||||
public static String FileScopeProblemPreference_Label;
|
||||
public static String SuppressionCommentProblemPreference_Label;
|
||||
|
||||
static {
|
||||
NLS.initializeMessages(Messages.class.getName(), Messages.class);
|
||||
|
|
|
@ -10,3 +10,4 @@
|
|||
# IBM Corporation
|
||||
###############################################################################
|
||||
FileScopeProblemPreference_Label=Exclusion and Inclusion
|
||||
SuppressionCommentProblemPreference_Label=Suppression Comment
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.codan.core.param;
|
||||
|
||||
|
||||
/**
|
||||
* Common problem preference root for most of the codan problems
|
||||
*
|
||||
|
@ -24,26 +23,34 @@ public class RootProblemPreference extends MapProblemPreference {
|
|||
public static final String KEY = PARAM;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
* Default constructor
|
||||
*/
|
||||
public RootProblemPreference() {
|
||||
super(KEY, ""); //$NON-NLS-1$
|
||||
addChildDescriptor(new FileScopeProblemPreference());
|
||||
addChildDescriptor(new LaunchModeProblemPreference());
|
||||
addChildDescriptor(new SuppressionCommentProblemPreference());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return scope preference
|
||||
*/
|
||||
public FileScopeProblemPreference getScopePreference() {
|
||||
return (FileScopeProblemPreference) getChildDescriptor(
|
||||
FileScopeProblemPreference.KEY);
|
||||
return (FileScopeProblemPreference) getChildDescriptor(FileScopeProblemPreference.KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return launch mode
|
||||
* @return launch mode preference
|
||||
*/
|
||||
public LaunchModeProblemPreference getLaunchModePreference() {
|
||||
return (LaunchModeProblemPreference) getChildDescriptor(LaunchModeProblemPreference.KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return suppression comment preference
|
||||
* @since 4.0
|
||||
*/
|
||||
public SuppressionCommentProblemPreference getSuppressionCommentPreference() {
|
||||
return (SuppressionCommentProblemPreference) getChildDescriptor(SuppressionCommentProblemPreference.KEY);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Alena Laskavaia
|
||||
* 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:
|
||||
* Alena Laskavaia - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.codan.core.param;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import org.eclipse.cdt.codan.core.model.IProblemWorkingCopy;
|
||||
|
||||
/**
|
||||
* Preference for suppressing a problem using code comments. Automatically added to all problems.
|
||||
* @since 4.0
|
||||
*/
|
||||
public class SuppressionCommentProblemPreference extends BasicProblemPreference implements IProblemPreference {
|
||||
public static final String KEY = "suppression_comment"; //$NON-NLS-1$;
|
||||
// Even if using English name it is really a keyword, so no externalizable.
|
||||
public static final String KEYWORD = "@suppress(\"{0}\")"; //$NON-NLS-1$;
|
||||
|
||||
public SuppressionCommentProblemPreference() {
|
||||
super(KEY, Messages.SuppressionCommentProblemPreference_Label, PreferenceType.TYPE_STRING);
|
||||
}
|
||||
|
||||
public static String generateDefaultComment(IProblemWorkingCopy problem) {
|
||||
String name = problem.getName();
|
||||
return MessageFormat.format(KEYWORD, name);
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue