diff --git a/codan/org.eclipse.cdt.codan.checkers/plugin.xml b/codan/org.eclipse.cdt.codan.checkers/plugin.xml index 0292066b8d3..d1cffe7a94c 100644 --- a/codan/org.eclipse.cdt.codan.checkers/plugin.xml +++ b/codan/org.eclipse.cdt.codan.checkers/plugin.xml @@ -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"> diff --git a/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CheckersMessages.java b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CheckersMessages.java index 86cd9f2da55..ed6890d657b 100644 --- a/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CheckersMessages.java +++ b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CheckersMessages.java @@ -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; diff --git a/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/NamingConventionFunctionChecker.java b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/NamingConventionFunctionChecker.java index 4befabb95d2..f155d4f6fe5 100644 --- a/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/NamingConventionFunctionChecker.java +++ b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/NamingConventionFunctionChecker.java @@ -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 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 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 diff --git a/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/messages.properties b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/messages.properties index bd30a1fcd99..74fc7c6647c 100644 --- a/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/messages.properties +++ b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/messages.properties @@ -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 diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/model/AbstractIndexAstChecker.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/model/AbstractIndexAstChecker.java index 07e27652b05..cf995147bb1 100644 --- a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/model/AbstractIndexAstChecker.java +++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/model/AbstractIndexAstChecker.java @@ -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 diff --git a/codan/org.eclipse.cdt.codan.core/schema/checkers.exsd b/codan/org.eclipse.cdt.codan.core/schema/checkers.exsd index 6634a51baf2..a4a5496633c 100644 --- a/codan/org.eclipse.cdt.codan.core/schema/checkers.exsd +++ b/codan/org.eclipse.cdt.codan.core/schema/checkers.exsd @@ -188,6 +188,13 @@ where xxx what checker would post as an argument for the problem. + + + + Can user duplicate this problem to have multiple instances (each instance can have diffrent scope, arguments, severity, etc. + + + diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractChecker.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractChecker.java index 24b9e7714c2..0fece960375 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractChecker.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractChecker.java @@ -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 getProblemsByMainId(String id, IResource file) { + ArrayList list = new ArrayList(); + 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 diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractCheckerWithProblemPreferences.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractCheckerWithProblemPreferences.java index 7918996237d..088e0274da0 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractCheckerWithProblemPreferences.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractCheckerWithProblemPreferences.java @@ -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 diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IProblemElement.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IProblemElement.java index a48f6000abc..11884a190ac 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IProblemElement.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IProblemElement.java @@ -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 diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IProblemMultiple.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IProblemMultiple.java new file mode 100644 index 00000000000..f3d09d92257 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IProblemMultiple.java @@ -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(); +} diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CheckersRegistry.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CheckersRegistry.java index 9da75a7b37b..30f4c987fb5 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CheckersRegistry.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CheckersRegistry.java @@ -51,6 +51,7 @@ public class CheckersRegistry implements Iterable, 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 checkers = new ArrayList(); private static CheckersRegistry instance; private static boolean initialized = false; @@ -190,6 +191,7 @@ public class CheckersRegistry implements Iterable, 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, 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, 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, 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, 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, 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; + } } diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblem.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblem.java index 652c6645fc0..3bae48a4758 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblem.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblem.java @@ -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); + } } diff --git a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblemCategory.java b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblemCategory.java index c5fc8ff30f5..6ebb4c4c3f7 100644 --- a/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblemCategory.java +++ b/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblemCategory.java @@ -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(); - for (Iterator 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(); + for (Iterator 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; } /*