The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available
+at http://www.eclipse.org/legal/epl-v10.html.
+For purposes of the EPL, "Program" will mean the Content.
+
+
If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party ("Redistributor") and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was
+provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at http://www.eclipse.org.
+
+
\ No newline at end of file
diff --git a/org.eclipse.cdt.codan.core/build.properties b/org.eclipse.cdt.codan.core/build.properties
index 3595411..b599b4a 100644
--- a/org.eclipse.cdt.codan.core/build.properties
+++ b/org.eclipse.cdt.codan.core/build.properties
@@ -1,6 +1,19 @@
+###############################################################################
+# Copyright (c) 2009, 2010 Alena Laskavaia and others.
+# 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
+###############################################################################
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.,\
plugin.xml,\
- schema/
+ schema/,\
+ OSGI-INF/l10n/bundle.properties,\
+ about.html
+src.includes = schema/
diff --git a/org.eclipse.cdt.codan.core/plugin.xml b/org.eclipse.cdt.codan.core/plugin.xml
index b7b10a0..1b051a3 100644
--- a/org.eclipse.cdt.codan.core/plugin.xml
+++ b/org.eclipse.cdt.codan.core/plugin.xml
@@ -1,11 +1,11 @@
-
+
@@ -16,7 +16,7 @@
+
+
+
+
+ type="org.eclipse.cdt.core.problem">
+
+
+
+
+
@@ -48,9 +59,12 @@
+
-
@@ -62,7 +76,7 @@
thread="main"
visible="true">
+ class="org.eclipse.cdt.codan.internal.core.CodanApplication">
diff --git a/org.eclipse.cdt.codan.core/schema/CVS/Entries b/org.eclipse.cdt.codan.core/schema/CVS/Entries
index 2905ba5..f6008c3 100644
--- a/org.eclipse.cdt.codan.core/schema/CVS/Entries
+++ b/org.eclipse.cdt.codan.core/schema/CVS/Entries
@@ -1,2 +1 @@
-/checkers.exsd/1.1/Thu Apr 9 12:46:50 2009//
-D
+/checkers.exsd/1.5/Sun Jun 27 01:30:41 2010//TCDT_7_0_0
diff --git a/org.eclipse.cdt.codan.core/schema/CVS/Tag b/org.eclipse.cdt.codan.core/schema/CVS/Tag
new file mode 100644
index 0000000..49a449a
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/schema/CVS/Tag
@@ -0,0 +1 @@
+NCDT_7_0_0
diff --git a/org.eclipse.cdt.codan.core/schema/checkers.exsd b/org.eclipse.cdt.codan.core/schema/checkers.exsd
index 71808a5..1990117 100644
--- a/org.eclipse.cdt.codan.core/schema/checkers.exsd
+++ b/org.eclipse.cdt.codan.core/schema/checkers.exsd
@@ -60,6 +60,7 @@
+
@@ -143,6 +144,43 @@
+
+
+
+ If problem is enabled in original profile. Default is true.
+
+
+
+
+
+
+ Default error message pattern. Use java pattern notation such as {0} to replace with first argument, and so on.
+
+
+
+
+
+
+
+
+
+ Short description of the problem
+
+
+
+
+
+
+
+
+
+ Marker type to use to generate problem, default is the generic codan marker
+
+
+
+
+
+
@@ -178,6 +216,21 @@
+
+
+
+
+
+ Reference to a problem
+
+
+
+
+
+
+
+
+
diff --git a/org.eclipse.cdt.codan.core/src/CVS/Tag b/org.eclipse.cdt.codan.core/src/CVS/Tag
new file mode 100644
index 0000000..3cd1ca4
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/CVS/Tag
@@ -0,0 +1 @@
+TCDT_7_0_0
diff --git a/org.eclipse.cdt.codan.core/src/org/CVS/Tag b/org.eclipse.cdt.codan.core/src/org/CVS/Tag
new file mode 100644
index 0000000..3cd1ca4
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/CVS/Tag
@@ -0,0 +1 @@
+TCDT_7_0_0
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/CVS/Tag b/org.eclipse.cdt.codan.core/src/org/eclipse/CVS/Tag
new file mode 100644
index 0000000..3cd1ca4
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/CVS/Tag
@@ -0,0 +1 @@
+TCDT_7_0_0
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/CVS/Tag b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/CVS/Tag
new file mode 100644
index 0000000..3cd1ca4
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/CVS/Tag
@@ -0,0 +1 @@
+TCDT_7_0_0
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/CVS/Entries b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/CVS/Entries
index 94f7274..d028aeb 100644
--- a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/CVS/Entries
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/CVS/Entries
@@ -1,2 +1,3 @@
D/core////
D/internal////
+D/provisional////
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/CVS/Tag b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/CVS/Tag
new file mode 100644
index 0000000..3cd1ca4
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/CVS/Tag
@@ -0,0 +1 @@
+TCDT_7_0_0
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/CVS/Entries b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/CVS/Entries
index d3c5192..3e108e0 100644
--- a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/CVS/Entries
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/CVS/Entries
@@ -1,6 +1,8 @@
-/CodanApplication.java/1.2/Sat Aug 22 21:16:48 2009//
-/CodanCorePlugin.java/1.3/Sat Aug 22 21:16:48 2009//
-/CodanRuntime.java/1.1/Sat Aug 22 21:16:48 2009//
-/PreferenceConstants.java/1.2/Sat Apr 18 04:01:43 2009//
+/CodanCorePlugin.java/1.5/Sun Jun 27 01:30:41 2010//TCDT_7_0_0
+/CodanRuntime.java/1.6/Sun Jun 27 01:30:41 2010//TCDT_7_0_0
+/Messages.java/1.3/Tue May 25 01:33:23 2010//TCDT_7_0_0
+/PreferenceConstants.java/1.6/Sun Jun 27 01:30:41 2010//TCDT_7_0_0
D/builder////
+/messages.properties/1.4/Thu Jun 3 17:01:53 2010//TCDT_7_0_0
D/model////
+D/param////
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/CVS/Tag b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/CVS/Tag
new file mode 100644
index 0000000..49a449a
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/CVS/Tag
@@ -0,0 +1 @@
+NCDT_7_0_0
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/CodanApplication.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/CodanApplication.java
deleted file mode 100644
index e0287b1..0000000
--- a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/CodanApplication.java
+++ /dev/null
@@ -1,94 +0,0 @@
-package org.eclipse.cdt.codan.core;
-
-import java.util.ArrayList;
-import java.util.Collection;
-
-import org.eclipse.cdt.codan.internal.core.CodanBuilder;
-import org.eclipse.cdt.codan.internal.core.model.CodanMarkerProblemReporter;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IWorkspaceRoot;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.equinox.app.IApplication;
-import org.eclipse.equinox.app.IApplicationContext;
-
-public class CodanApplication implements IApplication {
- private Collection projects = new ArrayList();
- private boolean verbose = false;
- private boolean all = false;
-
- public Object start(IApplicationContext context) throws Exception {
- String[] args = (String[]) context.getArguments().get(
- "application.args");
- if (args == null || args.length == 0) {
- help();
- return EXIT_OK;
- }
- extractArguments(args);
- CodanBuilder codanBuilder = new CodanBuilder();
- CodanRuntime runtime = CodanRuntime.getInstance();
- runtime.setProblemReporter(new CodanMarkerProblemReporter() {
- @Override
- public void reportProblem(String id, int severity, IFile file,
- int lineNumber, int startChar, int endChar, String message) {
- System.out.println(file.getLocation() + ":" + lineNumber + ": "
- + message);
- }
- });
- IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
- if (all) {
- log("Launching analysis on workspace");
- root.accept(codanBuilder.new CodanResourceVisitor());
- } else {
- for (String project : projects) {
- log("Launching analysis on project " + project);
- IProject wProject = root.getProject(project);
- if (!wProject.exists()) {
- System.err.println("Error: project " + project
- + " does not exist");
- continue;
- }
- wProject.accept(codanBuilder.new CodanResourceVisitor());
- }
- }
- return EXIT_OK;
- }
-
- /**
- * @param string
- */
- private void log(String string) {
- if (verbose)
- System.err.println(string);
- }
-
- /**
- * @param args
- */
- private void extractArguments(String[] args) {
- for (int i = 0; i < args.length; i++) {
- String string = args[i];
- if (string.equals("-verbose")) {
- verbose = true;
- } else if (string.equals("-all")) {
- all = true;
- } else {
- projects.add(string);
- }
- }
- }
-
- /**
- *
- */
- private void help() {
- System.out.println("Usage: [options] ...");
- System.out.println("Options:");
- System.out.println(" -all - run on all projects in workspace");
- System.out.println(" -verbose - print extra build information");
- }
-
- public void stop() {
- // nothing
- }
-}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/CodanCorePlugin.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/CodanCorePlugin.java
index d60262b..90e5d83 100644
--- a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/CodanCorePlugin.java
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/CodanCorePlugin.java
@@ -1,3 +1,13 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Alena Laskavaia and others.
+ * 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;
import org.eclipse.cdt.codan.internal.core.CodeAnlysisNature;
@@ -13,7 +23,7 @@ import org.osgi.framework.BundleContext;
*/
public class CodanCorePlugin extends Plugin {
// The plug-in ID
- public static final String PLUGIN_ID = "org.eclipse.cdt.codan.core";
+ public static final String PLUGIN_ID = "org.eclipse.cdt.codan.core"; //$NON-NLS-1$
public static final String NATURE_ID = CodeAnlysisNature.NATURE_ID;
// The shared instance
private static CodanCorePlugin plugin;
@@ -34,6 +44,7 @@ public class CodanCorePlugin extends Plugin {
* @see
* org.eclipse.core.runtime.Plugins#start(org.osgi.framework.BundleContext)
*/
+ @Override
public void start(BundleContext context) throws Exception {
super.start(context);
plugin = this;
@@ -45,6 +56,7 @@ public class CodanCorePlugin extends Plugin {
* @see
* org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext)
*/
+ @Override
public void stop(BundleContext context) throws Exception {
plugin = null;
super.stop(context);
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/CodanRuntime.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/CodanRuntime.java
index 16375cf..bc7b3d7 100644
--- a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/CodanRuntime.java
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/CodanRuntime.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009 Alena Laskavaia
+ * Copyright (c) 2009, 2010 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
@@ -11,44 +11,102 @@
package org.eclipse.cdt.codan.core;
import org.eclipse.cdt.codan.core.model.ICheckersRegistry;
-import org.eclipse.cdt.codan.core.model.ICodanAstReconciler;
import org.eclipse.cdt.codan.core.model.ICodanBuilder;
+import org.eclipse.cdt.codan.core.model.IProblemLocationFactory;
import org.eclipse.cdt.codan.core.model.IProblemReporter;
-import org.eclipse.cdt.codan.internal.core.CheckersRegisry;
+import org.eclipse.cdt.codan.internal.core.CheckersRegistry;
import org.eclipse.cdt.codan.internal.core.CodanBuilder;
import org.eclipse.cdt.codan.internal.core.model.CodanMarkerProblemReporter;
+import org.eclipse.cdt.codan.internal.core.model.ProblemLocationFactory;
/**
* Runtime singleton class to get access to Codan framework parts
*
+ * Clients may extend this class to override default framework parts.
+ *
+ *
+ * EXPERIMENTAL. This class or interface has been added as part
+ * of a work in progress. There is no guarantee that this API will work or that
+ * it will remain the same.
+ *
*/
public class CodanRuntime {
private static CodanRuntime instance = new CodanRuntime();
private IProblemReporter problemReporter = new CodanMarkerProblemReporter();
- private CodanBuilder builder = new CodanBuilder();
- private CheckersRegisry checkers = CheckersRegisry.getInstance();
+ private ICodanBuilder builder = new CodanBuilder();
+ private CheckersRegistry checkers = CheckersRegistry.getInstance();
+ private IProblemLocationFactory locFactory = new ProblemLocationFactory();
+
+ /**
+ * CodanRuntime - only can be called by subclasses to override default
+ * constructor
+ */
+ protected CodanRuntime() {
+ // nothing here
+ }
+ /**
+ * Get runtime problem reporter. Default reported generated problem markers.
+ *
+ * @return
+ */
public IProblemReporter getProblemReporter() {
return problemReporter;
}
+ /**
+ * Set different problem reporter.
+ *
+ * @param reporter
+ */
public void setProblemReporter(IProblemReporter reporter) {
problemReporter = reporter;
}
+ /**
+ * Get instance of of Codan Runtime
+ *
+ * @return
+ */
public static CodanRuntime getInstance() {
return instance;
}
+ /**
+ * Get builder. Builder can used to run code analysis on given resource
+ * using API.
+ *
+ * @return
+ */
public ICodanBuilder getBuilder() {
return builder;
}
- public ICodanAstReconciler getAstQuickBuilder() {
- return builder;
- }
-
+ /**
+ * Get checkers registry.
+ *
+ * @return
+ */
public ICheckersRegistry getChechersRegistry() {
return checkers;
}
+
+ /**
+ * Get problem location factory.
+ *
+ * @return
+ */
+ public IProblemLocationFactory getProblemLocationFactory() {
+ return locFactory;
+ }
+
+ /**
+ * Set another problem location factory - only need if default is not
+ * sufficient, i.e IProblemLocation is implemented differently
+ *
+ * @param factory
+ */
+ public void setProblemLocationFactory(IProblemLocationFactory factory) {
+ locFactory = factory;
+ }
}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/Messages.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/Messages.java
new file mode 100644
index 0000000..312c5c2
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/Messages.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2009,2010 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;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Core Messages
+ */
+public class Messages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.cdt.codan.core.messages"; //$NON-NLS-1$
+ public static String CodanApplication_all_option;
+ public static String CodanApplication_Error_ProjectDoesNotExists;
+ public static String CodanApplication_LogRunProject;
+ public static String CodanApplication_LogRunWorkspace;
+ public static String CodanApplication_Options;
+ public static String CodanApplication_Usage;
+ public static String CodanApplication_verbose_option;
+ public static String CodanBuilder_Code_Analysis_On;
+ public static String FileScopeProblemPreference_Label;
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ }
+}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/PreferenceConstants.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/PreferenceConstants.java
index a4a1374..c730e9e 100644
--- a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/PreferenceConstants.java
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/PreferenceConstants.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009 Alena Laskavaia
+ * Copyright (c) 2009, 2010 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
@@ -12,9 +12,15 @@ package org.eclipse.cdt.codan.core;
/**
* Constant definitions for plug-in preferences
+ *
+ * EXPERIMENTAL. This class or interface has been added as part
+ * of a work in progress. There is no guarantee that this API will work or that
+ * it will remain the same.
+ *
*/
public class PreferenceConstants {
- public static final String P_RUN_ON_BUILD = "booleanPreference";
- public static final String P_PROBLEMS = "problems";
- public static final String P_USE_PARENT = "useParentScope";
+ public static final String P_RUN_ON_BUILD = "onBuild"; //$NON-NLS-1$
+ public static final String P_RUN_IN_EDITOR = "inEditor"; //$NON-NLS-1$
+ public static final String P_PROBLEMS = "problems"; //$NON-NLS-1$
+ public static final String P_USE_PARENT = "useParentScope"; //$NON-NLS-1$
}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/messages.properties b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/messages.properties
new file mode 100644
index 0000000..d27aa29
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/messages.properties
@@ -0,0 +1,19 @@
+###############################################################################
+# Copyright (c) 2010 Alena Laskavaia and others.
+# 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
+###############################################################################
+CodanApplication_Error_ProjectDoesNotExists=Error: project {0} does not exist
+CodanApplication_LogRunProject=Running code analysis on project
+CodanApplication_LogRunWorkspace=Running code analysis on workspace
+CodanApplication_Usage=Usage: [options] ...
+CodanApplication_Options=Options:
+CodanApplication_all_option= -all - run on all projects in workspace
+CodanApplication_verbose_option= -verbose - print verbose build information
+CodanBuilder_Code_Analysis_On=Code analysis on
+FileScopeProblemPreference_Label=Exclusion and Inclusion
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractChecker.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractChecker.java
index f1e5028..411ba67 100644
--- a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractChecker.java
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractChecker.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009 Alena Laskavaia
+ * Copyright (c) 2009, 2010 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
@@ -11,12 +11,21 @@
package org.eclipse.cdt.codan.core.model;
import org.eclipse.cdt.codan.core.CodanRuntime;
+import org.eclipse.cdt.codan.internal.core.CheckersRegistry;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
+/**
+ * Convenience implementation of IChecker interface. Has a default
+ * implementation for common methods.
+ *
+ */
public abstract class AbstractChecker implements IChecker {
protected String name;
+ /**
+ * Default constructor
+ */
public AbstractChecker() {
}
@@ -32,19 +41,38 @@ public abstract class AbstractChecker implements IChecker {
* Reports a simple problem for given file and line
*
* @param id
- * - problem id
+ * - problem id
* @param file
- * - file
+ * - file
* @param lineNumber
- * - line
- * @param arg
- * - problem argument, if problem does not define error message
- * it will be error message (not recommended because of
- * internationalization)
+ * - line
+ * @param args
+ * - problem arguments, if problem does not define error message
+ * it will be error message (not recommended because of
+ * internationalization)
*/
- public void reportProblem(String id, IFile file, int lineNumber, String arg) {
+ public void reportProblem(String id, IFile file, int lineNumber,
+ Object... args) {
getProblemReporter().reportProblem(id,
- new ProblemLocation(file, lineNumber), arg);
+ createProblemLocation(file, lineNumber), args);
+ }
+
+ /**
+ * Finds an instance of problem by given id, in user profile registered for
+ * specific file
+ *
+ * @param id
+ * - problem id
+ * @param file
+ * - file in scope
+ * @return problem instance
+ */
+ public IProblem getProblemById(String id, IResource file) {
+ IProblem problem = CheckersRegistry.getInstance()
+ .getResourceProfile(file).findProblem(id);
+ if (problem == null)
+ throw new IllegalArgumentException("Id is not registered"); //$NON-NLS-1$
+ return problem;
}
/**
@@ -52,15 +80,15 @@ public abstract class AbstractChecker implements IChecker {
* from problem definition
*
* @param id
- * - problem id
+ * - problem id
* @param file
- * - file
+ * - file
* @param lineNumber
- * - line
+ * - line
*/
public void reportProblem(String id, IFile file, int lineNumber) {
getProblemReporter().reportProblem(id,
- new ProblemLocation(file, lineNumber), new Object[] {});
+ createProblemLocation(file, lineNumber), new Object[] {});
}
/**
@@ -70,7 +98,64 @@ public abstract class AbstractChecker implements IChecker {
return CodanRuntime.getInstance().getProblemReporter();
}
+ /**
+ * Convenience method to return codan runtime
+ *
+ * @return
+ */
+ protected CodanRuntime getRuntime() {
+ return CodanRuntime.getInstance();
+ }
+
+ /**
+ * Convenience method to create and return instance of IProblemLocation
+ *
+ * @param file
+ * - file where problem is found
+ * @param line
+ * - line number 1-relative
+ * @return instance of IProblemLocation
+ */
+ protected IProblemLocation createProblemLocation(IFile file, int line) {
+ return getRuntime().getProblemLocationFactory().createProblemLocation(
+ file, line);
+ }
+
+ /**
+ * Convenience method to create and return instance of IProblemLocation
+ *
+ * @param file
+ * - file where problem is found
+ * @param startChar
+ * - start char of the problem in the file, is zero-relative
+ * @param endChar
+ * - end char of the problem in the file, is zero-relative and
+ * exclusive.
+ * @return instance of IProblemLocation
+ */
+ protected IProblemLocation createProblemLocation(IFile file, int startChar,
+ int endChar) {
+ return getRuntime().getProblemLocationFactory().createProblemLocation(
+ file, startChar, endChar);
+ }
+
+ /**
+ * Defines if checker should be run as user type in C editor. Override this
+ * method is checker is too heavy for that (runs too long)
+ */
public boolean runInEditor() {
- return false;
+ return this instanceof IRunnableInEditorChecker;
+ }
+
+ /**
+ * report a problem
+ *
+ * @param problemId - id of a problem
+ * @param loc - problem location
+ * @param args - extra problem arguments
+ */
+ public void reportProblem(String problemId, IProblemLocation loc,
+ Object... args) {
+ getProblemReporter().reportProblem(problemId, loc, args);
}
}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractCheckerWithProblemPreferences.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractCheckerWithProblemPreferences.java
new file mode 100644
index 0000000..b58156f
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractCheckerWithProblemPreferences.java
@@ -0,0 +1,223 @@
+/*******************************************************************************
+ * Copyright (c) 2009,2010 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.model;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.eclipse.cdt.codan.core.param.AbstractProblemPreference;
+import org.eclipse.cdt.codan.core.param.BasicProblemPreference;
+import org.eclipse.cdt.codan.core.param.FileScopeProblemPreference;
+import org.eclipse.cdt.codan.core.param.IProblemPreference;
+import org.eclipse.cdt.codan.core.param.IProblemPreferenceDescriptor.PreferenceType;
+import org.eclipse.cdt.codan.core.param.ListProblemPreference;
+import org.eclipse.cdt.codan.core.param.MapProblemPreference;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IPath;
+
+/**
+ * AbstarctChecker that has extra methods to simplify adding problem
+ * preferences.
+ * Checker can produce several problems, but preferences are per problem.
+ * Sharing preferences between problems is not supported now.
+ */
+public abstract class AbstractCheckerWithProblemPreferences extends
+ AbstractChecker implements ICheckerWithPreferences {
+ /**
+ * Checker that actually has parameter must override this
+ */
+ public void initPreferences(IProblemWorkingCopy problem) {
+ // by default add file scope preference
+ addPreference(problem, new FileScopeProblemPreference(), null);
+ }
+
+ /**
+ * 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
+ */
+ public FileScopeProblemPreference getScopePreference(IProblem problem) {
+ FileScopeProblemPreference scope = (FileScopeProblemPreference) getTopLevelPreferenceMap(
+ problem).getChildDescriptor(FileScopeProblemPreference.KEY);
+ return scope;
+ }
+
+ /**
+ * 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.
+ * 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.
+ */
+ public boolean shouldProduceProblems(IResource res) {
+ Collection refProblems = getRuntime().getChechersRegistry()
+ .getRefProblems(this);
+ for (Iterator iterator = refProblems.iterator(); iterator
+ .hasNext();) {
+ IProblem checkerProblem = iterator.next();
+ if (shouldProduceProblem(
+ getProblemById(checkerProblem.getId(), res),
+ res.getLocation()))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * 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 produce a
+ * specific problem on this resource. Test should
+ * be done within processResource method not in enabledInContext, or just
+ * 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.
+ */
+ public boolean shouldProduceProblem(IProblem problem, IPath resource) {
+ FileScopeProblemPreference scope = getScopePreference(problem);
+ if (scope == null)
+ return true;
+ return scope.isInScope(resource);
+ }
+
+ @Override
+ public void reportProblem(String problemId, IProblemLocation loc,
+ Object... args) {
+ if (shouldProduceProblem(getProblemById(problemId, loc.getFile()), loc
+ .getFile().getLocation()))
+ super.reportProblem(problemId, loc, args);
+ }
+
+ /**
+ * Add a parameter
+ *
+ * @param problem
+ * - problem that has parameter
+ * @param key
+ * - parameter key
+ * @param label
+ * - parameter label - user visible
+ * @param defaultValue
+ * - parameter default value
+ * @return - parameter info object
+ */
+ public IProblemPreference addPreference(IProblemWorkingCopy problem,
+ String key, String label, Object defaultValue) {
+ MapProblemPreference map = getTopLevelPreferenceMap(problem);
+ BasicProblemPreference info = new BasicProblemPreference(key, label,
+ PreferenceType.typeOf(defaultValue));
+ map.addChildDescriptor(info);
+ setDefaultPreferenceValue(problem, key, defaultValue);
+ return info;
+ }
+
+ /**
+ * Add preference of type list of strings, list is empty by
+ * default
+ *
+ * @param problem
+ * - problem
+ * @param key
+ * - preference key
+ * @param label
+ * - preference label
+ * @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 = getTopLevelPreferenceMap(problem);
+ ListProblemPreference list = new ListProblemPreference(key, label);
+ list.setChildDescriptor(new BasicProblemPreference(
+ ListProblemPreference.COMMON_DESCRIPTOR_KEY, itemLabel,
+ PreferenceType.TYPE_STRING));
+ return (ListProblemPreference) map.addChildDescriptor(list);
+ }
+
+ /**
+ * Add preference for the given problem with default value
+ *
+ * @param problem
+ * @param pref - preference
+ * @param defaultValue - default value of the preference
+ * @return added preference
+ */
+ public IProblemPreference addPreference(IProblemWorkingCopy problem,
+ IProblemPreference pref, Object defaultValue) {
+ MapProblemPreference map = getTopLevelPreferenceMap(problem);
+ String key = pref.getKey();
+ pref = map.addChildDescriptor(pref);
+ setDefaultPreferenceValue(problem, key, defaultValue);
+ return pref;
+ }
+
+ /**
+ * 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
+ */
+ protected void setDefaultPreferenceValue(IProblemWorkingCopy problem,
+ String key, Object defaultValue) {
+ MapProblemPreference map = getTopLevelPreferenceMap(problem);
+ if (map.getChildValue(key) == null)
+ map.setChildValue(key, defaultValue);
+ }
+
+ /**
+ * Return "map" problem preference for a give problem, if problem
+ * has preference different than a map, it will throw ClassCastException.
+ * 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
+ */
+ protected MapProblemPreference getTopLevelPreferenceMap(IProblem problem) {
+ MapProblemPreference map = (MapProblemPreference) problem
+ .getPreference();
+ if (map == null) {
+ map = new MapProblemPreference(AbstractProblemPreference.PARAM, ""); //$NON-NLS-1$
+ if (problem instanceof IProblemWorkingCopy) {
+ ((IProblemWorkingCopy) problem).setPreference(map);
+ }
+ }
+ return map;
+ }
+
+ /**
+ * 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
+ */
+ public Object getPreference(IProblem problem, String key) {
+ return ((MapProblemPreference) problem.getPreference())
+ .getChildValue(key);
+ }
+}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractIndexAstChecker.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractIndexAstChecker.java
deleted file mode 100644
index d805f2f..0000000
--- a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractIndexAstChecker.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009 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.model;
-
-import org.eclipse.cdt.codan.core.CodanCorePlugin;
-import org.eclipse.cdt.core.CCorePlugin;
-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.CoreModel;
-import org.eclipse.cdt.core.model.ICElement;
-import org.eclipse.cdt.core.model.ITranslationUnit;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.Path;
-
-/**
- * @author Alena
- *
- */
-public abstract class AbstractIndexAstChecker extends AbstractChecker implements
- ICAstChecker {
- private IFile file;
-
- protected IFile getFile() {
- return file;
- }
-
- void processFile(IFile file) throws CoreException, InterruptedException {
- // create translation unit and access index
- ICElement model = CoreModel.getDefault().create(file);
- if (!(model instanceof ITranslationUnit))
- return;
- ITranslationUnit tu = (ITranslationUnit) model;
- if (tu == null)
- return; // not a C/C++ file
- IIndex index = CCorePlugin.getIndexManager().getIndex(tu.getCProject());
- // lock the index for read access
- index.acquireReadLock();
- try {
- // create index based ast
- IASTTranslationUnit ast = tu.getAST(index,
- ITranslationUnit.AST_SKIP_INDEXED_HEADERS);
- // traverse the ast using the visitor pattern.
- this.file = file;
- processAst(ast);
- } finally {
- this.file = null;
- index.releaseReadLock();
- }
- }
-
- public boolean processResource(IResource resource) {
- if (resource instanceof IFile) {
- IFile file = (IFile) resource;
- try {
- processFile(file);
- } catch (CoreException e) {
- CodanCorePlugin.log(e);
- } catch (InterruptedException e) {
- // ignore
- }
- return false;
- }
- return true;
- }
-
- public void reportProblem(String id, IASTNode astNode, String message) {
- IASTFileLocation astLocation = astNode.getFileLocation();
- IPath location = new Path(astLocation.getFileName());
- IFile astFile = ResourcesPlugin.getWorkspace().getRoot()
- .getFileForLocation(location);
- if (astFile == null) {
- astFile = file;
- }
- ProblemLocation loc;
- if (astLocation.getStartingLineNumber() == astLocation
- .getEndingLineNumber())
- loc = new ProblemLocation(astFile, astLocation.getNodeOffset(),
- astLocation.getNodeOffset() + astLocation.getNodeLength());
- else
- loc = new ProblemLocation(astFile, astLocation
- .getStartingLineNumber());
- getProblemReporter().reportProblem(id, loc, message);
- }
-
- @Override
- public boolean runInEditor() {
- return true;
- }
-}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractProblemLocation.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractProblemLocation.java
new file mode 100644
index 0000000..c2bcd2a
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/AbstractProblemLocation.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 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.model;
+
+import org.eclipse.core.resources.IFile;
+
+/**
+ * Abstract Implementation of IProblemLocation
+ *
+ * Clients may extend this class.
+ *
+ * EXPERIMENTAL. This class or interface has been added as
+ * part of a work in progress. There is no guarantee that this API will
+ * work or that it will remain the same.
+ *
+ */
+public abstract class AbstractProblemLocation implements IProblemLocation {
+ protected IFile file;
+ protected int line;
+ protected int posStart;
+ protected int posEnd;
+ protected Object extra;
+
+ protected AbstractProblemLocation(IFile file, int line) {
+ this.file = file;
+ this.line = line;
+ this.posStart = -1;
+ this.posEnd = -1;
+ }
+
+ protected AbstractProblemLocation(IFile file, int startChar, int endChar) {
+ this.file = file;
+ this.line = -1;
+ this.posStart = startChar;
+ this.posEnd = endChar;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.cdt.codan.core.model.IProblemLocation#getData()
+ */
+ public Object getData() {
+ return extra;
+ }
+
+ /**
+ * Sets extra data for the problem location
+ *
+ * @param data
+ */
+ public void setData(Object data) {
+ this.extra = data;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.cdt.codan.core.model.IProblemLocation#getFile()
+ */
+ public IFile getFile() {
+ return file;
+ }
+
+ /**
+ * Problem line number referenced in problem view in location field
+ */
+ public int getLineNumber() {
+ return getStartingLineNumber();
+ }
+
+ /**
+ * @return line number where problem starts
+ */
+ public int getStartingLineNumber() {
+ return line;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.cdt.codan.core.model.IProblemLocation#getStartPos()
+ */
+ public int getStartingChar() {
+ return posStart;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.cdt.codan.core.model.IProblemLocation#getEndingChar()
+ */
+ public int getEndingChar() {
+ return posEnd;
+ }
+}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/CVS/Entries b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/CVS/Entries
index 8635b9d..4315bc4 100644
--- a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/CVS/Entries
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/CVS/Entries
@@ -1,16 +1,19 @@
-/AbstractChecker.java/1.4/Sat Aug 22 21:31:29 2009//
-/AbstractIndexAstChecker.java/1.6/Wed Dec 16 21:48:48 2009//
-/CodanSeverity.java/1.2/Wed Apr 22 01:26:56 2009//
-/ICAstChecker.java/1.1/Thu Apr 9 12:46:50 2009//
-/IChecker.java/1.3/Wed Dec 16 21:48:48 2009//
-/ICheckersRegistry.java/1.1/Sat Aug 22 21:16:48 2009//
-/ICodanAstReconciler.java/1.1/Sat Aug 22 21:16:48 2009//
-/ICodanBuilder.java/1.1/Sat Aug 22 21:16:48 2009//
-/IProblem.java/1.4/Wed Dec 16 21:48:48 2009//
-/IProblemCategory.java/1.3/Wed Dec 16 21:48:48 2009//
-/IProblemElement.java/1.2/Wed Dec 16 21:48:48 2009//
-/IProblemLocation.java/1.1/Sat Aug 22 21:16:48 2009//
-/IProblemProfile.java/1.4/Wed Dec 16 21:48:48 2009//
-/IProblemReporter.java/1.2/Wed Dec 16 21:48:48 2009//
-/ProblemLocation.java/1.1/Sat Aug 22 21:16:48 2009//
-D
+/AbstractChecker.java/1.13/Sun Jun 27 01:30:41 2010//TCDT_7_0_0
+/AbstractCheckerWithProblemPreferences.java/1.5/Mon May 31 02:53:25 2010//TCDT_7_0_0
+/AbstractProblemLocation.java/1.3/Sun Jun 27 01:30:41 2010//TCDT_7_0_0
+/CodanSeverity.java/1.6/Sun Jun 27 01:30:41 2010//TCDT_7_0_0
+/IChecker.java/1.8/Sun Jun 27 01:30:41 2010//TCDT_7_0_0
+/ICheckerWithPreferences.java/1.3/Thu Jun 3 17:01:52 2010//TCDT_7_0_0
+/ICheckersRegistry.java/1.6/Sun Jun 27 01:30:41 2010//TCDT_7_0_0
+/ICodanBuilder.java/1.4/Sun Jun 27 01:30:41 2010//TCDT_7_0_0
+/IProblem.java/1.13/Sun Jun 27 01:30:41 2010//TCDT_7_0_0
+/IProblemCategory.java/1.7/Sun Jun 27 01:30:41 2010//TCDT_7_0_0
+/IProblemElement.java/1.4/Sun Jun 27 01:30:41 2010//TCDT_7_0_0
+/IProblemLocation.java/1.4/Sun Jun 27 01:30:41 2010//TCDT_7_0_0
+/IProblemLocationFactory.java/1.5/Sun Jun 27 01:30:41 2010//TCDT_7_0_0
+/IProblemProfile.java/1.8/Sun Jun 27 01:30:41 2010//TCDT_7_0_0
+/IProblemReporter.java/1.6/Sun Jun 27 01:30:41 2010//TCDT_7_0_0
+/IProblemReporterPersistent.java/1.3/Sun Jun 27 01:30:41 2010//TCDT_7_0_0
+/IProblemWorkingCopy.java/1.9/Sun Jun 27 01:30:41 2010//TCDT_7_0_0
+/IRunnableInEditorChecker.java/1.3/Sun Jun 27 01:30:41 2010//TCDT_7_0_0
+D/cfg////
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/CVS/Tag b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/CVS/Tag
new file mode 100644
index 0000000..49a449a
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/CVS/Tag
@@ -0,0 +1 @@
+NCDT_7_0_0
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/CodanSeverity.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/CodanSeverity.java
index acfa4d1..fb85718 100644
--- a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/CodanSeverity.java
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/CodanSeverity.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009 Alena Laskavaia
+ * Copyright (c) 2009, 2010 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
@@ -12,21 +12,40 @@ package org.eclipse.cdt.codan.core.model;
import org.eclipse.core.resources.IMarker;
+/**
+ *
+ * Represents Severity of the codan problem. It is directly mapped to markers
+ * severity.
+ *
+ */
public enum CodanSeverity {
- Info(IMarker.SEVERITY_INFO), Warning(IMarker.SEVERITY_WARNING), Error(
- IMarker.SEVERITY_ERROR);
+ /**
+ * Info severity
+ */
+ Info(IMarker.SEVERITY_INFO),
+ /**
+ * Warning severity
+ */
+ Warning(IMarker.SEVERITY_WARNING),
+ /**
+ * Error severity
+ */
+ Error(IMarker.SEVERITY_ERROR);
private int value;
private CodanSeverity(int value) {
this.value = value;
}
+ /**
+ * @return int value of the severity
+ */
public int intValue() {
return value;
}
/**
- * @return
+ * @return array of string value for all severities
*/
public static String[] stringValues() {
CodanSeverity[] values = values();
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/ICAstChecker.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/ICAstChecker.java
deleted file mode 100644
index 461c0fa..0000000
--- a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/ICAstChecker.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009 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.model;
-
-import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
-
-/**
- * @author Alena
- *
- */
-public interface ICAstChecker extends IChecker {
- void processAst(IASTTranslationUnit ast);
-}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IChecker.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IChecker.java
index 60f7cb2..f00fea0 100644
--- a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IChecker.java
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IChecker.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009 Alena Laskavaia
+ * Copyright (c) 2009, 2010 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
@@ -13,27 +13,48 @@ package org.eclipse.cdt.codan.core.model;
import org.eclipse.core.resources.IResource;
/**
- * Interface that checker must implement. CDT Checker must be able to process a resource.
+ * Interface that checker must implement (through extending directly or
+ * indirectly {@link AbstractChecker}.
+ *
+ *
+ * EXPERIMENTAL. This class or interface has been added as part
+ * of a work in progress. There is no guarantee that this API will work or that
+ * it will remain the same.
+ *
+ *
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
+ * Extend {@link AbstractChecker} class instead.
*/
public interface IChecker {
/**
* Main method that checker should implement that actually detects errors
- * @param resource - resource to run on
- * @return true if need to traverse children
+ *
+ * @param resource
+ * - resource to run on
+ * @return true if framework should traverse children of the resource and
+ * run this checkers on them again
*/
boolean processResource(IResource resource);
/**
- * Implement this method to trim down type of resource you are interested in,
- * usually it will be c/c++ files only
+ * Implement this method to trim down type of resource you are interested
+ * in, usually it will be c/c++ files only. This method should be
+ * independent from current user preferences.
+ *
* @param resource
- * @return
+ * - resource to run on
+ * @return - true if checker should be run on this resource
*/
boolean enabledInContext(IResource resource);
/**
* Checker must implement this method to determine if it can run in editor
- * "as you type", checker must be really light weight to run in this mode
+ * "as you type". Checker must be really light weight to run in this mode.
+ * If it returns true, checker must also implement
+ * {@link IRunnableInEditorChecker}.
+ * Checker should return false if check is non-trivial and takes a long
+ * time.
*
* @return true if need to be run in editor as user types, and false
* otherwise
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/ICheckerWithPreferences.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/ICheckerWithPreferences.java
new file mode 100644
index 0000000..56619cb
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/ICheckerWithPreferences.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 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.model;
+
+/**
+ * Interface for checker with parameters, if checker implements this interface
+ * method would be called on initialization so checker has a chance to set
+ * default values for its parameters. It is recommended to use
+ * {@link AbstractCheckerWithProblemPreferences} insted of implementing it
+ * directly.
+ * EXPERIMENTAL. This class or interface has been added as part
+ * of a work in progress. There is no guarantee that this API will work or that
+ * it will remain the same.
+ *
+ *
+ * @noextend This interface is not intended to be extended by clients.
+ */
+public interface ICheckerWithPreferences {
+ /**
+ * Implement this method to set default parameters for checkers with
+ * parameters.
+ *
+ * @param problem
+ * - instance of problem working copy
+ */
+ void initPreferences(IProblemWorkingCopy problem);
+}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/ICheckersRegistry.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/ICheckersRegistry.java
index 052d868..04189ae 100644
--- a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/ICheckersRegistry.java
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/ICheckersRegistry.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009 Alena Laskavaia
+ * Copyright (c) 2009, 2010 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
@@ -10,57 +10,125 @@
*******************************************************************************/
package org.eclipse.cdt.codan.core.model;
+import java.util.Collection;
import java.util.Iterator;
import org.eclipse.core.resources.IResource;
/**
- * @author Alena
+ * This interface an API to add/remove checker and problems programmatically,
+ * get problem profiles and change problem default settings
+ *
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
*
*/
-public interface ICheckersRegistry {
- public abstract Iterator iterator();
+public interface ICheckersRegistry extends Iterable {
+ /**
+ * Iterator for registered checkers
+ *
+ * @return iterator for registered checkers
+ */
+ public Iterator iterator();
+
+ /**
+ * Add a checker
+ *
+ * @param checker instance
+ */
+ public void addChecker(IChecker checker);
- public abstract void addChecker(IChecker checker);
+ /**
+ * Add problem p into a category defined by a category id into default
+ * profile, category must exists in default profile
+ *
+ * @param p
+ * - problem
+ * @param categoryId
+ * - category id
+ */
+ public void addProblem(IProblem p, String categoryId);
- public abstract void addProblem(IProblem p, String category);
+ /**
+ * Add subcategory category into parent category with the id of
+ * parentCategoryId, if parent does not exist in the default profile or it
+ * is a null - it will be added to the root
+ *
+ * @param category
+ * - new category
+ * @param parentCategoryId
+ * - parent category id
+ */
+ public abstract void addCategory(IProblemCategory category,
+ String parentCategoryId);
- public abstract void addCategory(IProblemCategory p, String category);
+ /**
+ * Add problem reference to a checker, i.e. claim that checker can produce
+ * this problem. If checker does not claim any problems it cannot be
+ * enabled.
+ *
+ * @param c
+ * - checker
+ * @param p
+ * - problem
+ */
+ public void addRefProblem(IChecker c, IProblem p);
- public abstract void addRefProblem(IChecker c, IProblem p);
+ /**
+ * Return collection of problem that this checker can produce
+ *
+ * @param checker
+ * @return collection of problems
+ */
+ public Collection getRefProblems(IChecker checker);
/**
- * @return
+ * Default profile is kind of "Installation Default".
+ * Always the same, comes from defaults in checker extensions or APIs added
+ *
+ * @return default profile
*/
- public abstract IProblemProfile getDefaultProfile();
+ public IProblemProfile getDefaultProfile();
/**
- * @return
+ * Get workspace profile. User can change setting for workspace profile.
+ *
+ * @return workspace profile
*/
- public abstract IProblemProfile getWorkspaceProfile();
+ public IProblemProfile getWorkspaceProfile();
/**
+ * Get resource profile. For example given project can have different
+ * profile than a workspace.
+ *
* @param element
- * @return
+ * - resource
+ * @return resource profile
*/
- public abstract IProblemProfile getResourceProfile(IResource element);
+ public IProblemProfile getResourceProfile(IResource element);
/**
+ * Returns profile working copy for given resource element. (If profile is
+ * not specified for given element it will search for parent resource and so
+ * on). If you planning on editing it this method should be used instead of
+ * getResourceProfile. You have to save your changes after updating a
+ * working copy, using {@link #updateProfile(IResource, IProblemProfile)}
+ * method.
+ *
+ * @noreference This method is not intended to be referenced by clients.
* @param element
- * @return
+ * @return resource profile
*/
- public abstract IProblemProfile getResourceProfileWorkingCopy(
- IResource element);
+ public IProblemProfile getResourceProfileWorkingCopy(IResource element);
/**
- * Set profile for resource. This method is called by UI, and should not be
- * called by clients directly
+ * Set profile for resource.
*
+ * @noreference This method is not intended to be referenced by clients.
* @param resource
- * - resource
+ * - resource
* @param profile
- * - problems profile
+ * - problems profile
*/
- public abstract void updateProfile(IResource resource,
- IProblemProfile profile);
+ public void updateProfile(IResource resource, IProblemProfile profile);
}
\ No newline at end of file
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/ICodanAstReconciler.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/ICodanAstReconciler.java
deleted file mode 100644
index 17bc8f7..0000000
--- a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/ICodanAstReconciler.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009 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.model;
-
-import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
-import org.eclipse.core.runtime.IProgressMonitor;
-
-/**
- * @author Alena
- *
- */
-public interface ICodanAstReconciler {
- public void reconcileAst(IASTTranslationUnit ast, IProgressMonitor monitor);
-}
\ No newline at end of file
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/ICodanBuilder.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/ICodanBuilder.java
index ce1f668..dcbe4c3 100644
--- a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/ICodanBuilder.java
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/ICodanBuilder.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009 Alena Laskavaia
+ * Copyright (c) 2009, 2010 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
@@ -14,9 +14,20 @@ import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IProgressMonitor;
/**
- * @author Alena
+ * Interface for "Codan Builder". Clients can call processResource method to
+ * traverse the resource tree. It will be calling all the checkers (this
+ * interface allows to call framework without using UI). You can obtain instance
+ * of this class as CodanRuntime.getInstance().getBuilder()
*
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
*/
public interface ICodanBuilder {
+ /**
+ * Run code analysis on given resource
+ *
+ * @param resource - resource to process
+ * @param monitor - progress monitor
+ */
public void processResource(IResource resource, IProgressMonitor monitor);
}
\ No newline at end of file
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IProblem.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IProblem.java
index bbab313..d12806d 100644
--- a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IProblem.java
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/core/model/IProblem.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009 Alena Laskavaia
+ * Copyright (c) 2009, 2010 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
@@ -10,56 +10,82 @@
*******************************************************************************/
package org.eclipse.cdt.codan.core.model;
-import java.util.Collection;
+import org.eclipse.cdt.codan.core.param.IProblemPreference;
/**
- * Interface representing code analysis problem
- *
+ * Interface representing code analysis problem type. For example
+ * "Null Pointer Dereference" is a problem. It has user visible Name and Message
+ * (translatable), as well as some other parameters, changeable by user such as
+ * enablement, severity and so on. Same problem cannot have two severities
+ * determined by runtime. If it is the case - two Problems should be created
+ * (i.e. one for error and one for warning). All of problem attributes are
+ * defined in a checker extension point.
+ *
+ *
+ * EXPERIMENTAL. This class or interface has been added as part
+ * of a work in progress. There is no guarantee that this API will work or that
+ * it will remain the same.
+ *
+ *
+ * @noextend This interface is not intended to be extended by clients.
+ * @noimplement This interface is not intended to be implemented by clients.
*/
public interface IProblem extends IProblemElement {
/**
* Name of the problem - user visible "title", not the message
+ *
+ * @return title of the problem
*/
String getName();
/**
- * Unique problem id. Should be qualified by plugin name to maintain uniqueness.
- * @return
+ * Unique problem id. Should be qualified by plugin name to maintain
+ * uniqueness.
+ *
+ * @return unique problem id
*/
String getId();
/**
* Is enabled in current context (usually within profile)
+ *
* @return true if enabled
*/
boolean isEnabled();
/**
* Get current severity
+ *
* @return severity
*/
CodanSeverity getSeverity();
/**
* Message pattern, java patter like 'Variable {0} is never used here'
- * @return pattern
+ *
+ * @return pattern
*/
String getMessagePattern();
- void setSeverity(CodanSeverity sev);
-
- void setEnabled(boolean checked);
-
- void setMessagePattern(String message);
-
- public void setProperty(Object key, Object value);
+ /**
+ * Get root preference descriptor or null if not defined (used by ui to
+ * generate user controls for changing parameters)
+ *
+ * @return root preference or null
+ */
+ public IProblemPreference getPreference();
/**
- * Get custom property
- * @param property name
- * @return property object
+ * Get short description of a problem
+ *
+ * @return description
*/
- public Object getProperty(Object key);
+ public String getDescription();
- public Collection
+ *
+ * @param array
+ * the given array
+ * @param prefix
+ * the given prefix
+ * @return the result of the comparison
+ * @exception NullPointerException
+ * if either array or prefix is null
+ */
+ public static final int compareWith(char[] array, char[] prefix) {
+ int arrayLength = array.length;
+ int prefixLength = prefix.length;
+ int min = Math.min(arrayLength, prefixLength);
+ int i = 0;
+ while (min-- != 0) {
+ char c1 = array[i];
+ char c2 = prefix[i++];
+ if (c1 != c2)
+ return c1 - c2;
+ }
+ if (prefixLength == i)
+ return 0;
+ return 1;
+ }
+
+ /**
+ * Answers the concatenation of the two arrays. It answers null if the two
+ * arrays are null.
+ * If the first array is null, then the second array is returned.
+ * If the second array is null, then the first array is returned.
+ *
+ *
+ * For example:
+ *
+ *
+ * first = null
+ * second = { 'a' }
+ * => result = { ' a' }
+ *
+ *
+ *
+ * first = { ' a' }
+ * second = null
+ * => result = { ' a' }
+ *
+ *
+ *
+ * first = { ' a' }
+ * second = { ' b' }
+ * => result = { ' a' , ' b' }
+ *
+ *
+ *
+ *
+ * @param first
+ * the first array to concatenate
+ * @param second
+ * the second array to concatenate
+ * @return the concatenation of the two arrays, or null if the two arrays
+ * are null.
+ */
+ public static final char[] concat(char[] first, char[] second) {
+ if (first == null)
+ return second;
+ if (second == null)
+ return first;
+ int length1 = first.length;
+ int length2 = second.length;
+ char[] result = new char[length1 + length2];
+ System.arraycopy(first, 0, result, 0, length1);
+ System.arraycopy(second, 0, result, length1, length2);
+ return result;
+ }
+
+ /**
+ * Answers the concatenation of the three arrays. It answers null if the
+ * three arrays are null.
+ * If first is null, it answers the concatenation of second and third.
+ * If second is null, it answers the concatenation of first and third.
+ * If third is null, it answers the concatenation of first and second.
+ *
+ *
+ * For example:
+ *
+ *
+ * first = null
+ * second = { 'a' }
+ * third = { 'b' }
+ * => result = { ' a', 'b' }
+ *
+ *
+ *
+ * first = { 'a' }
+ * second = null
+ * third = { 'b' }
+ * => result = { ' a', 'b' }
+ *
+ *
+ *
+ * first = { 'a' }
+ * second = { 'b' }
+ * third = null
+ * => result = { ' a', 'b' }
+ *
+ *
+ *
+ * first = null
+ * second = null
+ * third = null
+ * => result = null
+ *
+ *
+ *
+ * first = { 'a' }
+ * second = { 'b' }
+ * third = { 'c' }
+ * => result = { 'a', 'b', 'c' }
+ *
+ *
+ *
+ *
+ * @param first
+ * the first array to concatenate
+ * @param second
+ * the second array to concatenate
+ * @param third
+ * the third array to concatenate
+ *
+ * @return the concatenation of the three arrays, or null if the three
+ * arrays are null.
+ */
+ public static final char[] concat(char[] first, char[] second, char[] third) {
+ if (first == null)
+ return concat(second, third);
+ if (second == null)
+ return concat(first, third);
+ if (third == null)
+ return concat(first, second);
+ int length1 = first.length;
+ int length2 = second.length;
+ int length3 = third.length;
+ char[] result = new char[length1 + length2 + length3];
+ System.arraycopy(first, 0, result, 0, length1);
+ System.arraycopy(second, 0, result, length1, length2);
+ System.arraycopy(third, 0, result, length1 + length2, length3);
+ return result;
+ }
+
+ /**
+ * Answers the concatenation of the two arrays inserting the separator
+ * character between the two arrays.
+ * It answers null if the two arrays are null.
+ * If the first array is null, then the second array is returned.
+ * If the second array is null, then the first array is returned.
+ *
+ *
+ * For example:
+ *
+ *
+ * first = null
+ * second = { 'a' }
+ * separator = '/'
+ * => result = { ' a' }
+ *
+ *
+ *
+ * first = { ' a' }
+ * second = null
+ * separator = '/'
+ * => result = { ' a' }
+ *
+ *
+ *
+ * first = { ' a' }
+ * second = { ' b' }
+ * separator = '/'
+ * => result = { ' a' , '/', 'b' }
+ *
+ *
+ *
+ *
+ * @param first
+ * the first array to concatenate
+ * @param second
+ * the second array to concatenate
+ * @param separator
+ * the character to insert
+ * @return the concatenation of the two arrays inserting the separator
+ * character
+ * between the two arrays , or null if the two arrays are null.
+ */
+ public static final char[] concat(char[] first, char[] second,
+ char separator) {
+ if (first == null)
+ return second;
+ if (second == null)
+ return first;
+ int length1 = first.length;
+ if (length1 == 0)
+ return second;
+ int length2 = second.length;
+ if (length2 == 0)
+ return first;
+ char[] result = new char[length1 + length2 + 1];
+ System.arraycopy(first, 0, result, 0, length1);
+ result[length1] = separator;
+ System.arraycopy(second, 0, result, length1 + 1, length2);
+ return result;
+ }
+
+ /**
+ * Answers the concatenation of the three arrays inserting the sep1
+ * character between the
+ * two arrays and sep2 between the last two.
+ * It answers null if the three arrays are null.
+ * If the first array is null, then it answers the concatenation of second
+ * and third inserting
+ * the sep2 character between them.
+ * If the second array is null, then it answers the concatenation of first
+ * and third inserting
+ * the sep1 character between them.
+ * If the third array is null, then it answers the concatenation of first
+ * and second inserting
+ * the sep1 character between them.
+ *
+ *
+ * For example:
+ *
+ *
+ * first = null
+ * sep1 = '/'
+ * second = { 'a' }
+ * sep2 = ':'
+ * third = { 'b' }
+ * => result = { ' a' , ':', 'b' }
+ *
+ *
+ *
+ * first = { 'a' }
+ * sep1 = '/'
+ * second = null
+ * sep2 = ':'
+ * third = { 'b' }
+ * => result = { ' a' , '/', 'b' }
+ *
+ *
+ *
+ * first = { 'a' }
+ * sep1 = '/'
+ * second = { 'b' }
+ * sep2 = ':'
+ * third = null
+ * => result = { ' a' , '/', 'b' }
+ *
+ *
+ *
+ * first = { 'a' }
+ * sep1 = '/'
+ * second = { 'b' }
+ * sep2 = ':'
+ * third = { 'c' }
+ * => result = { ' a' , '/', 'b' , ':', 'c' }
+ *
+ *
+ *
+ *
+ * @param first
+ * the first array to concatenate
+ * @param sep1
+ * the character to insert
+ * @param second
+ * the second array to concatenate
+ * @param sep2
+ * the character to insert
+ * @param third
+ * the second array to concatenate
+ * @return the concatenation of the three arrays inserting the sep1
+ * character between the
+ * two arrays and sep2 between the last two.
+ */
+ public static final char[] concat(char[] first, char sep1, char[] second,
+ char sep2, char[] third) {
+ if (first == null)
+ return concat(second, third, sep2);
+ if (second == null)
+ return concat(first, third, sep1);
+ if (third == null)
+ return concat(first, second, sep1);
+ int length1 = first.length;
+ int length2 = second.length;
+ int length3 = third.length;
+ char[] result = new char[length1 + length2 + length3 + 2];
+ System.arraycopy(first, 0, result, 0, length1);
+ result[length1] = sep1;
+ System.arraycopy(second, 0, result, length1 + 1, length2);
+ result[length1 + length2 + 1] = sep2;
+ System.arraycopy(third, 0, result, length1 + length2 + 2, length3);
+ return result;
+ }
+
+ /**
+ * Answers a new array with prepending the prefix character and appending
+ * the suffix
+ * character at the end of the array. If array is null, it answers a new
+ * array containing the
+ * prefix and the suffix characters.
+ *
+ *
+ * For example:
+ *
+ *
+ *
+ *
+ * @param prefix
+ * the prefix character
+ * @param array
+ * the array that is concanated with the prefix and suffix
+ * characters
+ * @param suffix
+ * the suffix character
+ * @return the new array
+ */
+ public static final char[] concat(char prefix, char[] array, char suffix) {
+ if (array == null)
+ return new char[] { prefix, suffix };
+ int length = array.length;
+ char[] result = new char[length + 2];
+ result[0] = prefix;
+ System.arraycopy(array, 0, result, 1, length);
+ result[length + 1] = suffix;
+ return result;
+ }
+
+ /**
+ * Answers the concatenation of the given array parts using the given
+ * separator between each
+ * part and appending the given name at the end.
+ *
+ *
+ * For example:
+ *
+ *
+ * name = { ' c' }
+ * array = null
+ * separator = '.'
+ * => result = { 'c' }
+ *
+ *
+ *
+ * @param name
+ * the given name
+ * @param array
+ * the given array
+ * @param separator
+ * the given separator
+ * @return the concatenation of the given array parts using the given
+ * separator between each
+ * part and appending the given name at the end
+ */
+ public static final char[] concatWith(char[] name, char[][] array,
+ char separator) {
+ int nameLength = name == null ? 0 : name.length;
+ if (nameLength == 0)
+ return concatWith(array, separator);
+ if (array == null)
+ return name;
+ final int length = array.length;
+ if (length == 0)
+ return name;
+ int size = nameLength;
+ int index = length;
+ while (--index >= 0)
+ if (array[index].length > 0)
+ size += array[index].length + 1;
+ char[] result = new char[size];
+ index = size;
+ for (int i = length - 1; i >= 0; i--) {
+ int subLength = array[i].length;
+ if (subLength > 0) {
+ index -= subLength;
+ System.arraycopy(array[i], 0, result, index, subLength);
+ result[--index] = separator;
+ }
+ }
+ System.arraycopy(name, 0, result, 0, nameLength);
+ return result;
+ }
+
+ /**
+ * Answers the concatenation of the given array parts using the given
+ * separator between each
+ * part and appending the given name at the end.
+ *
+ *
+ * For example:
+ *
+ *
+ * name = { ' c' }
+ * array = null
+ * separator = '.'
+ * => result = { 'c' }
+ *
+ *
+ *
+ * @param array
+ * the given array
+ * @param name
+ * the given name
+ * @param separator
+ * the given separator
+ * @return the concatenation of the given array parts using the given
+ * separator between each
+ * part and appending the given name at the end
+ */
+ public static final char[] concatWith(char[][] array, char[] name,
+ char separator) {
+ int nameLength = name == null ? 0 : name.length;
+ if (nameLength == 0)
+ return concatWith(array, separator);
+ if (array == null)
+ return name;
+ final int length = array.length;
+ if (length == 0)
+ return name;
+ int size = nameLength;
+ int index = length;
+ while (--index >= 0)
+ if (array[index].length > 0)
+ size += array[index].length + 1;
+ char[] result = new char[size];
+ index = 0;
+ for (int i = 0; i < length; i++) {
+ int subLength = array[i].length;
+ if (subLength > 0) {
+ System.arraycopy(array[i], 0, result, index, subLength);
+ index += subLength;
+ result[index++] = separator;
+ }
+ }
+ System.arraycopy(name, 0, result, index, nameLength);
+ return result;
+ }
+
+ /**
+ * Answers the concatenation of the given array parts using the given
+ * separator between each part.
+ *
+ *
+ * For example:
+ *
+ *
+ *
+ *
+ * @param array
+ * the given array
+ * @param separator
+ * the given separator
+ * @return the concatenation of the given array parts using the given
+ * separator between each part
+ */
+ public static final char[] concatWith(char[][] array, char separator) {
+ if (array == null)
+ return CharOperation.NO_CHAR;
+ int length = array.length;
+ if (length == 0)
+ return CharOperation.NO_CHAR;
+ int size = length - 1;
+ int index = length;
+ while (--index >= 0) {
+ if (array[index].length == 0)
+ size--;
+ else
+ size += array[index].length;
+ }
+ if (size <= 0)
+ return CharOperation.NO_CHAR;
+ char[] result = new char[size];
+ index = length;
+ while (--index >= 0) {
+ length = array[index].length;
+ if (length > 0) {
+ System.arraycopy(array[index], 0, result, (size -= length),
+ length);
+ if (--size >= 0)
+ result[size] = separator;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Answers true if the array contains an occurrence of character, false
+ * otherwise.
+ *
+ *
+ *
+ * For example:
+ *
+ *
+ * character = 'c'
+ * array = { { ' a' }, { ' b' } }
+ * result => false
+ *
+ *
+ *
+ * character = 'a'
+ * array = { { ' a' }, { ' b' } }
+ * result => true
+ *
+ *
+ *
+ *
+ * @param character
+ * the character to search
+ * @param array
+ * the array in which the search is done
+ * @return true if the array contains an occurrence of character, false
+ * otherwise.
+ * @exception NullPointerException
+ * if array is null.
+ */
+ public static final boolean contains(char character, char[][] array) {
+ for (int i = array.length; --i >= 0;) {
+ char[] subarray = array[i];
+ for (int j = subarray.length; --j >= 0;)
+ if (subarray[j] == character)
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Answers true if the array contains an occurrence of character, false
+ * otherwise.
+ *
+ *
+ *
+ * For example:
+ *
+ *
+ * character = 'c'
+ * array = { ' b' }
+ * result => false
+ *
+ *
+ *
+ * character = 'a'
+ * array = { ' a' , ' b' }
+ * result => true
+ *
+ *
+ *
+ *
+ * @param character
+ * the character to search
+ * @param array
+ * the array in which the search is done
+ * @return true if the array contains an occurrence of character, false
+ * otherwise.
+ * @exception NullPointerException
+ * if array is null.
+ */
+ public static final boolean contains(char character, char[] array) {
+ for (int i = array.length; --i >= 0;)
+ if (array[i] == character)
+ return true;
+ return false;
+ }
+
+ /**
+ * Answers a deep copy of the toCopy array.
+ *
+ * @param toCopy
+ * the array to copy
+ * @return a deep copy of the toCopy array.
+ */
+ public static final char[][] deepCopy(char[][] toCopy) {
+ int toCopyLength = toCopy.length;
+ char[][] result = new char[toCopyLength][];
+ for (int i = 0; i < toCopyLength; i++) {
+ char[] toElement = toCopy[i];
+ int toElementLength = toElement.length;
+ char[] resultElement = new char[toElementLength];
+ System.arraycopy(toElement, 0, resultElement, 0, toElementLength);
+ result[i] = resultElement;
+ }
+ return result;
+ }
+
+ /**
+ * Return true if array ends with the sequence of characters contained in
+ * toBeFound,
+ * otherwise false.
+ *
+ *
+ * For example:
+ *
+ *
+ *
+ *
+ * @param array
+ * the array to check
+ * @param toBeFound
+ * the array to find
+ * @return true if array ends with the sequence of characters contained in
+ * toBeFound,
+ * otherwise false.
+ * @exception NullPointerException
+ * if array is null or toBeFound is null
+ */
+ public static final boolean endsWith(char[] array, char[] toBeFound) {
+ int i = toBeFound.length;
+ int j = array.length - i;
+ if (j < 0)
+ return false;
+ while (--i >= 0)
+ if (toBeFound[i] != array[i + j])
+ return false;
+ return true;
+ }
+
+ /**
+ * Answers true if the two arrays are identical character by character,
+ * otherwise false.
+ * The equality is case sensitive.
+ *
+ *
+ * For example:
+ *
+ *
+ * first = null
+ * second = null
+ * result => true
+ *
+ *
+ *
+ * first = { { } }
+ * second = null
+ * result => false
+ *
+ *
+ *
+ * first = { { 'a' } }
+ * second = { { 'a' } }
+ * result => true
+ *
+ *
+ *
+ * first = { { 'A' } }
+ * second = { { 'a' } }
+ * result => false
+ *
+ *
+ *
+ *
+ * @param first
+ * the first array
+ * @param second
+ * the second array
+ * @return true if the two arrays are identical character by character,
+ * otherwise false
+ */
+ public static final boolean equals(char[][] first, char[][] second) {
+ if (first == second)
+ return true;
+ if (first == null || second == null)
+ return false;
+ if (first.length != second.length)
+ return false;
+ for (int i = first.length; --i >= 0;)
+ if (!equals(first[i], second[i]))
+ return false;
+ return true;
+ }
+
+ /**
+ * If isCaseSensite is true, answers true if the two arrays are identical
+ * character
+ * by character, otherwise false.
+ * If it is false, answers true if the two arrays are identical character by
+ * character without checking the case, otherwise false.
+ *
+ *
+ * For example:
+ *
+ *
+ * first = null
+ * second = null
+ * isCaseSensitive = true
+ * result => true
+ *
+ *
+ *
+ * first = { { } }
+ * second = null
+ * isCaseSensitive = true
+ * result => false
+ *
+ *
+ *
+ * first = { { 'A' } }
+ * second = { { 'a' } }
+ * isCaseSensitive = true
+ * result => false
+ *
+ *
+ *
+ * first = { { 'A' } }
+ * second = { { 'a' } }
+ * isCaseSensitive = false
+ * result => true
+ *
+ *
+ *
+ *
+ * @param first
+ * the first array
+ * @param second
+ * the second array
+ * @param isCaseSensitive
+ * check whether or not the equality should be case sensitive
+ * @return true if the two arrays are identical character by character
+ * according to the value
+ * of isCaseSensitive, otherwise false
+ */
+ public static final boolean equals(char[][] first, char[][] second,
+ boolean isCaseSensitive) {
+ if (isCaseSensitive) {
+ return equals(first, second);
+ }
+ if (first == second)
+ return true;
+ if (first == null || second == null)
+ return false;
+ if (first.length != second.length)
+ return false;
+ for (int i = first.length; --i >= 0;)
+ if (!equals(first[i], second[i], false))
+ return false;
+ return true;
+ }
+
+ /**
+ * Answers true if the two arrays are identical character by character,
+ * otherwise false.
+ * The equality is case sensitive.
+ *
+ *
+ * For example:
+ *
+ *
+ * first = null
+ * second = null
+ * result => true
+ *
+ *
+ *
+ * first = { }
+ * second = null
+ * result => false
+ *
+ *
+ *
+ * first = { 'a' }
+ * second = { 'a' }
+ * result => true
+ *
+ *
+ *
+ * first = { 'a' }
+ * second = { 'A' }
+ * result => false
+ *
+ *
+ *
+ *
+ * @param first
+ * the first array
+ * @param second
+ * the second array
+ * @return true if the two arrays are identical character by character,
+ * otherwise false
+ */
+ public static final boolean equals(char[] first, char[] second) {
+ if (first == second)
+ return true;
+ if (first == null || second == null)
+ return false;
+ if (first.length != second.length)
+ return false;
+ for (int i = first.length; --i >= 0;)
+ if (first[i] != second[i])
+ return false;
+ return true;
+ }
+
+ /**
+ * If isCaseSensite is true, answers true if the two arrays are identical
+ * character
+ * by character, otherwise false.
+ * If it is false, answers true if the two arrays are identical character by
+ * character without checking the case, otherwise false.
+ *
+ *
+ * For example:
+ *
+ *
+ * first = null
+ * second = null
+ * isCaseSensitive = true
+ * result => true
+ *
+ *
+ *
+ * first = { }
+ * second = null
+ * isCaseSensitive = true
+ * result => false
+ *
+ *
+ *
+ * first = { 'A' }
+ * second = { 'a' }
+ * isCaseSensitive = true
+ * result => false
+ *
+ *
+ *
+ * first = { 'A' }
+ * second = { 'a' }
+ * isCaseSensitive = false
+ * result => true
+ *
+ *
+ *
+ *
+ * @param first
+ * the first array
+ * @param second
+ * the second array
+ * @param isCaseSensitive
+ * check whether or not the equality should be case sensitive
+ * @return true if the two arrays are identical character by character
+ * according to the value
+ * of isCaseSensitive, otherwise false
+ */
+ public static final boolean equals(char[] first, char[] second,
+ boolean isCaseSensitive) {
+ if (isCaseSensitive) {
+ return equals(first, second);
+ }
+ if (first == second)
+ return true;
+ if (first == null || second == null)
+ return false;
+ if (first.length != second.length)
+ return false;
+ for (int i = first.length; --i >= 0;)
+ if (Character.toLowerCase(first[i]) != Character
+ .toLowerCase(second[i]))
+ return false;
+ return true;
+ }
+
+ /**
+ * If isCaseSensite is true, the equality is case sensitive, otherwise it is
+ * case insensitive.
+ *
+ * Answers true if the name contains the fragment at the starting index
+ * startIndex, otherwise false.
+ *
+ *
+ * For example:
+ *
+ *
+ *
+ *
+ * @param fragment
+ * the fragment to check
+ * @param name
+ * the array to check
+ * @param startIndex
+ * the starting index
+ * @param isCaseSensitive
+ * check whether or not the equality should be case sensitive
+ * @return true if the name contains the fragment at the starting index
+ * startIndex according to the
+ * value of isCaseSensitive, otherwise false.
+ * @exception NullPointerException
+ * if fragment or name is null.
+ */
+ public static final boolean fragmentEquals(char[] fragment, char[] name,
+ int startIndex, boolean isCaseSensitive) {
+ int max = fragment.length;
+ if (name.length < max + startIndex)
+ return false;
+ if (isCaseSensitive) {
+ for (int i = max; --i >= 0;)
+ // assumes the prefix is not larger than the name
+ if (fragment[i] != name[i + startIndex])
+ return false;
+ return true;
+ }
+ for (int i = max; --i >= 0;)
+ // assumes the prefix is not larger than the name
+ if (Character.toLowerCase(fragment[i]) != Character
+ .toLowerCase(name[i + startIndex]))
+ return false;
+ return true;
+ }
+
+ /**
+ * Answers a hashcode for the array
+ *
+ * @param array
+ * the array for which a hashcode is required
+ * @return the hashcode
+ * @exception NullPointerException
+ * if array is null
+ */
+ public static final int hashCode(char[] array) {
+ int hash = 0;
+ int offset = 0;
+ int length = array.length;
+ if (length < 16) {
+ for (int i = length; i > 0; i--)
+ hash = (hash * 37) + array[offset++];
+ } else {
+ // only sample some characters
+ int skip = length / 8;
+ for (int i = length; i > 0; i -= skip, offset += skip)
+ hash = (hash * 39) + array[offset];
+ }
+ return hash & 0x7FFFFFFF;
+ }
+
+ /**
+ * Answers true if c is a whitespace according to the JLS (\u000a,
+ * \u000c, \u000d, \u0009), otherwise false.
+ *
+ *
+ * For example:
+ *
+ *
+ * c = ' '
+ * result => true
+ *
+ *
+ *
+ * c = '\u3000'
+ * result => false
+ *
+ *
+ *
+ *
+ * @param c
+ * the character to check
+ * @return true if c is a whitespace according to the JLS, otherwise false.
+ */
+ public static boolean isWhitespace(char c) {
+ switch (c) {
+ case 10: /* \ u000a: LINE FEED */
+ case 12: /* \ u000c: FORM FEED */
+ case 13: /* \ u000d: CARRIAGE RETURN */
+ case 32: /* \ u0020: SPACE */
+ case 9: /* \ u0009: HORIZONTAL TABULATION */
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Answers the first index in the array for which the corresponding
+ * character is
+ * equal to toBeFound. Answers -1 if no occurrence of this character is
+ * found.
+ *
+ *
+ * For example:
+ *
+ *
+ *
+ *
+ * @param toBeFound
+ * the character to search
+ * @param array
+ * the array to be searched
+ * @return the first index in the array for which the corresponding
+ * character is
+ * equal to toBeFound, -1 otherwise
+ * @exception NullPointerException
+ * if array is null
+ */
+ public static final int indexOf(char toBeFound, char[] array) {
+ for (int i = 0; i < array.length; i++)
+ if (toBeFound == array[i])
+ return i;
+ return -1;
+ }
+
+ /**
+ * Answers the first index in the array for which the corresponding
+ * character is
+ * equal to toBeFound starting the search at index start.
+ * Answers -1 if no occurrence of this character is found.
+ *
+ *
+ * For example:
+ *
+ *
+ *
+ *
+ * @param toBeFound
+ * the character to search
+ * @param array
+ * the array to be searched
+ * @param start
+ * the starting index
+ * @return the first index in the array for which the corresponding
+ * character is
+ * equal to toBeFound, -1 otherwise
+ * @exception NullPointerException
+ * if array is null
+ * @exception ArrayIndexOutOfBoundsException
+ * if start is lower than 0
+ */
+ public static final int indexOf(char toBeFound, char[] array, int start) {
+ for (int i = start; i < array.length; i++)
+ if (toBeFound == array[i])
+ return i;
+ return -1;
+ }
+
+ /**
+ * Answers the last index in the array for which the corresponding character
+ * is
+ * equal to toBeFound starting from the end of the array.
+ * Answers -1 if no occurrence of this character is found.
+ *
+ *
+ * For example:
+ *
+ *
+ *
+ *
+ * @param toBeFound
+ * the character to search
+ * @param array
+ * the array to be searched
+ * @return the last index in the array for which the corresponding character
+ * is
+ * equal to toBeFound starting from the end of the array, -1
+ * otherwise
+ * @exception NullPointerException
+ * if array is null
+ */
+ public static final int lastIndexOf(char toBeFound, char[] array) {
+ for (int i = array.length; --i >= 0;)
+ if (toBeFound == array[i])
+ return i;
+ return -1;
+ }
+
+ /**
+ * Answers the last index in the array for which the corresponding character
+ * is
+ * equal to toBeFound stopping at the index startIndex.
+ * Answers -1 if no occurrence of this character is found.
+ *
+ *
+ * For example:
+ *
+ *
+ *
+ *
+ * @param toBeFound
+ * the character to search
+ * @param array
+ * the array to be searched
+ * @param startIndex
+ * the stopping index
+ * @return the last index in the array for which the corresponding character
+ * is
+ * equal to toBeFound stopping at the index startIndex, -1 otherwise
+ * @exception NullPointerException
+ * if array is null
+ * @exception ArrayIndexOutOfBoundsException
+ * if startIndex is lower than 0
+ */
+ public static final int lastIndexOf(char toBeFound, char[] array,
+ int startIndex) {
+ for (int i = array.length; --i >= startIndex;)
+ if (toBeFound == array[i])
+ return i;
+ return -1;
+ }
+
+ /**
+ * Answers the last index in the array for which the corresponding character
+ * is
+ * equal to toBeFound starting from endIndex to startIndex.
+ * Answers -1 if no occurrence of this character is found.
+ *
+ *
+ * For example:
+ *
+ *
+ *
+ *
+ * @param toBeFound
+ * the character to search
+ * @param array
+ * the array to be searched
+ * @param startIndex
+ * the stopping index
+ * @param endIndex
+ * the starting index
+ * @return the last index in the array for which the corresponding character
+ * is
+ * equal to toBeFound starting from endIndex to startIndex, -1
+ * otherwise
+ * @exception NullPointerException
+ * if array is null
+ * @exception ArrayIndexOutOfBoundsException
+ * if endIndex is greater or equals to array length or
+ * starting is lower than 0
+ */
+ public static final int lastIndexOf(char toBeFound, char[] array,
+ int startIndex, int endIndex) {
+ for (int i = endIndex; --i >= startIndex;)
+ if (toBeFound == array[i])
+ return i;
+ return -1;
+ }
+
+ /**
+ * Answers the last portion of a name given a separator.
+ *
+ *
+ * For example,
+ *
+ *
+ * @param array
+ * the array
+ * @param separator
+ * the given separator
+ * @return the last portion of a name given a separator
+ * @exception NullPointerException
+ * if array is null
+ */
+ final static public char[] lastSegment(char[] array, char separator) {
+ int pos = lastIndexOf(separator, array);
+ if (pos < 0)
+ return array;
+ return subarray(array, pos + 1, array.length);
+ }
+
+ /**
+ * Answers true if the pattern matches the given name, false otherwise. This
+ * char[] pattern matching
+ * accepts wild-cards '*' and '?'.
+ *
+ * When not case sensitive, the pattern is assumed to already be lowercased,
+ * the
+ * name will be lowercased character per character as comparing.
+ * If name is null, the answer is false.
+ * If pattern is null, the answer is true if name is not null.
+ *
+ *
+ * For example:
+ *
+ *
+ *
+ *
+ * @param pattern
+ * the given pattern
+ * @param name
+ * the given name
+ * @param isCaseSensitive
+ * flag to know whether or not the matching should be case
+ * sensitive
+ * @return true if the pattern matches the given name, false otherwise
+ */
+ public static final boolean match(char[] pattern, char[] name,
+ boolean isCaseSensitive) {
+ if (name == null)
+ return false; // null name cannot match
+ if (pattern == null)
+ return true; // null pattern is equivalent to '*'
+ return match(pattern, 0, pattern.length, name, 0, name.length,
+ isCaseSensitive, true);
+ }
+
+ /**
+ * Answers true if the a sub-pattern matches the subpart of the given name,
+ * false otherwise.
+ * char[] pattern matching, accepting wild-cards '*' and '?'. Can match only
+ * subset of name/pattern.
+ * end positions are non-inclusive.
+ * The subpattern is defined by the patternStart and pattternEnd positions.
+ * When not case sensitive, the pattern is assumed to already be lowercased,
+ * the
+ * name will be lowercased character per character as comparing.
+ *
+ *
+ * For example:
+ *
+ *
+ *
+ *
+ * @param toBeFound
+ * the given character
+ * @param array
+ * the given array
+ * @return the number of occurrences of the given character in the given
+ * array, 0 if any
+ * @exception NullPointerException
+ * if array is null
+ */
+ public static final int occurencesOf(char toBeFound, char[] array) {
+ int count = 0;
+ for (char element : array)
+ if (toBeFound == element)
+ count++;
+ return count;
+ }
+
+ /**
+ * Answers the number of occurrences of the given character in the given
+ * array starting
+ * at the given index, 0 if any.
+ *
+ *
+ *
+ * For example:
+ *
+ *
+ *
+ *
+ * @param toBeFound
+ * the given character
+ * @param array
+ * the given array
+ * @return the number of occurrences of the given character in the given
+ * array, 0 if any
+ * @exception NullPointerException
+ * if array is null
+ * @exception ArrayIndexOutOfBoundsException
+ * if start is lower than 0
+ */
+ public static final int occurencesOf(char toBeFound, char[] array, int start) {
+ int count = 0;
+ for (int i = start; i < array.length; i++)
+ if (toBeFound == array[i])
+ count++;
+ return count;
+ }
+
+ /**
+ * Answers true if the given name starts with the given prefix, false
+ * otherwise.
+ * The comparison is case sensitive.
+ *
+ *
+ * For example:
+ *
+ *
+ *
+ *
+ * @param prefix
+ * the given prefix
+ * @param name
+ * the given name
+ * @return true if the given name starts with the given prefix, false
+ * otherwise
+ * @exception NullPointerException
+ * if the given name is null or if the given prefix is null
+ */
+ public static final boolean prefixEquals(char[] prefix, char[] name) {
+ int max = prefix.length;
+ if (name.length < max)
+ return false;
+ for (int i = max; --i >= 0;)
+ // assumes the prefix is not larger than the name
+ if (prefix[i] != name[i])
+ return false;
+ return true;
+ }
+
+ /**
+ * Answers true if the given name starts with the given prefix, false
+ * otherwise.
+ * isCaseSensitive is used to find out whether or not the comparison should
+ * be case sensitive.
+ *
+ *
+ * For example:
+ *
+ *
+ *
+ *
+ * @param prefix
+ * the given prefix
+ * @param name
+ * the given name
+ * @param isCaseSensitive
+ * to find out whether or not the comparison should be case
+ * sensitive
+ * @return true if the given name starts with the given prefix, false
+ * otherwise
+ * @exception NullPointerException
+ * if the given name is null or if the given prefix is null
+ */
+ public static final boolean prefixEquals(char[] prefix, char[] name,
+ boolean isCaseSensitive) {
+ int max = prefix.length;
+ if (name.length < max)
+ return false;
+ if (isCaseSensitive) {
+ for (int i = max; --i >= 0;)
+ // assumes the prefix is not larger than the name
+ if (prefix[i] != name[i])
+ return false;
+ return true;
+ }
+ for (int i = max; --i >= 0;)
+ // assumes the prefix is not larger than the name
+ if (Character.toLowerCase(prefix[i]) != Character
+ .toLowerCase(name[i]))
+ return false;
+ return true;
+ }
+
+ /**
+ * Replace all occurrence of the character to be replaced with the
+ * remplacement character in the
+ * given array.
+ *
+ *
+ * For example:
+ *
+ *
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * toBeReplaced = 'b'
+ * replacementChar = 'a'
+ * result => No returned value, but array is now equals to { 'a' , 'a', 'a',
+ * 'a', 'a', 'a' }
+ *
+ *
+ *
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * toBeReplaced = 'c'
+ * replacementChar = 'a'
+ * result => No returned value, but array is now equals to { 'a' , 'b', 'b',
+ * 'a', 'b', 'a' }
+ *
+ *
+ *
+ *
+ * @param array
+ * the given array
+ * @param toBeReplaced
+ * the character to be replaced
+ * @param replacementChar
+ * the replacement character
+ * @exception NullPointerException
+ * if the given array is null
+ */
+ public static final void replace(char[] array, char toBeReplaced,
+ char replacementChar) {
+ if (toBeReplaced != replacementChar) {
+ for (int i = 0, max = array.length; i < max; i++) {
+ if (array[i] == toBeReplaced)
+ array[i] = replacementChar;
+ }
+ }
+ }
+
+ /**
+ * Answers a new array of characters with substitutions. No side-effect is
+ * operated on the original
+ * array, in case no substitution happened, then the result is the same as
+ * the
+ * original one.
+ *
+ *
+ * For example:
+ *
+ *
+ *
+ *
+ * @param divider
+ * the given divider
+ * @param array
+ * the given array
+ * @return a new array which is the split of the given array using the given
+ * divider and triming each subarray to remove
+ * whitespaces equals to ' '
+ */
+ public static final char[][] splitAndTrimOn(char divider, char[] array) {
+ if (array == null)
+ return NO_CHAR_CHAR;
+ final int length = array.length;
+ if (length == 0)
+ return NO_CHAR_CHAR;
+ int wordCount = 1;
+ for (int i = 0; i < length; i++)
+ if (array[i] == divider)
+ wordCount++;
+ char[][] split = new char[wordCount][];
+ int last = 0, currentWord = 0;
+ for (int i = 0; i < length; i++) {
+ if (array[i] == divider) {
+ int start = last, end = i - 1;
+ while (start < i && array[start] == ' ')
+ start++;
+ while (end > start && array[end] == ' ')
+ end--;
+ split[currentWord] = new char[end - start + 1];
+ System.arraycopy(array, start, split[currentWord++], 0, end
+ - start + 1);
+ last = i + 1;
+ }
+ }
+ int start = last, end = length - 1;
+ while (start < length && array[start] == ' ')
+ start++;
+ while (end > start && array[end] == ' ')
+ end--;
+ split[currentWord] = new char[end - start + 1];
+ System.arraycopy(array, start, split[currentWord++], 0, end - start + 1);
+ return split;
+ }
+
+ /**
+ * Return a new array which is the split of the given array using the given
+ * divider.
+ *
+ *
+ * For example:
+ *
+ *
+ *
+ *
+ * @param divider
+ * the given divider
+ * @param array
+ * the given array
+ * @return a new array which is the split of the given array using the given
+ * divider
+ */
+ public static final char[][] splitOn(char divider, char[] array) {
+ if (array == null)
+ return NO_CHAR_CHAR;
+ final int length = array.length;
+ if (length == 0)
+ return NO_CHAR_CHAR;
+ int wordCount = 1;
+ for (int i = 0; i < length; i++)
+ if (array[i] == divider)
+ wordCount++;
+ char[][] split = new char[wordCount][];
+ int last = 0, currentWord = 0;
+ for (int i = 0; i < length; i++) {
+ if (array[i] == divider) {
+ split[currentWord] = new char[i - last];
+ System.arraycopy(array, last, split[currentWord++], 0, i - last);
+ last = i + 1;
+ }
+ }
+ split[currentWord] = new char[length - last];
+ System.arraycopy(array, last, split[currentWord], 0, length - last);
+ return split;
+ }
+
+ /**
+ * Return a new array which is the split of the given array using the given
+ * divider. The given end
+ * is exclusive and the given start is inclusive.
+ *
+ *
+ * For example:
+ *
+ *
+ *
+ *
+ * @param divider
+ * the given divider
+ * @param array
+ * the given array
+ * @param start
+ * the given starting index
+ * @param end
+ * the given ending index
+ * @return a new array which is the split of the given array using the given
+ * divider
+ * @exception ArrayIndexOutOfBoundsException
+ * if start is lower than 0 or end is greater than the array
+ * length
+ */
+ public static final char[][] splitOn(char divider, char[] array, int start,
+ int end) {
+ if (array == null)
+ return NO_CHAR_CHAR;
+ final int length = array.length;
+ if (length == 0 || start > end)
+ return NO_CHAR_CHAR;
+ int wordCount = 1;
+ for (int i = start; i < end; i++)
+ if (array[i] == divider)
+ wordCount++;
+ char[][] split = new char[wordCount][];
+ int last = start, currentWord = 0;
+ for (int i = start; i < end; i++) {
+ if (array[i] == divider) {
+ split[currentWord] = new char[i - last];
+ System.arraycopy(array, last, split[currentWord++], 0, i - last);
+ last = i + 1;
+ }
+ }
+ split[currentWord] = new char[end - last];
+ System.arraycopy(array, last, split[currentWord], 0, end - last);
+ return split;
+ }
+
+ /**
+ * Answers a new array which is a copy of the given array starting at the
+ * given start and
+ * ending at the given end. The given start is inclusive and the given end
+ * is exclusive.
+ * Answers null if start is greater than end, if start is lower than 0 or if
+ * end is greater
+ * than the length of the given array. If end equals -1, it is converted to
+ * the array length.
+ *
+ *
+ * For example:
+ *
+ *
+ *
+ *
+ * @param array
+ * the given array
+ * @param start
+ * the given starting index
+ * @param end
+ * the given ending index
+ * @return a new array which is a copy of the given array starting at the
+ * given start and
+ * ending at the given end
+ * @exception NullPointerException
+ * if the given array is null
+ */
+ public static final char[][] subarray(char[][] array, int start, int end) {
+ if (end == -1)
+ end = array.length;
+ if (start > end)
+ return null;
+ if (start < 0)
+ return null;
+ if (end > array.length)
+ return null;
+ char[][] result = new char[end - start][];
+ System.arraycopy(array, start, result, 0, end - start);
+ return result;
+ }
+
+ /**
+ * Answers a new array which is a copy of the given array starting at the
+ * given start and
+ * ending at the given end. The given start is inclusive and the given end
+ * is exclusive.
+ * Answers null if start is greater than end, if start is lower than 0 or if
+ * end is greater
+ * than the length of the given array. If end equals -1, it is converted to
+ * the array length.
+ *
+ *
+ * For example:
+ *
+ *
+ *
+ *
+ * @param array
+ * the given array
+ * @param start
+ * the given starting index
+ * @param end
+ * the given ending index
+ * @return a new array which is a copy of the given array starting at the
+ * given start and
+ * ending at the given end
+ * @exception NullPointerException
+ * if the given array is null
+ */
+ public static final char[] subarray(char[] array, int start, int end) {
+ if (end == -1)
+ end = array.length;
+ if (start > end)
+ return null;
+ if (start < 0)
+ return null;
+ if (end > array.length)
+ return null;
+ char[] result = new char[end - start];
+ System.arraycopy(array, start, result, 0, end - start);
+ return result;
+ }
+
+ /**
+ * Answers the result of a char[] conversion to lowercase. Answers null if
+ * the given chars array is null.
+ *
+ * NOTE: If no conversion was necessary, then answers back the argument one.
+ *
+ *
+ * For example:
+ *
+ *