mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-05 08:46:02 +02:00
started adding support for multiple instance problems
This commit is contained in:
parent
2122fc3c99
commit
527ee4ff5a
13 changed files with 265 additions and 90 deletions
|
@ -84,6 +84,7 @@
|
|||
description="%problem.description.NamingConventionFunction"
|
||||
id="org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker"
|
||||
messagePattern="%problem.messagePattern.NamingConventionFunction"
|
||||
multiple="true"
|
||||
name="%problem.name.NamingConventionFunction">
|
||||
</problem>
|
||||
</checker>
|
||||
|
|
|
@ -22,6 +22,7 @@ public class CheckersMessages extends NLS {
|
|||
public static String CaseBreakChecker_LastCaseDescription;
|
||||
public static String CatchByReference_ReportForUnknownType;
|
||||
public static String NamingConventionFunctionChecker_LabelNamePattern;
|
||||
public static String NamingConventionFunctionChecker_ParameterMethods;
|
||||
public static String ReturnChecker_Param0;
|
||||
public static String GenericParameter_ParameterExceptions;
|
||||
public static String GenericParameter_ParameterExceptionsItem;
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.codan.internal.checkers;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.cdt.codan.checkers.CodanCheckersActivator;
|
||||
|
@ -36,7 +38,7 @@ public class NamingConventionFunctionChecker extends AbstractIndexAstChecker imp
|
|||
public static final String PARAM_EXCEPT_ARG_LIST = "exceptions"; //$NON-NLS-1$
|
||||
|
||||
public void processAst(IASTTranslationUnit ast) {
|
||||
final IProblem pt = getProblemById(ER_ID, getFile());
|
||||
final List<IProblem> pts = getProblemsByMainId(ER_ID, getFile());
|
||||
try {
|
||||
ast.accept(new ASTVisitor() {
|
||||
{
|
||||
|
@ -45,33 +47,55 @@ public class NamingConventionFunctionChecker extends AbstractIndexAstChecker imp
|
|||
|
||||
public int visit(IASTDeclaration element) {
|
||||
if (element instanceof IASTFunctionDefinition) {
|
||||
String parameter = (String) getPreference(pt, PARAM_KEY);
|
||||
Pattern pattern = Pattern.compile(parameter);
|
||||
IASTName astName = ((IASTFunctionDefinition) element).getDeclarator().getName();
|
||||
String name = astName.toString();
|
||||
if (astName instanceof ICPPASTQualifiedName) {
|
||||
if (!shouldReportCppMethods())
|
||||
return PROCESS_SKIP;
|
||||
ICPPASTQualifiedName cppAstName = (ICPPASTQualifiedName) astName;
|
||||
if (cppAstName.isConversionOrOperator())
|
||||
return PROCESS_SKIP;
|
||||
name = cppAstName.getLastName().toString();
|
||||
if (name.startsWith("~")) // destructor //$NON-NLS-1$
|
||||
return PROCESS_SKIP;
|
||||
IASTName[] names = cppAstName.getNames();
|
||||
if (names.length >= 2) {
|
||||
if (names[names.length - 1].toString().equals(names[names.length - 2].toString())) {
|
||||
// constructor
|
||||
String name = getSearchibleName(astName);
|
||||
if (name != null) {
|
||||
for (Iterator<IProblem> iterator = pts.iterator(); iterator.hasNext();) {
|
||||
IProblem pt = iterator.next();
|
||||
if (!shouldReport(astName, pt))
|
||||
return PROCESS_SKIP;
|
||||
String parameter = (String) getPreference(pt, PARAM_KEY);
|
||||
Pattern pattern = Pattern.compile(parameter);
|
||||
if (!pattern.matcher(name).find() && !isFilteredArg(name, pt)) {
|
||||
reportProblem(pt, astName, name, parameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!pattern.matcher(name).find() && !isFilteredArg(name)) {
|
||||
reportProblem(ER_ID, astName, name, parameter);
|
||||
|
||||
}
|
||||
}
|
||||
return PROCESS_SKIP;
|
||||
}
|
||||
|
||||
public boolean shouldReport(IASTName astName, IProblem pt) {
|
||||
if (astName instanceof ICPPASTQualifiedName) {
|
||||
return shouldReportCppMethods(pt);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param astName
|
||||
* @return
|
||||
*/
|
||||
public String getSearchibleName(IASTName astName) {
|
||||
String name = astName.toString();
|
||||
if (astName instanceof ICPPASTQualifiedName) {
|
||||
ICPPASTQualifiedName cppAstName = (ICPPASTQualifiedName) astName;
|
||||
if (cppAstName.isConversionOrOperator())
|
||||
return null;
|
||||
name = cppAstName.getLastName().toString();
|
||||
if (name.startsWith("~")) // destructor //$NON-NLS-1$
|
||||
return null;
|
||||
IASTName[] names = cppAstName.getNames();
|
||||
if (names.length >= 2) {
|
||||
if (names[names.length - 1].toString().equals(names[names.length - 2].toString())) {
|
||||
// constructor
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
CodanCheckersActivator.log(e);
|
||||
|
@ -88,17 +112,17 @@ public class NamingConventionFunctionChecker extends AbstractIndexAstChecker imp
|
|||
public void initPreferences(IProblemWorkingCopy problem) {
|
||||
super.initPreferences(problem);
|
||||
addPreference(problem, PARAM_KEY, CheckersMessages.NamingConventionFunctionChecker_LabelNamePattern, "^[a-z]"); //$NON-NLS-1$
|
||||
addPreference(problem, PARAM_METHODS, "Also check C++ method names", Boolean.TRUE);
|
||||
addPreference(problem, PARAM_METHODS, CheckersMessages.NamingConventionFunctionChecker_ParameterMethods, Boolean.TRUE);
|
||||
addListPreference(problem, PARAM_EXCEPT_ARG_LIST, CheckersMessages.GenericParameter_ParameterExceptions,
|
||||
CheckersMessages.GenericParameter_ParameterExceptionsItem);
|
||||
}
|
||||
|
||||
public boolean shouldReportCppMethods() {
|
||||
return (Boolean) getPreference(getProblemById(ER_ID, getFile()), PARAM_METHODS);
|
||||
public boolean shouldReportCppMethods(IProblem pt) {
|
||||
return (Boolean) getPreference(pt, PARAM_METHODS);
|
||||
}
|
||||
|
||||
public boolean isFilteredArg(String arg) {
|
||||
return isFilteredArg(arg, getProblemById(ER_ID, getFile()), PARAM_EXCEPT_ARG_LIST);
|
||||
public boolean isFilteredArg(String arg, IProblem pt) {
|
||||
return isFilteredArg(arg, pt, PARAM_EXCEPT_ARG_LIST);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -13,6 +13,7 @@ CaseBreakChecker_EmptyCaseDescription=Check also empty case statement (except if
|
|||
CaseBreakChecker_LastCaseDescription=Check also the last case statement
|
||||
CatchByReference_ReportForUnknownType=Report a problem if type cannot be resolved
|
||||
NamingConventionFunctionChecker_LabelNamePattern=Name Pattern
|
||||
NamingConventionFunctionChecker_ParameterMethods=Also check C++ method names
|
||||
ReturnChecker_Param0=Also check functions with implicit return value
|
||||
GenericParameter_ParameterExceptions=Exceptions (value of the problem argument)
|
||||
GenericParameter_ParameterExceptionsItem=Value of the argument
|
||||
|
|
|
@ -13,6 +13,7 @@ package org.eclipse.cdt.codan.core.cxx.model;
|
|||
import org.eclipse.cdt.codan.core.CodanCorePlugin;
|
||||
import org.eclipse.cdt.codan.core.cxx.Activator;
|
||||
import org.eclipse.cdt.codan.core.model.AbstractCheckerWithProblemPreferences;
|
||||
import org.eclipse.cdt.codan.core.model.IProblem;
|
||||
import org.eclipse.cdt.codan.core.model.IProblemLocation;
|
||||
import org.eclipse.cdt.codan.core.model.IRunnableInEditorChecker;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
|
||||
|
@ -81,8 +82,22 @@ public abstract class AbstractIndexAstChecker extends AbstractCheckerWithProblem
|
|||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
|
||||
public void reportProblem(String id, IASTNode astNode, Object... args) {
|
||||
IProblemLocation loc = getProblemLocation(astNode);
|
||||
if (loc!=null) reportProblem(id, loc, args);
|
||||
}
|
||||
public void reportProblem(IProblem problem, IASTNode astNode, Object... args) {
|
||||
IProblemLocation loc = getProblemLocation(astNode);
|
||||
if (loc!=null) reportProblem(problem, loc, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param astNode
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
protected IProblemLocation getProblemLocation(IASTNode astNode) {
|
||||
IASTFileLocation astLocation = astNode.getFileLocation();
|
||||
IPath location = new Path(astLocation.getFileName());
|
||||
IFile astFile = ResourceLookup.selectFileForLocation(location, getProject());
|
||||
|
@ -91,7 +106,7 @@ public abstract class AbstractIndexAstChecker extends AbstractCheckerWithProblem
|
|||
}
|
||||
if (astFile == null) {
|
||||
Activator.log("Cannot resolve location: " + location); //$NON-NLS-1$
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
IProblemLocation loc;
|
||||
int line = astLocation.getStartingLineNumber();
|
||||
|
@ -100,7 +115,7 @@ public abstract class AbstractIndexAstChecker extends AbstractCheckerWithProblem
|
|||
astLocation.getNodeOffset() + astLocation.getNodeLength(), line);
|
||||
else
|
||||
loc = getRuntime().getProblemLocationFactory().createProblemLocation(astFile, line);
|
||||
reportProblem(id, loc, args);
|
||||
return loc;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -188,6 +188,13 @@ where xxx what checker would post as an argument for the problem.
|
|||
</appinfo>
|
||||
</annotation>
|
||||
</attribute>
|
||||
<attribute name="multiple" type="boolean">
|
||||
<annotation>
|
||||
<documentation>
|
||||
Can user duplicate this problem to have multiple instances (each instance can have diffrent scope, arguments, severity, etc.
|
||||
</documentation>
|
||||
</annotation>
|
||||
</attribute>
|
||||
</complexType>
|
||||
</element>
|
||||
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.codan.core.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.cdt.codan.core.CodanRuntime;
|
||||
import org.eclipse.cdt.codan.internal.core.CheckerInvocationContext;
|
||||
import org.eclipse.cdt.codan.internal.core.CheckersRegistry;
|
||||
|
@ -77,6 +80,27 @@ public abstract class AbstractChecker implements IChecker {
|
|||
return problem;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id - main problem id
|
||||
* @param file - checked resource
|
||||
* @return - list of problems matching with this id, including duplicates
|
||||
* @since 2.0
|
||||
*/
|
||||
public List<IProblem> getProblemsByMainId(String id, IResource file) {
|
||||
ArrayList<IProblem> list = new ArrayList<IProblem>();
|
||||
IProblemProfile resourceProfile = CheckersRegistry.getInstance().getResourceProfile(file);
|
||||
IProblem[] problems = resourceProfile.getProblems();
|
||||
for (int i = 0; i < problems.length; i++) {
|
||||
IProblem p = problems[i];
|
||||
if (p.getId().equals(id)) {
|
||||
list.add(p);
|
||||
} else if (p.getId().startsWith(id + CheckersRegistry.CLONE_SUFFIX)) {
|
||||
list.add(p);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports a simple problem for given file and line, error message comes
|
||||
* from problem definition
|
||||
|
|
|
@ -41,7 +41,7 @@ public abstract class AbstractCheckerWithProblemPreferences extends AbstractChec
|
|||
/**
|
||||
* Scope preference - special preference that all file checkers should have,
|
||||
* it allows user to include/exclude files for this specific problem.
|
||||
*
|
||||
*
|
||||
* @param problem - problem for which scope preference is need
|
||||
* @return scope problem preference, null if not defined
|
||||
*/
|
||||
|
@ -50,7 +50,6 @@ public abstract class AbstractCheckerWithProblemPreferences extends AbstractChec
|
|||
return scope;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param problem - problem for which preference is extracted
|
||||
* @return launch mode preference
|
||||
|
@ -67,7 +66,7 @@ public abstract class AbstractCheckerWithProblemPreferences extends AbstractChec
|
|||
* be done within processResource method not in enabledInContext.
|
||||
* This test uses user "scope" preference for the all problems that this
|
||||
* checker can produce.
|
||||
*
|
||||
*
|
||||
* @param res - resource to test on
|
||||
* @return true if checker should report problems, fails otherwise.
|
||||
*/
|
||||
|
@ -89,10 +88,10 @@ public abstract class AbstractCheckerWithProblemPreferences extends AbstractChec
|
|||
* before printing of a problem.
|
||||
* This test uses user "scope" preference for the given problem. If scope is
|
||||
* not defined preference it returns true.
|
||||
*
|
||||
*
|
||||
* @param problem - problem to test for
|
||||
* @param resource - resource to test on
|
||||
*
|
||||
*
|
||||
* @return true if problem should be report for given resource, fails
|
||||
* otherwise.
|
||||
*/
|
||||
|
@ -109,9 +108,23 @@ public abstract class AbstractCheckerWithProblemPreferences extends AbstractChec
|
|||
super.reportProblem(problemId, loc, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* report a problem
|
||||
*
|
||||
* @param pr - problem (kind) instance
|
||||
* @param loc - problem location
|
||||
* @param args - extra problem arguments
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public void reportProblem(IProblem pr, IProblemLocation loc, Object... args) {
|
||||
if (shouldProduceProblem(pr, loc.getFile().getLocation()))
|
||||
super.reportProblem(pr.getId(), loc, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a parameter
|
||||
*
|
||||
*
|
||||
* @param problem
|
||||
* - problem that has parameter
|
||||
* @param key
|
||||
|
@ -133,7 +146,7 @@ public abstract class AbstractCheckerWithProblemPreferences extends AbstractChec
|
|||
/**
|
||||
* Add preference of type list of strings, list is empty by
|
||||
* default
|
||||
*
|
||||
*
|
||||
* @param problem
|
||||
* - problem
|
||||
* @param key
|
||||
|
@ -143,7 +156,7 @@ public abstract class AbstractCheckerWithProblemPreferences extends AbstractChec
|
|||
* @param itemLabel
|
||||
* @return preference instance of of the list, can be used to add default
|
||||
* values or set different element type
|
||||
*
|
||||
*
|
||||
*/
|
||||
public ListProblemPreference addListPreference(IProblemWorkingCopy problem, String key, String label, String itemLabel) {
|
||||
MapProblemPreference map = getTopLevelPreference(problem);
|
||||
|
@ -155,7 +168,7 @@ public abstract class AbstractCheckerWithProblemPreferences extends AbstractChec
|
|||
|
||||
/**
|
||||
* Add preference for the given problem with default value
|
||||
*
|
||||
*
|
||||
* @param problem
|
||||
* @param pref - preference
|
||||
* @param defaultValue - default value of the preference
|
||||
|
@ -172,7 +185,7 @@ public abstract class AbstractCheckerWithProblemPreferences extends AbstractChec
|
|||
/**
|
||||
* Convenience method for setting default preference value for checker that
|
||||
* uses "map" as top level problem preference.
|
||||
*
|
||||
*
|
||||
* @param problem - problem for which to set default value for a prefence
|
||||
* @param key - preference key
|
||||
* @param defaultValue - value of preference to be set
|
||||
|
@ -189,7 +202,7 @@ public abstract class AbstractCheckerWithProblemPreferences extends AbstractChec
|
|||
* If top level preference does not exist create a map preference with name
|
||||
* "params"
|
||||
* and return it.
|
||||
*
|
||||
*
|
||||
* @param problem
|
||||
* @return top level preference if it is a map
|
||||
* @since 2.0
|
||||
|
@ -208,7 +221,7 @@ public abstract class AbstractCheckerWithProblemPreferences extends AbstractChec
|
|||
/**
|
||||
* Returns value of the preference for the key in the top level
|
||||
* preference map for the given problem
|
||||
*
|
||||
*
|
||||
* @param problem - problem for which to get the preference
|
||||
* @param key - preference key
|
||||
* @return value of the preference
|
||||
|
|
|
@ -23,10 +23,8 @@ public interface IProblemElement extends Cloneable {
|
|||
*
|
||||
* @see {@link Object#clone}
|
||||
* @return new object which is copy of this one
|
||||
* @throws CloneNotSupportedException - it is declared with this exception
|
||||
* but it should NOT throw it
|
||||
*/
|
||||
Object clone() throws CloneNotSupportedException;
|
||||
Object clone();
|
||||
|
||||
/**
|
||||
* @return problem profile where element belongs, can return null if profile
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2009,2010 QNX Software Systems
|
||||
* 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:
|
||||
* QNX Software Systems (Alena Laskavaia) - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.codan.core.model;
|
||||
|
||||
/**
|
||||
* Additional interface to the problem kind to quiry either it supports multiple
|
||||
* instances or not
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface IProblemMultiple {
|
||||
/**
|
||||
*
|
||||
* @return true if problem can be replicated by the user, i.e. multiple is
|
||||
* true in the extension
|
||||
*/
|
||||
public boolean isMultiple();
|
||||
|
||||
/**
|
||||
* @return true if this is original problem, false if it replica
|
||||
*/
|
||||
public boolean isOriginal();
|
||||
}
|
|
@ -51,6 +51,7 @@ public class CheckersRegistry implements Iterable<IChecker>, ICheckersRegistry {
|
|||
private static final String PROBLEM_ELEMENT = "problem"; //$NON-NLS-1$
|
||||
private static final String CATEGORY_ELEMENT = "category"; //$NON-NLS-1$
|
||||
private static final Object DEFAULT = "DEFAULT"; //$NON-NLS-1$
|
||||
public static final String CLONE_SUFFIX = ".COPY"; //$NON-NLS-1$
|
||||
private Collection<IChecker> checkers = new ArrayList<IChecker>();
|
||||
private static CheckersRegistry instance;
|
||||
private static boolean initialized = false;
|
||||
|
@ -190,6 +191,7 @@ public class CheckersRegistry implements Iterable<IChecker>, ICheckersRegistry {
|
|||
String patt = getAtt(configurationElement, "messagePattern", false); //$NON-NLS-1$
|
||||
String desc = getAtt(configurationElement, "description", false); //$NON-NLS-1$
|
||||
String markerType = getAtt(configurationElement, "markerType", false); //$NON-NLS-1$
|
||||
String smultiple = getAtt(configurationElement, "multiple", false); //$NON-NLS-1$
|
||||
if (enab != null) {
|
||||
p.setEnabled(Boolean.valueOf(enab));
|
||||
}
|
||||
|
@ -205,6 +207,9 @@ public class CheckersRegistry implements Iterable<IChecker>, ICheckersRegistry {
|
|||
p.setMarkerType(markerType);
|
||||
}
|
||||
p.setDescription(desc);
|
||||
if (smultiple != null) {
|
||||
p.setMultiple(Boolean.valueOf(smultiple));
|
||||
}
|
||||
addProblem(p, category);
|
||||
return p;
|
||||
}
|
||||
|
@ -329,15 +334,11 @@ public class CheckersRegistry implements Iterable<IChecker>, ICheckersRegistry {
|
|||
public IProblemProfile getWorkspaceProfile() {
|
||||
IProblemProfile wp = profiles.get(ResourcesPlugin.getWorkspace());
|
||||
if (wp == null) {
|
||||
try {
|
||||
wp = (IProblemProfile) getDefaultProfile().clone();
|
||||
((ProblemProfile) wp).setResource(ResourcesPlugin.getWorkspace());
|
||||
// load default values
|
||||
CodanPreferencesLoader loader = new CodanPreferencesLoader(wp);
|
||||
loader.load(CodanPreferencesLoader.getWorkspaceNode());
|
||||
} catch (CloneNotSupportedException e) {
|
||||
wp = getDefaultProfile();
|
||||
}
|
||||
wp = (IProblemProfile) getDefaultProfile().clone();
|
||||
((ProblemProfile) wp).setResource(ResourcesPlugin.getWorkspace());
|
||||
// load default values
|
||||
CodanPreferencesLoader loader = new CodanPreferencesLoader(wp);
|
||||
loader.load(CodanPreferencesLoader.getWorkspaceNode());
|
||||
profiles.put(ResourcesPlugin.getWorkspace(), wp);
|
||||
}
|
||||
return wp;
|
||||
|
@ -363,20 +364,16 @@ public class CheckersRegistry implements Iterable<IChecker>, ICheckersRegistry {
|
|||
IProblemProfile prof = profiles.get(element);
|
||||
if (prof == null) {
|
||||
if (element instanceof IProject) {
|
||||
try {
|
||||
prof = (IProblemProfile) getWorkspaceProfile().clone();
|
||||
((ProblemProfile) prof).setResource(element);
|
||||
// load default values
|
||||
CodanPreferencesLoader loader = new CodanPreferencesLoader(prof);
|
||||
Preferences projectNode = CodanPreferencesLoader.getProjectNode((IProject) element);
|
||||
boolean useWorkspace = projectNode.getBoolean(PreferenceConstants.P_USE_PARENT, false);
|
||||
if (!useWorkspace) {
|
||||
loader.load(projectNode);
|
||||
}
|
||||
profiles.put(element, prof);
|
||||
} catch (CloneNotSupportedException e) {
|
||||
// can't
|
||||
prof = (IProblemProfile) getWorkspaceProfile().clone();
|
||||
((ProblemProfile) prof).setResource(element);
|
||||
// load default values
|
||||
CodanPreferencesLoader loader = new CodanPreferencesLoader(prof);
|
||||
Preferences projectNode = CodanPreferencesLoader.getProjectNode((IProject) element);
|
||||
boolean useWorkspace = projectNode.getBoolean(PreferenceConstants.P_USE_PARENT, false);
|
||||
if (!useWorkspace) {
|
||||
loader.load(projectNode);
|
||||
}
|
||||
profiles.put(element, prof);
|
||||
} else if (element.getParent() != null) {
|
||||
prof = getResourceProfile(element.getParent());
|
||||
} else {
|
||||
|
@ -394,13 +391,8 @@ public class CheckersRegistry implements Iterable<IChecker>, ICheckersRegistry {
|
|||
* getResourceProfileWorkingCopy(org.eclipse.core.resources.IResource)
|
||||
*/
|
||||
public IProblemProfile getResourceProfileWorkingCopy(IResource element) {
|
||||
try {
|
||||
IProblemProfile prof = (IProblemProfile) getResourceProfile(element).clone();
|
||||
return prof;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
// can't
|
||||
return null;
|
||||
}
|
||||
IProblemProfile prof = (IProblemProfile) getResourceProfile(element).clone();
|
||||
return prof;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -463,4 +455,43 @@ public class CheckersRegistry implements Iterable<IChecker>, ICheckersRegistry {
|
|||
public int getCheckersSize() {
|
||||
return checkers.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a replicated problem - it has same check and same initial values
|
||||
* as original but user can modify it further
|
||||
*
|
||||
* @param problem
|
||||
* @param profile
|
||||
*/
|
||||
public void replicateProblem(IProblem problem, IProblemProfile profile) {
|
||||
CodanProblem x = (CodanProblem) problem.clone();
|
||||
x.setId(getNextCloneId(problem, profile));
|
||||
((ProblemProfile) profile).addProblem(x, problem.getParentCategory());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param problem
|
||||
* @param profile
|
||||
* @return
|
||||
*/
|
||||
private String getNextCloneId(IProblem problem, IProblemProfile profile) {
|
||||
IProblem[] problems = profile.getProblems();
|
||||
String prefix = problem.getId() + CLONE_SUFFIX;
|
||||
int max = 0;
|
||||
for (int i = 0; i < problems.length; i++) {
|
||||
IProblem x = problems[i];
|
||||
if (x.getId().startsWith(prefix)) {
|
||||
int num = 0;
|
||||
try {
|
||||
num = Integer.parseInt(x.getId().substring(prefix.length()));
|
||||
} catch (Exception e) {
|
||||
// well...
|
||||
}
|
||||
if (max < num)
|
||||
max = num;
|
||||
}
|
||||
}
|
||||
max++;
|
||||
return prefix + max;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,15 +11,17 @@
|
|||
package org.eclipse.cdt.codan.internal.core.model;
|
||||
|
||||
import org.eclipse.cdt.codan.core.model.CodanSeverity;
|
||||
import org.eclipse.cdt.codan.core.model.IProblemMultiple;
|
||||
import org.eclipse.cdt.codan.core.model.IProblemReporter;
|
||||
import org.eclipse.cdt.codan.core.model.IProblemWorkingCopy;
|
||||
import org.eclipse.cdt.codan.core.model.ProblemProfileChangeEvent;
|
||||
import org.eclipse.cdt.codan.core.param.IProblemPreference;
|
||||
import org.eclipse.cdt.codan.internal.core.CheckersRegistry;
|
||||
|
||||
/**
|
||||
* A type of problems reported by Codan.
|
||||
*/
|
||||
public class CodanProblem extends CodanProblemElement implements IProblemWorkingCopy, Cloneable {
|
||||
public class CodanProblem extends CodanProblemElement implements IProblemWorkingCopy, Cloneable, IProblemMultiple {
|
||||
private String id;
|
||||
private String name;
|
||||
private String messagePattern;
|
||||
|
@ -28,6 +30,11 @@ public class CodanProblem extends CodanProblemElement implements IProblemWorking
|
|||
private IProblemPreference rootPreference;
|
||||
private String description;
|
||||
private String markerType = IProblemReporter.GENERIC_CODE_ANALYSIS_MARKER_TYPE;
|
||||
private boolean multiple;
|
||||
|
||||
public void setMultiple(boolean multiple) {
|
||||
this.multiple = multiple;
|
||||
}
|
||||
|
||||
public CodanSeverity getSeverity() {
|
||||
return severity;
|
||||
|
@ -50,6 +57,14 @@ public class CodanProblem extends CodanProblemElement implements IProblemWorking
|
|||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id
|
||||
* @noreference This method is not intended to be referenced by clients.
|
||||
*/
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
|
@ -156,4 +171,22 @@ public class CodanProblem extends CodanProblemElement implements IProblemWorking
|
|||
checkSet();
|
||||
this.markerType = markerType;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.cdt.codan.core.model.IProblemMultiple#isMultiple()
|
||||
*/
|
||||
public boolean isMultiple() {
|
||||
return multiple;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.cdt.codan.core.model.IProblemMultiple#isOriginal()
|
||||
*/
|
||||
public boolean isOriginal() {
|
||||
return !id.contains(CheckersRegistry.CLONE_SUFFIX);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -124,25 +124,21 @@ public class CodanProblemCategory extends CodanProblemElement implements IProble
|
|||
*/
|
||||
@Override
|
||||
public Object clone() {
|
||||
try {
|
||||
CodanProblemCategory catClone = (CodanProblemCategory) super.clone();
|
||||
catClone.list = new ArrayList<IProblemElement>();
|
||||
for (Iterator<IProblemElement> iterator = this.list.iterator(); iterator.hasNext();) {
|
||||
IProblemElement child = iterator.next();
|
||||
IProblemElement childClone = (IProblemElement) child.clone();
|
||||
if (childClone instanceof CodanProblemElement) {
|
||||
CodanProblemElement cce = (CodanProblemElement) childClone;
|
||||
boolean fro = cce.isFrozen();
|
||||
cce.setFrozen(false);
|
||||
cce.setParentCategory(catClone);
|
||||
cce.setFrozen(fro);
|
||||
}
|
||||
catClone.list.add(childClone);
|
||||
CodanProblemCategory catClone = (CodanProblemCategory) super.clone();
|
||||
catClone.list = new ArrayList<IProblemElement>();
|
||||
for (Iterator<IProblemElement> iterator = this.list.iterator(); iterator.hasNext();) {
|
||||
IProblemElement child = iterator.next();
|
||||
IProblemElement childClone = (IProblemElement) child.clone();
|
||||
if (childClone instanceof CodanProblemElement) {
|
||||
CodanProblemElement cce = (CodanProblemElement) childClone;
|
||||
boolean fro = cce.isFrozen();
|
||||
cce.setFrozen(false);
|
||||
cce.setParentCategory(catClone);
|
||||
cce.setFrozen(fro);
|
||||
}
|
||||
return catClone;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
return this;
|
||||
catClone.list.add(childClone);
|
||||
}
|
||||
return catClone;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Add table
Reference in a new issue