1
0
Fork 0
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:
Alena Laskavaia 2016-01-07 23:12:51 -05:00 committed by Elena Laskavaia
parent 12843ef1d7
commit 05daa126a0
10 changed files with 176 additions and 22 deletions

View file

@ -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,

View file

@ -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>

View file

@ -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);

View file

@ -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);
}
}

View file

@ -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);
}
/**

View file

@ -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
*

View file

@ -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);

View file

@ -10,3 +10,4 @@
# IBM Corporation
###############################################################################
FileScopeProblemPreference_Label=Exclusion and Inclusion
SuppressionCommentProblemPreference_Label=Suppression Comment

View file

@ -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);
}
}

View file

@ -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);
}
}