summaryrefslogtreecommitdiffstats
path: root/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal
diff options
context:
space:
mode:
authorElliott Baron <ebaron@fedoraproject.org>2010-06-26 22:27:34 -0400
committerElliott Baron <ebaron@fedoraproject.org>2010-06-26 22:27:34 -0400
commit4e112eca7750a4f530c986be55c178c43c16d3ea (patch)
treedb140c4fe4db9945502398e4869707ca0346353e /org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal
parentaa73b3f2503808e4b4029a73368a75b258d6f0dc (diff)
downloadcodan-4e112eca7750a4f530c986be55c178c43c16d3ea.tar.gz
codan-4e112eca7750a4f530c986be55c178c43c16d3ea.tar.xz
codan-4e112eca7750a4f530c986be55c178c43c16d3ea.zip
Update codan plugins to CDT 7.0.HEADmaster
* org.eclipse.cdt.codan.checkers.ui: Updated. * org.eclipse.cdt.codan.checkers: Updated. * org.eclipse.cdt.codan.core: Updated. * org.eclipse.cdt.codan.ui: Updated. * org.eclipse.cdt.codan.core.cxx: Added. * org.eclipse.cdt.codan.extension/META-INF/MANIFEST.MF: Import org.eclipse.cdt.codan.core.cxx.model. * org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/checkers/AbstractPropSimChecker.java: Superclass moved.
Diffstat (limited to 'org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal')
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/CVS/Tag1
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CVS/Entries11
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CVS/Tag1
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CharOperation.java2713
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CheckersRegistry.java (renamed from org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CheckersRegisry.java)189
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CodanApplication.java118
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CodanBuilder.java245
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CodanPreferencesLoader.java140
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CodeAnlysisNature.java29
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/AbstractBasicBlock.java61
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/AbstractSingleIncomingNode.java56
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/AbstractSingleOutgoingNode.java56
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/BranchNode.java36
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/CVS/Entries12
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/CVS/Repository1
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/CVS/Root1
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/CVS/Tag1
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/ConnectorNode.java69
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/ControlFlowGraph.java147
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/DecisionNode.java74
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/ExitNode.java48
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/JumpNode.java71
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/NodeFactory.java101
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/PlainNode.java54
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/StartNode.java42
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CVS/Entries11
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CVS/Tag1
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanMarkerProblemReporter.java132
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblem.java87
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblemCategory.java33
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblemLocation.java33
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/ProblemLocationFactory.java53
-rw-r--r--org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/ProblemProfile.java18
33 files changed, 4292 insertions, 353 deletions
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/CVS/Tag b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/CVS/Tag
new file mode 100644
index 0000000..3cd1ca4
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/CVS/Tag
@@ -0,0 +1 @@
+TCDT_7_0_0
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CVS/Entries b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CVS/Entries
index 49bf43c..9771946 100644
--- a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CVS/Entries
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CVS/Entries
@@ -1,5 +1,8 @@
-/CheckersRegisry.java/1.3/Wed Dec 16 21:48:48 2009//
-/CodanBuilder.java/1.3/Wed Dec 16 21:48:48 2009//
-/CodanPreferencesLoader.java/1.1/Wed Sep 23 23:29:36 2009//
-/CodeAnlysisNature.java/1.1/Sat Aug 22 21:16:49 2009//
+/CharOperation.java/1.2/Thu Jun 3 17:01:53 2010//TCDT_7_0_0
+/CheckersRegistry.java/1.3/Thu Jun 3 17:01:53 2010//TCDT_7_0_0
+/CodanApplication.java/1.7/Sun Jun 27 01:30:42 2010//TCDT_7_0_0
+/CodanBuilder.java/1.12/Sun Jun 27 01:30:42 2010//TCDT_7_0_0
+/CodanPreferencesLoader.java/1.8/Sun Jun 27 01:30:42 2010//TCDT_7_0_0
+/CodeAnlysisNature.java/1.4/Sun Jun 27 01:30:42 2010//TCDT_7_0_0
+D/cfg////
D/model////
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CVS/Tag b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CVS/Tag
new file mode 100644
index 0000000..49a449a
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CVS/Tag
@@ -0,0 +1 @@
+NCDT_7_0_0
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CharOperation.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CharOperation.java
new file mode 100644
index 0000000..7790814
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CharOperation.java
@@ -0,0 +1,2713 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.cdt.codan.internal.core;
+
+/**
+ * This class is a collection of helper methods to manipulate char arrays.
+ *
+ * @since 2.1
+ */
+public final class CharOperation {
+ /**
+ * Constant for an empty char array
+ */
+ public static final char[] NO_CHAR = new char[0];
+ /**
+ * Constant for an empty char array with two dimensions.
+ */
+ public static final char[][] NO_CHAR_CHAR = new char[0][];
+
+ /**
+ * Answers a new array with appending the suffix character at the end of the
+ * array.
+ * <br>
+ * <br>
+ * For example:<br>
+ * <ol>
+ * <li><pre>
+ * array = { 'a', 'b' }
+ * suffix = 'c'
+ * => result = { 'a', 'b' , 'c' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * array = null
+ * suffix = 'c'
+ * => result = { 'c' }
+ * </pre></li>
+ * </ol>
+ *
+ * @param array
+ * the array that is concanated with the suffix character
+ * @param suffix
+ * the suffix character
+ * @return the new array
+ */
+ public static final char[] append(char[] array, char suffix) {
+ if (array == null)
+ return new char[] { suffix };
+ int length = array.length;
+ System.arraycopy(array, 0, array = new char[length + 1], 0, length);
+ array[length] = suffix;
+ return array;
+ }
+
+ /**
+ * Append the given subarray to the target array starting at the given index
+ * in the target array.
+ * The start of the subarray is inclusive, the end is exclusive.
+ * Answers a new target array if it needs to grow, otherwise answers the
+ * same target array.
+ * <br>
+ * For example:<br>
+ * <ol>
+ * <li><pre>
+ * target = { 'a', 'b', '0' }
+ * index = 2
+ * array = { 'c', 'd' }
+ * start = 0
+ * end = 1
+ * => result = { 'a', 'b' , 'c' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * target = { 'a', 'b' }
+ * index = 2
+ * array = { 'c', 'd' }
+ * start = 0
+ * end = 1
+ * => result = { 'a', 'b' , 'c', '0', '0' , '0' } (new array)
+ * </pre></li>
+ * <li><pre>
+ * target = { 'a', 'b', 'c' }
+ * index = 1
+ * array = { 'c', 'd', 'e', 'f' }
+ * start = 1
+ * end = 4
+ * => result = { 'a', 'd' , 'e', 'f', '0', '0', '0', '0' } (new array)
+ * </pre></li>
+ * </ol>
+ *
+ * @param target
+ * the given target
+ * @param index
+ * the given index
+ * @param array
+ * the given array
+ * @param start
+ * the given start index
+ * @param end
+ * the given end index
+ *
+ * @return the new array
+ * @throws NullPointerException
+ * if the target array is null
+ */
+ public static final char[] append(char[] target, int index, char[] array,
+ int start, int end) {
+ int targetLength = target.length;
+ int subLength = end - start;
+ int newTargetLength = subLength + index;
+ if (newTargetLength > targetLength) {
+ System.arraycopy(target, 0, target = new char[newTargetLength * 2],
+ 0, index);
+ }
+ System.arraycopy(array, start, target, index, subLength);
+ return target;
+ }
+
+ /**
+ * 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.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * first = null
+ * second = null
+ * => result = null
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { { ' a' } }
+ * second = null
+ * => result = { { ' a' } }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = null
+ * second = { { ' a' } }
+ * => result = { { ' a' } }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { { ' b' } }
+ * second = { { ' a' } }
+ * => result = { { ' b' }, { ' a' } }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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[][] arrayConcat(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 a new array adding the second array at the end of first array.
+ * It answers null if the first and second are null.
+ * If the first array is null, then a new array char[][] is created with
+ * second.
+ * If the second array is null, then the first array is returned.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * first = null
+ * second = { 'a' }
+ * => result = { { ' a' } }
+ * </pre>
+ * <li><pre>
+ * first = { { ' a' } }
+ * second = null
+ * => result = { { ' a' } }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { { ' a' } }
+ * second = { ' b' }
+ * => result = { { ' a' } , { ' b' } }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param first
+ * the first array to concatenate
+ * @param second
+ * the array to add at the end of the first array
+ * @return a new array adding the second array at the end of first array, or
+ * null if the two arrays are null.
+ */
+ public static final char[][] arrayConcat(char[][] first, char[] second) {
+ if (second == null)
+ return first;
+ if (first == null)
+ return new char[][] { second };
+ int length = first.length;
+ char[][] result = new char[length + 1][];
+ System.arraycopy(first, 0, result, 0, length);
+ result[length] = second;
+ return result;
+ }
+
+ /**
+ * Compares the contents of the two arrays array and prefix. Returns
+ * <ul>
+ * <li>zero if the array starts with the prefix contents</li>
+ * <li>the difference between the first two characters that are not equal
+ * </li>
+ * <li>one if array length is lower than the prefix length and that the
+ * prefix starts with the
+ * array contents.</li>
+ * </ul>
+ * <p>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * array = null
+ * prefix = null
+ * => result = NullPointerException
+ * </pre>
+ * </li>
+ * <li><pre>
+ * array = { 'a', 'b', 'c', 'd', 'e' }
+ * prefix = { 'a', 'b', 'c'}
+ * => result = 0
+ * </pre>
+ * </li>
+ * <li><pre>
+ * array = { 'a', 'b', 'c', 'd', 'e' }
+ * prefix = { 'a', 'B', 'c'}
+ * => result = 32
+ * </pre>
+ * </li>
+ * <li><pre>
+ * array = { 'd', 'b', 'c', 'd', 'e' }
+ * prefix = { 'a', 'b', 'c'}
+ * => result = 3
+ * </pre>
+ * </li>
+ * <li><pre>
+ * array = { 'a', 'b', 'c', 'd', 'e' }
+ * prefix = { 'd', 'b', 'c'}
+ * => result = -3
+ * </pre>
+ * </li>
+ * <li><pre>
+ * array = { 'a', 'a', 'c', 'd', 'e' }
+ * prefix = { 'a', 'e', 'c'}
+ * => result = -4
+ * </pre>
+ * </li>
+ * </ol>
+ * </p>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * first = null
+ * second = { 'a' }
+ * => result = { ' a' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { ' a' }
+ * second = null
+ * => result = { ' a' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { ' a' }
+ * second = { ' b' }
+ * => result = { ' a' , ' b' }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * first = null
+ * second = { 'a' }
+ * third = { 'b' }
+ * => result = { ' a', 'b' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { 'a' }
+ * second = null
+ * third = { 'b' }
+ * => result = { ' a', 'b' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { 'a' }
+ * second = { 'b' }
+ * third = null
+ * => result = { ' a', 'b' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = null
+ * second = null
+ * third = null
+ * => result = null
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { 'a' }
+ * second = { 'b' }
+ * third = { 'c' }
+ * => result = { 'a', 'b', 'c' }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * first = null
+ * second = { 'a' }
+ * separator = '/'
+ * => result = { ' a' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { ' a' }
+ * second = null
+ * separator = '/'
+ * => result = { ' a' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { ' a' }
+ * second = { ' b' }
+ * separator = '/'
+ * => result = { ' a' , '/', 'b' }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * first = null
+ * sep1 = '/'
+ * second = { 'a' }
+ * sep2 = ':'
+ * third = { 'b' }
+ * => result = { ' a' , ':', 'b' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { 'a' }
+ * sep1 = '/'
+ * second = null
+ * sep2 = ':'
+ * third = { 'b' }
+ * => result = { ' a' , '/', 'b' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { 'a' }
+ * sep1 = '/'
+ * second = { 'b' }
+ * sep2 = ':'
+ * third = null
+ * => result = { ' a' , '/', 'b' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { 'a' }
+ * sep1 = '/'
+ * second = { 'b' }
+ * sep2 = ':'
+ * third = { 'c' }
+ * => result = { ' a' , '/', 'b' , ':', 'c' }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example:<br>
+ * <ol>
+ * <li><pre>
+ * prefix = 'a'
+ * array = { 'b' }
+ * suffix = 'c'
+ * => result = { 'a', 'b' , 'c' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * prefix = 'a'
+ * array = null
+ * suffix = 'c'
+ * => result = { 'a', 'c' }
+ * </pre></li>
+ * </ol>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example:<br>
+ * <ol>
+ * <li><pre>
+ * name = { 'c' }
+ * array = { { 'a' }, { 'b' } }
+ * separator = '.'
+ * => result = { 'a', '.', 'b' , '.', 'c' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * name = null
+ * array = { { 'a' }, { 'b' } }
+ * separator = '.'
+ * => result = { 'a', '.', 'b' }
+ * </pre></li>
+ * <li><pre>
+ * name = { ' c' }
+ * array = null
+ * separator = '.'
+ * => result = { 'c' }
+ * </pre></li>
+ * </ol>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example:<br>
+ * <ol>
+ * <li><pre>
+ * name = { 'c' }
+ * array = { { 'a' }, { 'b' } }
+ * separator = '.'
+ * => result = { 'a', '.', 'b' , '.', 'c' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * name = null
+ * array = { { 'a' }, { 'b' } }
+ * separator = '.'
+ * => result = { 'a', '.', 'b' }
+ * </pre></li>
+ * <li><pre>
+ * name = { ' c' }
+ * array = null
+ * separator = '.'
+ * => result = { 'c' }
+ * </pre></li>
+ * </ol>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example:<br>
+ * <ol>
+ * <li><pre>
+ * array = { { 'a' }, { 'b' } }
+ * separator = '.'
+ * => result = { 'a', '.', 'b' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * array = null
+ * separator = '.'
+ * => result = { }
+ * </pre></li>
+ * </ol>
+ *
+ * @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.
+ *
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * character = 'c'
+ * array = { { ' a' }, { ' b' } }
+ * result => false
+ * </pre>
+ * </li>
+ * <li><pre>
+ * character = 'a'
+ * array = { { ' a' }, { ' b' } }
+ * result => true
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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.
+ *
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * character = 'c'
+ * array = { ' b' }
+ * result => false
+ * </pre>
+ * </li>
+ * <li><pre>
+ * character = 'a'
+ * array = { ' a' , ' b' }
+ * result => true
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * array = { 'a', 'b', 'c', 'd' }
+ * toBeFound = { 'b', 'c' }
+ * result => false
+ * </pre>
+ * </li>
+ * <li><pre>
+ * array = { 'a', 'b', 'c' }
+ * toBeFound = { 'b', 'c' }
+ * result => true
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * first = null
+ * second = null
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { { } }
+ * second = null
+ * result => false
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { { 'a' } }
+ * second = { { 'a' } }
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { { 'A' } }
+ * second = { { 'a' } }
+ * result => false
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * first = null
+ * second = null
+ * isCaseSensitive = true
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { { } }
+ * second = null
+ * isCaseSensitive = true
+ * result => false
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { { 'A' } }
+ * second = { { 'a' } }
+ * isCaseSensitive = true
+ * result => false
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { { 'A' } }
+ * second = { { 'a' } }
+ * isCaseSensitive = false
+ * result => true
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * first = null
+ * second = null
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { }
+ * second = null
+ * result => false
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { 'a' }
+ * second = { 'a' }
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { 'a' }
+ * second = { 'A' }
+ * result => false
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * first = null
+ * second = null
+ * isCaseSensitive = true
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { }
+ * second = null
+ * isCaseSensitive = true
+ * result => false
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { 'A' }
+ * second = { 'a' }
+ * isCaseSensitive = true
+ * result => false
+ * </pre>
+ * </li>
+ * <li><pre>
+ * first = { 'A' }
+ * second = { 'a' }
+ * isCaseSensitive = false
+ * result => true
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * fragment = { 'b', 'c' , 'd' }
+ * name = { 'a', 'b', 'c' , 'd' }
+ * startIndex = 1
+ * isCaseSensitive = true
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * fragment = { 'b', 'c' , 'd' }
+ * name = { 'a', 'b', 'C' , 'd' }
+ * startIndex = 1
+ * isCaseSensitive = true
+ * result => false
+ * </pre>
+ * </li>
+ * <li><pre>
+ * fragment = { 'b', 'c' , 'd' }
+ * name = { 'a', 'b', 'C' , 'd' }
+ * startIndex = 0
+ * isCaseSensitive = false
+ * result => false
+ * </pre>
+ * </li>
+ * <li><pre>
+ * fragment = { 'b', 'c' , 'd' }
+ * name = { 'a', 'b'}
+ * startIndex = 0
+ * isCaseSensitive = true
+ * result => false
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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 (&#92;u000a,
+ * &#92;u000c, &#92;u000d, &#92;u0009), otherwise false.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * c = ' '
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * c = '&#92;u3000'
+ * result => false
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * toBeFound = 'c'
+ * array = { ' a', 'b', 'c', 'd' }
+ * result => 2
+ * </pre>
+ * </li>
+ * <li><pre>
+ * toBeFound = 'e'
+ * array = { ' a', 'b', 'c', 'd' }
+ * result => -1
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * toBeFound = 'c'
+ * array = { ' a', 'b', 'c', 'd' }
+ * start = 2
+ * result => 2
+ * </pre>
+ * </li>
+ * <li><pre>
+ * toBeFound = 'c'
+ * array = { ' a', 'b', 'c', 'd' }
+ * start = 3
+ * result => -1
+ * </pre>
+ * </li>
+ * <li><pre>
+ * toBeFound = 'e'
+ * array = { ' a', 'b', 'c', 'd' }
+ * start = 1
+ * result => -1
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * toBeFound = 'c'
+ * array = { ' a', 'b', 'c', 'd' , 'c', 'e' }
+ * result => 4
+ * </pre>
+ * </li>
+ * <li><pre>
+ * toBeFound = 'e'
+ * array = { ' a', 'b', 'c', 'd' }
+ * result => -1
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * toBeFound = 'c'
+ * array = { ' a', 'b', 'c', 'd' }
+ * startIndex = 2
+ * result => 2
+ * </pre>
+ * </li>
+ * <li><pre>
+ * toBeFound = 'c'
+ * array = { ' a', 'b', 'c', 'd', 'e' }
+ * startIndex = 3
+ * result => -1
+ * </pre>
+ * </li>
+ * <li><pre>
+ * toBeFound = 'e'
+ * array = { ' a', 'b', 'c', 'd' }
+ * startIndex = 0
+ * result => -1
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * toBeFound = 'c'
+ * array = { ' a', 'b', 'c', 'd' }
+ * startIndex = 2
+ * endIndex = 2
+ * result => 2
+ * </pre>
+ * </li>
+ * <li><pre>
+ * toBeFound = 'c'
+ * array = { ' a', 'b', 'c', 'd', 'e' }
+ * startIndex = 3
+ * endIndex = 4
+ * result => -1
+ * </pre>
+ * </li>
+ * <li><pre>
+ * toBeFound = 'e'
+ * array = { ' a', 'b', 'c', 'd' }
+ * startIndex = 0
+ * endIndex = 3
+ * result => -1
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example,
+ * <pre>
+ * lastSegment("java.lang.Object".toCharArray(),'.') --> Object
+ * </pre>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * pattern = { '?', 'b', '*' }
+ * name = { 'a', 'b', 'c' , 'd' }
+ * isCaseSensitive = true
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * pattern = { '?', 'b', '?' }
+ * name = { 'a', 'b', 'c' , 'd' }
+ * isCaseSensitive = true
+ * result => false
+ * </pre>
+ * </li>
+ * <li><pre>
+ * pattern = { 'b', '*' }
+ * name = { 'a', 'b', 'c' , 'd' }
+ * isCaseSensitive = true
+ * result => false
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * pattern = { '?', 'b', '*' }
+ * patternStart = 1
+ * patternEnd = 3
+ * name = { 'a', 'b', 'c' , 'd' }
+ * nameStart = 1
+ * nameEnd = 4
+ * isCaseSensitive = true
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * pattern = { '?', 'b', '*' }
+ * patternStart = 1
+ * patternEnd = 2
+ * name = { 'a', 'b', 'c' , 'd' }
+ * nameStart = 1
+ * nameEnd = 2
+ * isCaseSensitive = true
+ * result => false
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param pattern
+ * the given pattern
+ * @param patternStart
+ * the given pattern start
+ * @param patternEnd
+ * the given pattern end
+ * @param name
+ * the given name
+ * @param nameStart
+ * the given name start
+ * @param nameEnd
+ * the given name end
+ * @param isCaseSensitive
+ * flag to know if the matching should be case sensitive
+ * @return true if the a sub-pattern matches the subpart of the given name,
+ * false otherwise
+ */
+ public static final boolean match(char[] pattern, int patternStart,
+ int patternEnd, char[] name, int nameStart, int nameEnd,
+ boolean isCaseSensitive) {
+ return match(pattern, patternStart, patternEnd, name, nameStart,
+ nameEnd, isCaseSensitive, false);
+ }
+
+ public static final boolean match(char[] pattern, int patternStart,
+ int patternEnd, char[] name, int nameStart, int nameEnd,
+ boolean isCaseSensitive, boolean allowEscaping) {
+ if (name == null)
+ return false; // null name cannot match
+ if (pattern == null)
+ return true; // null pattern is equivalent to '*'
+ int iPattern = patternStart;
+ int iName = nameStart;
+ if (patternEnd < 0)
+ patternEnd = pattern.length;
+ if (nameEnd < 0)
+ nameEnd = name.length;
+ /* check first segment */
+ char patternChar = 0;
+ boolean isEscaped = false;
+ while ((iPattern < patternEnd)
+ && ((patternChar = pattern[iPattern]) != '*' || (patternChar == '*' && isEscaped))) {
+ if (allowEscaping && pattern[iPattern] == '\\' && !isEscaped) {
+ iPattern++;
+ isEscaped = true;
+ continue;
+ } else
+ isEscaped = false;
+ if (iName == nameEnd)
+ return false;
+ if (patternChar != (isCaseSensitive ? name[iName] : Character
+ .toLowerCase(name[iName])) && patternChar != '?') {
+ return false;
+ }
+ iName++;
+ iPattern++;
+ patternChar = 0;
+ }
+ /* check sequence of star+segment */
+ int segmentStart;
+ if (patternChar == '*') {
+ segmentStart = ++iPattern; // skip star
+ } else {
+ segmentStart = 0; // force iName check
+ }
+ int prefixStart = iName;
+ checkSegment: while (iName < nameEnd) {
+ if (iPattern == patternEnd) {
+ iPattern = segmentStart; // mismatch - restart current segment
+ iName = ++prefixStart;
+ continue checkSegment;
+ }
+ /* segment is ending */
+ if ((patternChar = pattern[iPattern]) == '*') {
+ segmentStart = ++iPattern; // skip start
+ if (segmentStart == patternEnd) {
+ return true;
+ }
+ prefixStart = iName;
+ continue checkSegment;
+ }
+ /* check current name character */
+ if ((isCaseSensitive ? name[iName] : Character
+ .toLowerCase(name[iName])) != patternChar
+ && patternChar != '?') {
+ iPattern = segmentStart; // mismatch - restart current segment
+ iName = ++prefixStart;
+ continue checkSegment;
+ }
+ iName++;
+ iPattern++;
+ }
+ return (segmentStart == patternEnd)
+ || (iName == nameEnd && iPattern == patternEnd)
+ || (iPattern == patternEnd - 1 && pattern[iPattern] == '*');
+ }
+
+ /**
+ * Answers true if the pattern matches the filepath using the pathSepatator,
+ * false otherwise.
+ *
+ * Path char[] pattern matching, accepting wild-cards '**', '*' and '?'
+ * (using Ant directory tasks
+ * conventions, also see
+ * "http://jakarta.apache.org/ant/manual/dirtasks.html#defaultexcludes").
+ * Path pattern matching is enhancing regular pattern matching in supporting
+ * extra rule where '**' represent
+ * any folder combination.
+ * Special rules:
+ * - foo\ is equivalent to foo\**
+ * - *.java is equivalent to **\*.java
+ * When not case sensitive, the pattern is assumed to already be lowercased,
+ * the
+ * name will be lowercased character per character as comparing.
+ *
+ * @param pattern
+ * the given pattern
+ * @param filepath
+ * the given path
+ * @param isCaseSensitive
+ * to find out whether or not the matching should be case
+ * sensitive
+ * @param pathSeparator
+ * the given path separator
+ * @return true if the pattern matches the filepath using the pathSepatator,
+ * false otherwise
+ */
+ public static final boolean pathMatch(char[] pattern, char[] filepath,
+ boolean isCaseSensitive, char pathSeparator) {
+ if (filepath == null)
+ return false; // null name cannot match
+ if (pattern == null)
+ return true; // null pattern is equivalent to '*'
+ // special case: pattern foo is equivalent to **\foo (not absolute)
+ boolean freeLeadingDoubleStar;
+ // offsets inside pattern
+ int pSegmentStart, pLength = pattern.length;
+ freeLeadingDoubleStar = (pattern[0] != pathSeparator);
+ if (freeLeadingDoubleStar) {
+ pSegmentStart = 0;
+ } else {
+ pSegmentStart = 1;
+ }
+ int pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern,
+ pSegmentStart + 1);
+ if (pSegmentEnd < 0)
+ pSegmentEnd = pLength;
+ // special case: pattern foo\ is equivalent to foo\**
+ boolean freeTrailingDoubleStar = pattern[pLength - 1] == pathSeparator;
+ // offsets inside filepath
+ int fSegmentStart, fLength = filepath.length;
+ if (filepath[0] != pathSeparator) {
+ fSegmentStart = 0;
+ } else {
+ fSegmentStart = 1;
+ }
+ if (fSegmentStart != pSegmentStart) {
+ return false; // both must start with a separator or none.
+ }
+ int fSegmentEnd = CharOperation.indexOf(pathSeparator, filepath,
+ fSegmentStart + 1);
+ if (fSegmentEnd < 0)
+ fSegmentEnd = fLength;
+ // first segments
+ while (pSegmentStart < pLength
+ && !freeLeadingDoubleStar
+ && !(pSegmentEnd == pLength && freeTrailingDoubleStar || (pSegmentEnd == pSegmentStart + 2
+ && pattern[pSegmentStart] == '*' && pattern[pSegmentStart + 1] == '*'))) {
+ if (fSegmentStart >= fLength)
+ return false;
+ if (!CharOperation.match(pattern, pSegmentStart, pSegmentEnd,
+ filepath, fSegmentStart, fSegmentEnd, isCaseSensitive)) {
+ return false;
+ }
+ // jump to next segment
+ pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern,
+ pSegmentStart = pSegmentEnd + 1);
+ // skip separator
+ if (pSegmentEnd < 0)
+ pSegmentEnd = pLength;
+ fSegmentEnd = CharOperation.indexOf(pathSeparator, filepath,
+ fSegmentStart = fSegmentEnd + 1);
+ // skip separator
+ if (fSegmentEnd < 0)
+ fSegmentEnd = fLength;
+ }
+ /* check sequence of doubleStar+segment */
+ int pSegmentRestart;
+ if ((pSegmentStart >= pLength && freeTrailingDoubleStar)
+ || (pSegmentEnd == pSegmentStart + 2
+ && pattern[pSegmentStart] == '*' && pattern[pSegmentStart + 1] == '*')) {
+ pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern,
+ pSegmentStart = pSegmentEnd + 1);
+ // skip separator
+ if (pSegmentEnd < 0)
+ pSegmentEnd = pLength;
+ pSegmentRestart = pSegmentStart;
+ } else {
+ if (pSegmentStart >= pLength)
+ return fSegmentStart >= fLength; // true if filepath is done too.
+ pSegmentRestart = 0; // force fSegmentStart check
+ }
+ int fSegmentRestart = fSegmentStart;
+ checkSegment: while (fSegmentStart < fLength) {
+ if (pSegmentStart >= pLength) {
+ if (freeTrailingDoubleStar)
+ return true;
+ // mismatch - restart current path segment
+ pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern,
+ pSegmentStart = pSegmentRestart);
+ if (pSegmentEnd < 0)
+ pSegmentEnd = pLength;
+ fSegmentRestart = CharOperation.indexOf(pathSeparator,
+ filepath, fSegmentRestart + 1);
+ // skip separator
+ if (fSegmentRestart < 0) {
+ fSegmentRestart = fLength;
+ } else {
+ fSegmentRestart++;
+ }
+ fSegmentEnd = CharOperation.indexOf(pathSeparator, filepath,
+ fSegmentStart = fSegmentRestart);
+ if (fSegmentEnd < 0)
+ fSegmentEnd = fLength;
+ continue checkSegment;
+ }
+ /* path segment is ending */
+ if (pSegmentEnd == pSegmentStart + 2
+ && pattern[pSegmentStart] == '*'
+ && pattern[pSegmentStart + 1] == '*') {
+ pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern,
+ pSegmentStart = pSegmentEnd + 1);
+ // skip separator
+ if (pSegmentEnd < 0)
+ pSegmentEnd = pLength;
+ pSegmentRestart = pSegmentStart;
+ fSegmentRestart = fSegmentStart;
+ if (pSegmentStart >= pLength)
+ return true;
+ continue checkSegment;
+ }
+ /* chech current path segment */
+ if (!CharOperation.match(pattern, pSegmentStart, pSegmentEnd,
+ filepath, fSegmentStart, fSegmentEnd, isCaseSensitive)) {
+ // mismatch - restart current path segment
+ pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern,
+ pSegmentStart = pSegmentRestart);
+ if (pSegmentEnd < 0)
+ pSegmentEnd = pLength;
+ fSegmentRestart = CharOperation.indexOf(pathSeparator,
+ filepath, fSegmentRestart + 1);
+ // skip separator
+ if (fSegmentRestart < 0) {
+ fSegmentRestart = fLength;
+ } else {
+ fSegmentRestart++;
+ }
+ fSegmentEnd = CharOperation.indexOf(pathSeparator, filepath,
+ fSegmentStart = fSegmentRestart);
+ if (fSegmentEnd < 0)
+ fSegmentEnd = fLength;
+ continue checkSegment;
+ }
+ // jump to next segment
+ pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern,
+ pSegmentStart = pSegmentEnd + 1);
+ // skip separator
+ if (pSegmentEnd < 0)
+ pSegmentEnd = pLength;
+ fSegmentEnd = CharOperation.indexOf(pathSeparator, filepath,
+ fSegmentStart = fSegmentEnd + 1);
+ // skip separator
+ if (fSegmentEnd < 0)
+ fSegmentEnd = fLength;
+ }
+ return (pSegmentRestart >= pSegmentEnd)
+ || (fSegmentStart >= fLength && pSegmentStart >= pLength)
+ || (pSegmentStart == pLength - 2
+ && pattern[pSegmentStart] == '*' && pattern[pSegmentStart + 1] == '*')
+ || (pSegmentStart == pLength && freeTrailingDoubleStar);
+ }
+
+ /**
+ * Answers the number of occurrences of the given character in the given
+ * array, 0 if any.
+ *
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * toBeFound = 'b'
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * result => 3
+ * </pre>
+ * </li>
+ * <li><pre>
+ * toBeFound = 'c'
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * result => 0
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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.
+ *
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * toBeFound = 'b'
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * start = 2
+ * result => 2
+ * </pre>
+ * </li>
+ * <li><pre>
+ * toBeFound = 'c'
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * start = 0
+ * result => 0
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * prefix = { 'a' , 'b' }
+ * name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * prefix = { 'a' , 'c' }
+ * name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * result => false
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * prefix = { 'a' , 'B' }
+ * name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * isCaseSensitive = false
+ * result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ * prefix = { 'a' , 'B' }
+ * name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * isCaseSensitive = true
+ * result => false
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * 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' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * 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' }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * toBeReplaced = { 'b' }
+ * replacementChar = { 'a', 'a' }
+ * result => { 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * toBeReplaced = { 'c' }
+ * replacementChar = { 'a' }
+ * result => { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param array
+ * the given array
+ * @param toBeReplaced
+ * characters to be replaced
+ * @param replacementChars
+ * the replacement characters
+ * @return a new array of characters with substitutions or the given array
+ * if none
+ * @exception NullPointerException
+ * if the given array is null
+ */
+ public static final char[] replace(char[] array, char[] toBeReplaced,
+ char[] replacementChars) {
+ int max = array.length;
+ int replacedLength = toBeReplaced.length;
+ int replacementLength = replacementChars.length;
+ int[] starts = new int[5];
+ int occurrenceCount = 0;
+ if (!equals(toBeReplaced, replacementChars)) {
+ next: for (int i = 0; i < max; i++) {
+ int j = 0;
+ while (j < replacedLength) {
+ if (i + j == max)
+ continue next;
+ if (array[i + j] != toBeReplaced[j++])
+ continue next;
+ }
+ if (occurrenceCount == starts.length) {
+ System.arraycopy(starts, 0,
+ starts = new int[occurrenceCount * 2], 0,
+ occurrenceCount);
+ }
+ starts[occurrenceCount++] = i;
+ }
+ }
+ if (occurrenceCount == 0)
+ return array;
+ char[] result = new char[max + occurrenceCount
+ * (replacementLength - replacedLength)];
+ int inStart = 0, outStart = 0;
+ for (int i = 0; i < occurrenceCount; i++) {
+ int offset = starts[i] - inStart;
+ System.arraycopy(array, inStart, result, outStart, offset);
+ inStart += offset;
+ outStart += offset;
+ System.arraycopy(replacementChars, 0, result, outStart,
+ replacementLength);
+ inStart += replacedLength;
+ outStart += replacementLength;
+ }
+ System.arraycopy(array, inStart, result, outStart, max - inStart);
+ return result;
+ }
+
+ /**
+ * 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 ' '.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * divider = 'b'
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * result => { { 'a' }, { }, { 'a' }, { 'a' } }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * divider = 'c'
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * divider = 'b'
+ * array = { 'a' , ' ', 'b', 'b', 'a', 'b', 'a' }
+ * result => { { 'a' }, { }, { 'a' }, { 'a' } }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * divider = 'c'
+ * array = { ' ', ' ', 'a' , 'b', 'b', 'a', 'b', 'a', ' ' }
+ * result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * divider = 'b'
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * result => { { 'a' }, { }, { 'a' }, { 'a' } }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * divider = 'c'
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * divider = 'c'
+ * array = { ' ', ' ', 'a' , 'b', 'b', 'a', 'b', 'a', ' ' }
+ * result => { { ' ', 'a', 'b', 'b', 'a', 'b', 'a', ' ' } }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * divider = 'b'
+ * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+ * start = 2
+ * end = 5
+ * result => { { }, { }, { 'a' } }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * array = { { 'a' } , { 'b' } }
+ * start = 0
+ * end = 1
+ * result => { { 'a' } }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * array = { { 'a' } , { 'b' } }
+ * start = 0
+ * end = -1
+ * result => { { 'a' }, { 'b' } }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * array = { 'a' , 'b' }
+ * start = 0
+ * end = 1
+ * result => { 'a' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * array = { 'a', 'b' }
+ * start = 0
+ * end = -1
+ * result => { 'a' , 'b' }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @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.
+ * <br>
+ * NOTE: If no conversion was necessary, then answers back the argument one.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * chars = { 'a' , 'b' }
+ * result => { 'a' , 'b' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * array = { 'A', 'b' }
+ * result => { 'a' , 'b' }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param chars
+ * the chars to convert
+ * @return the result of a char[] conversion to lowercase
+ */
+ final static public char[] toLowerCase(char[] chars) {
+ if (chars == null)
+ return null;
+ int length = chars.length;
+ char[] lowerChars = null;
+ for (int i = 0; i < length; i++) {
+ char c = chars[i];
+ char lc = Character.toLowerCase(c);
+ if ((c != lc) || (lowerChars != null)) {
+ if (lowerChars == null) {
+ System.arraycopy(chars, 0, lowerChars = new char[length],
+ 0, i);
+ }
+ lowerChars[i] = lc;
+ }
+ }
+ return lowerChars == null ? chars : lowerChars;
+ }
+
+ /**
+ * Answers a new array removing leading and trailing spaces (' '). Answers
+ * the given array if there is no
+ * space characters to remove.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * chars = { ' ', 'a' , 'b', ' ', ' ' }
+ * result => { 'a' , 'b' }
+ * </pre>
+ * </li>
+ * <li><pre>
+ * array = { 'A', 'b' }
+ * result => { 'A' , 'b' }
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param chars
+ * the given array
+ * @return a new array removing leading and trailing spaces (' ')
+ */
+ final static public char[] trim(char[] chars) {
+ if (chars == null)
+ return null;
+ int start = 0, length = chars.length, end = length - 1;
+ while (start < length && chars[start] == ' ') {
+ start++;
+ }
+ while (end > start && chars[end] == ' ') {
+ end--;
+ }
+ if (start != 0 || end != length - 1) {
+ return subarray(chars, start, end + 1);
+ }
+ return chars;
+ }
+
+ /**
+ * Answers a string which is the concatenation of the given array using the
+ * '.' as a separator.
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ * array = { { 'a' } , { 'b' } }
+ * result => "a.b"
+ * </pre>
+ * </li>
+ * <li><pre>
+ * array = { { ' ', 'a' } , { 'b' } }
+ * result => " a.b"
+ * </pre>
+ * </li>
+ * </ol>
+ *
+ * @param array
+ * the given array
+ * @return a string which is the concatenation of the given array using the
+ * '.' as a separator
+ */
+ final static public String toString(char[][] array) {
+ char[] result = concatWith(array, '.');
+ return new String(result);
+ }
+}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CheckersRegisry.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CheckersRegistry.java
index 5661622..9a9dadc 100644
--- a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CheckersRegisry.java
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CheckersRegistry.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
@@ -17,36 +17,43 @@ import java.util.Iterator;
import org.eclipse.cdt.codan.core.CodanCorePlugin;
import org.eclipse.cdt.codan.core.PreferenceConstants;
+import org.eclipse.cdt.codan.core.model.CodanSeverity;
import org.eclipse.cdt.codan.core.model.IChecker;
+import org.eclipse.cdt.codan.core.model.ICheckerWithPreferences;
import org.eclipse.cdt.codan.core.model.ICheckersRegistry;
import org.eclipse.cdt.codan.core.model.IProblem;
import org.eclipse.cdt.codan.core.model.IProblemCategory;
import org.eclipse.cdt.codan.core.model.IProblemProfile;
+import org.eclipse.cdt.codan.core.model.IProblemWorkingCopy;
import org.eclipse.cdt.codan.internal.core.model.CodanProblem;
import org.eclipse.cdt.codan.internal.core.model.CodanProblemCategory;
import org.eclipse.cdt.codan.internal.core.model.ProblemProfile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.ProjectScope;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.Platform;
-import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.osgi.service.prefs.Preferences;
-public class CheckersRegisry implements Iterable<IChecker>, ICheckersRegistry {
- private static final String EXTENSION_POINT_NAME = "checkers";
- private static final String CHECKER_ELEMENT = "checker";
- private static final String PROBLEM_ELEMENT = "problem";
- private static final String CATEGORY_ELEMENT = "category";
- private static final Object DEFAULT = "DEFAULT";
+/**
+ * Implementation of checker registry interface
+ */
+public class CheckersRegistry implements Iterable<IChecker>, ICheckersRegistry {
+ private static final String NAME_ATTR = "name"; //$NON-NLS-1$
+ private static final String ID_ATTR = "id"; //$NON-NLS-1$
+ private static final String EXTENSION_POINT_NAME = "checkers"; //$NON-NLS-1$
+ private static final String CHECKER_ELEMENT = "checker"; //$NON-NLS-1$
+ private static final String PROBLEM_ELEMENT = "problem"; //$NON-NLS-1$
+ private static final String CATEGORY_ELEMENT = "category"; //$NON-NLS-1$
+ private static final Object DEFAULT = "DEFAULT"; //$NON-NLS-1$
private Collection<IChecker> checkers = new ArrayList<IChecker>();
- private static CheckersRegisry instance;
+ private static CheckersRegistry instance;
private HashMap<Object, IProblemProfile> profiles = new HashMap<Object, IProblemProfile>();
private HashMap<IChecker, Collection<IProblem>> problemList = new HashMap<IChecker, Collection<IProblem>>();
- private CheckersRegisry() {
+ private CheckersRegistry() {
instance = this;
profiles.put(DEFAULT, new ProblemProfile());
readCheckersRegistry();
@@ -73,6 +80,27 @@ public class CheckersRegisry implements Iterable<IChecker>, ICheckersRegistry {
IConfigurationElement configurationElement = elements[i];
processChecker(configurationElement);
}
+ // init parameters for checkers with parameters
+ for (Iterator<IChecker> iterator = problemList.keySet().iterator(); iterator
+ .hasNext();) {
+ IChecker c = iterator.next();
+ if (c instanceof ICheckerWithPreferences) {
+ Collection<IProblem> list = problemList.get(c);
+ for (Iterator<IProblem> iterator2 = list.iterator(); iterator2
+ .hasNext();) {
+ IProblem p = iterator2.next();
+ if (p instanceof IProblemWorkingCopy) {
+ try {
+ ((ICheckerWithPreferences) c)
+ .initPreferences((IProblemWorkingCopy) p);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ CodanCorePlugin.log(t);
+ }
+ }
+ }
+ }
+ }
}
/**
@@ -80,15 +108,15 @@ public class CheckersRegisry implements Iterable<IChecker>, ICheckersRegistry {
*/
private void processCategories(IConfigurationElement configurationElement) {
if (configurationElement.getName().equals(CATEGORY_ELEMENT)) {
- String id = getAtt(configurationElement, "id");
+ String id = getAtt(configurationElement, ID_ATTR);
if (id == null)
return;
- String name = getAtt(configurationElement, "name");
+ String name = getAtt(configurationElement, NAME_ATTR);
if (name == null)
return;
CodanProblemCategory cat = new CodanProblemCategory(id, name);
- String category = getAtt(configurationElement, "parentCategory",
- false);
+ String category = getAtt(configurationElement,
+ "parentCategory", false); //$NON-NLS-1$
addCategory(cat, category);
}
}
@@ -99,16 +127,16 @@ public class CheckersRegisry implements Iterable<IChecker>, ICheckersRegistry {
private void processChecker(IConfigurationElement configurationElement) {
try {
if (configurationElement.getName().equals(CHECKER_ELEMENT)) {
- String id = getAtt(configurationElement, "id");
+ String id = getAtt(configurationElement, ID_ATTR);
if (id == null)
return;
- String name = getAtt(configurationElement, "name", false);
+ String name = getAtt(configurationElement, NAME_ATTR, false);
if (name == null)
name = id;
IChecker checkerObj = null;
try {
Object checker = configurationElement
- .createExecutableExtension("class");
+ .createExecutableExtension("class"); //$NON-NLS-1$
checkerObj = (IChecker) checker;
addChecker(checkerObj);
} catch (CoreException e) {
@@ -116,7 +144,7 @@ public class CheckersRegisry implements Iterable<IChecker>, ICheckersRegistry {
return;
}
IConfigurationElement[] children1 = configurationElement
- .getChildren("problemRef");
+ .getChildren("problemRef"); //$NON-NLS-1$
boolean hasRef = false;
IConfigurationElement[] children2 = configurationElement
.getChildren(PROBLEM_ELEMENT);
@@ -131,7 +159,7 @@ public class CheckersRegisry implements Iterable<IChecker>, ICheckersRegistry {
for (IConfigurationElement ref : children1) {
hasRef = true;
IProblem p = getDefaultProfile().findProblem(
- ref.getAttribute("refId"));
+ ref.getAttribute("refId")); //$NON-NLS-1$
addRefProblem(checkerObj, p);
}
}
@@ -141,7 +169,7 @@ public class CheckersRegisry implements Iterable<IChecker>, ICheckersRegistry {
addRefProblem(checkerObj, p);
}
}
- } catch (Exception e) {
+ } catch (Throwable e) {
CodanCorePlugin.log(e);
}
}
@@ -153,16 +181,37 @@ public class CheckersRegisry implements Iterable<IChecker>, ICheckersRegistry {
private CodanProblem processProblem(
IConfigurationElement configurationElement) {
if (configurationElement.getName().equals(PROBLEM_ELEMENT)) {
- String id = getAtt(configurationElement, "id");
+ String id = getAtt(configurationElement, ID_ATTR);
if (id == null)
return null;
- String name = getAtt(configurationElement, "name");
+ String name = getAtt(configurationElement, NAME_ATTR);
if (name == null)
name = id;
CodanProblem p = new CodanProblem(id, name);
- String category = getAtt(configurationElement, "category", false);
+ String category = getAtt(configurationElement, "category", false); //$NON-NLS-1$
if (category == null)
- category = "org.eclipse.cdt.codan.core.categories.ProgrammingProblems";
+ category = "org.eclipse.cdt.codan.core.categories.ProgrammingProblems"; //$NON-NLS-1$
+ String enab = getAtt(configurationElement, "defaultEnabled", false); //$NON-NLS-1$
+ String sev = getAtt(configurationElement, "defaultSeverity", false); //$NON-NLS-1$
+ String patt = getAtt(configurationElement, "messagePattern", false); //$NON-NLS-1$
+ String desc = getAtt(configurationElement, "description", false); //$NON-NLS-1$
+ String markerType = getAtt(configurationElement,
+ "markerType", false); //$NON-NLS-1$
+ if (enab != null) {
+ p.setEnabled(Boolean.valueOf(enab));
+ }
+ if (sev != null) {
+ CodanSeverity cSev = CodanSeverity.valueOf(sev);
+ if (cSev != null)
+ p.setSeverity(cSev);
+ }
+ if (patt != null) {
+ p.setMessagePattern(patt);
+ }
+ if (markerType != null) {
+ p.setMarkerType(markerType);
+ }
+ p.setDescription(desc);
addProblem(p, category);
return p;
}
@@ -178,11 +227,9 @@ public class CheckersRegisry implements Iterable<IChecker>, ICheckersRegistry {
String name, boolean req) {
String elementValue = configurationElement.getAttribute(name);
if (elementValue == null && req)
- CodanCorePlugin.log("Extension "
- + configurationElement.getDeclaringExtension()
- .getUniqueIdentifier()
- + " missing required attribute: "
- + configurationElement.getName() + "." + name);
+ CodanCorePlugin
+ .log("Extension " + configurationElement.getDeclaringExtension().getUniqueIdentifier() //$NON-NLS-1$
+ + " missing required attribute: " + configurationElement.getName() + "." + name); //$NON-NLS-1$ //$NON-NLS-2$
return elementValue;
}
@@ -195,9 +242,9 @@ public class CheckersRegisry implements Iterable<IChecker>, ICheckersRegistry {
return checkers.iterator();
}
- public static CheckersRegisry getInstance() {
+ public static CheckersRegistry getInstance() {
if (instance == null)
- new CheckersRegisry();
+ return new CheckersRegistry();
return instance;
}
@@ -256,9 +303,10 @@ public class CheckersRegisry implements Iterable<IChecker>, ICheckersRegistry {
}
plist.add(p);
}
-
+
/**
* Returns list of problems registered for given checker
+ *
* @return collection of problems or null
*/
public Collection<IProblem> getRefProblems(IChecker checker) {
@@ -288,18 +336,21 @@ public class CheckersRegisry implements Iterable<IChecker>, ICheckersRegistry {
wp = (IProblemProfile) getDefaultProfile().clone();
// load default values
CodanPreferencesLoader loader = new CodanPreferencesLoader(wp);
- loader.load(CodanCorePlugin.getDefault().getStorePreferences());
+ loader.load(CodanPreferencesLoader.getWorkspaceNode());
} catch (CloneNotSupportedException e) {
wp = getDefaultProfile();
}
+ profiles.put(ResourcesPlugin.getWorkspace(), wp);
}
return wp;
}
public void updateProfile(IResource element, IProblemProfile profile) {
- if (profile == null)
- profiles.remove(element);
- else
+ // updating profile can invalidate all cached profiles
+ IProblemProfile defaultProfile = getDefaultProfile();
+ profiles.clear();
+ profiles.put(DEFAULT, defaultProfile);
+ if (profile != null && element != null)
profiles.put(element, profile);
}
@@ -319,15 +370,14 @@ public class CheckersRegisry implements Iterable<IChecker>, ICheckersRegistry {
// load default values
CodanPreferencesLoader loader = new CodanPreferencesLoader(
prof);
- IEclipsePreferences node = new ProjectScope(
- (IProject) element)
- .getNode(CodanCorePlugin.PLUGIN_ID);
- boolean useWorkspace = node.getBoolean(
+ Preferences projectNode = CodanPreferencesLoader
+ .getProjectNode((IProject) element);
+ boolean useWorkspace = projectNode.getBoolean(
PreferenceConstants.P_USE_PARENT, false);
if (!useWorkspace) {
- loader.load(node);
+ loader.load(projectNode);
}
- updateProfile(element, prof);
+ profiles.put(element, prof);
} catch (CloneNotSupportedException e) {
// cant
}
@@ -348,20 +398,45 @@ public class CheckersRegisry implements Iterable<IChecker>, ICheckersRegistry {
* getResourceProfileWorkingCopy(org.eclipse.core.resources.IResource)
*/
public IProblemProfile getResourceProfileWorkingCopy(IResource element) {
- if (element instanceof IProject) {
- try {
- IProblemProfile prof = (IProblemProfile) getWorkspaceProfile()
- .clone();
- // load default values
- CodanPreferencesLoader loader = new CodanPreferencesLoader(prof);
- IEclipsePreferences node = new ProjectScope((IProject) element)
- .getNode(CodanCorePlugin.PLUGIN_ID);
- loader.load(node);
- return prof;
- } catch (CloneNotSupportedException e) {
- // cant
- }
+ try {
+ IProblemProfile prof = (IProblemProfile) getResourceProfile(element)
+ .clone();
+ return prof;
+ } catch (CloneNotSupportedException e) {
+ // cant
+ return null;
}
- return null;
+ }
+
+ /**
+ * Test if checker is enabled (needs to be run) or not. Checker is enabled
+ * if at least one problem it prints is enabled.
+ *
+ * @param checker
+ * @param resource
+ * @return
+ */
+ public boolean isCheckerEnabled(IChecker checker, IResource resource) {
+ IProblemProfile resourceProfile = getResourceProfile(resource);
+ Collection<IProblem> refProblems = getRefProblems(checker);
+ for (Iterator<IProblem> iterator = refProblems.iterator(); iterator
+ .hasNext();) {
+ IProblem p = iterator.next();
+ // we need to check problem enablement in particular profile
+ IProblem problem = resourceProfile.findProblem(p.getId());
+ if (problem == null)
+ throw new IllegalArgumentException("Id is not registered"); //$NON-NLS-1$
+ if (problem.isEnabled())
+ return true;
+ }
+ // no problem is enabled for this checker, skip the checker
+ return false;
+ }
+
+ /**
+ * @return
+ */
+ public int getCheckersSize() {
+ return checkers.size();
}
}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CodanApplication.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CodanApplication.java
new file mode 100644
index 0000000..188be3c
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CodanApplication.java
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.cdt.codan.internal.core;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.eclipse.cdt.codan.core.CodanRuntime;
+import org.eclipse.cdt.codan.core.Messages;
+import org.eclipse.cdt.codan.internal.core.model.CodanMarkerProblemReporter;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.equinox.app.IApplication;
+import org.eclipse.equinox.app.IApplicationContext;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Application to support headless build
+ *
+ * @noextend This class is not intended to be extended by clients.
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class CodanApplication implements IApplication {
+ private Collection<String> projects = new ArrayList<String>();
+ private boolean verbose = false;
+ private boolean all = false;
+
+ public Object start(IApplicationContext context) throws Exception {
+ String[] args = (String[]) context.getArguments().get(
+ "application.args"); //$NON-NLS-1$
+ 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, String markerType,
+ int severity, IResource file, int lineNumber,
+ int startChar, int endChar, String message) {
+ System.out.println(file.getLocation() + ":" + lineNumber + ": " //$NON-NLS-1$ //$NON-NLS-2$
+ + message);
+ }
+ });
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ if (all) {
+ log(Messages.CodanApplication_LogRunWorkspace);
+ codanBuilder.processResource(root, new NullProgressMonitor());
+ } else {
+ for (String project : projects) {
+ log(Messages.CodanApplication_LogRunProject + project);
+ IProject wProject = root.getProject(project);
+ if (!wProject.exists()) {
+ System.err
+ .println( //
+ NLS.bind(
+ Messages.CodanApplication_Error_ProjectDoesNotExists,
+ project));
+ continue;
+ }
+ codanBuilder.processResource(wProject,
+ new NullProgressMonitor());
+ }
+ }
+ 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")) { //$NON-NLS-1$
+ verbose = true;
+ } else if (string.equals("-all")) { //$NON-NLS-1$
+ all = true;
+ } else {
+ projects.add(string);
+ }
+ }
+ }
+
+ /**
+ *
+ */
+ private void help() {
+ System.out.println(Messages.CodanApplication_Usage);
+ System.out.println(Messages.CodanApplication_Options);
+ System.out.println(Messages.CodanApplication_all_option);
+ System.out.println(Messages.CodanApplication_verbose_option);
+ }
+
+ public void stop() {
+ // nothing
+ }
+}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CodanBuilder.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CodanBuilder.java
index 56916b8..6685b98 100644
--- a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CodanBuilder.java
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CodanBuilder.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,91 +10,74 @@
*******************************************************************************/
package org.eclipse.cdt.codan.internal.core;
-import java.io.File;
-import java.net.URI;
-import java.util.Collection;
-import java.util.Iterator;
import java.util.Map;
import org.eclipse.cdt.codan.core.CodanCorePlugin;
import org.eclipse.cdt.codan.core.CodanRuntime;
-import org.eclipse.cdt.codan.core.model.ICAstChecker;
+import org.eclipse.cdt.codan.core.Messages;
import org.eclipse.cdt.codan.core.model.IChecker;
-import org.eclipse.cdt.codan.core.model.ICodanAstReconciler;
import org.eclipse.cdt.codan.core.model.ICodanBuilder;
-import org.eclipse.cdt.codan.core.model.IProblem;
-import org.eclipse.cdt.codan.core.model.IProblemProfile;
import org.eclipse.cdt.codan.core.model.IProblemReporter;
-import org.eclipse.cdt.codan.internal.core.model.CodanMarkerProblemReporter;
-import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
-import org.eclipse.core.resources.IFile;
+import org.eclipse.cdt.codan.core.model.IProblemReporterPersistent;
+import org.eclipse.cdt.codan.core.model.IRunnableInEditorChecker;
+import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
-import org.eclipse.core.resources.IResourceVisitor;
-import org.eclipse.core.resources.IWorkspace;
-import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.IncrementalProjectBuilder;
-import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.SubProgressMonitor;
+/**
+ * Implementation of {@link ICodanBuilder}
+ */
public class CodanBuilder extends IncrementalProjectBuilder implements
- ICodanBuilder, ICodanAstReconciler {
- public static final String BUILDER_ID = "org.eclipse.cdt.codan.core.codanBuilder";
+ ICodanBuilder {
+ /**
+ * codan builder id
+ */
+ public static final String BUILDER_ID = "org.eclipse.cdt.codan.core.codanBuilder"; //$NON-NLS-1$
- public class CodanDeltaVisitor implements IResourceDeltaVisitor {
- /*
- * (non-Javadoc)
- *
- * @see
- * org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse
- * .core.resources.IResourceDelta)
- */
- /*
- * (non-Javadoc)
- *
- * @see
- * org.eclipse.cdt.codan.internal.core.ICodanBuilder#visit(org.eclipse
- * .core.resources.IResourceDelta)
+ private class CodanDeltaVisitor implements IResourceDeltaVisitor {
+ private IProgressMonitor monitor;
+
+ /**
+ * @param monitor
*/
+ public CodanDeltaVisitor(IProgressMonitor monitor) {
+ this.monitor = monitor;
+ }
+
public boolean visit(IResourceDelta delta) throws CoreException {
IResource resource = delta.getResource();
switch (delta.getKind()) {
- case IResourceDelta.ADDED:
- // handle added resource
- processResource(resource, new NullProgressMonitor());
- break;
- case IResourceDelta.REMOVED:
- // handle removed resource
- break;
- case IResourceDelta.CHANGED:
- // handle changed resource
- processResource(resource, new NullProgressMonitor());
- break;
+ case IResourceDelta.ADDED:
+ // handle added resource
+ processResource(resource, monitor);
+ break;
+ case IResourceDelta.REMOVED:
+ // handle removed resource
+ break;
+ case IResourceDelta.CHANGED:
+ // handle changed resource
+ processResource(resource, monitor);
+ break;
}
// return true to continue visiting children.
return true;
}
}
- public class CodanResourceVisitor implements IResourceVisitor {
- public boolean visit(IResource resource) {
- if (!(resource instanceof IProject))
- processResource(resource, new NullProgressMonitor());
- // return true to continue visiting children.
- return true;
- }
- }
-
/*
* (non-Javadoc)
*
* @see org.eclipse.core.internal.events.InternalBuilder#build(int,
* java.util.Map, org.eclipse.core.runtime.IProgressMonitor)
*/
+ @SuppressWarnings("rawtypes")
+ @Override
protected IProject[] build(int kind, Map args, IProgressMonitor monitor)
throws CoreException {
if (kind == FULL_BUILD) {
@@ -111,119 +94,101 @@ public class CodanBuilder extends IncrementalProjectBuilder implements
}
public void processResource(IResource resource, IProgressMonitor monitor) {
- // String string = Platform.getPreferencesService().getString(
- // CodanCorePlugin.PLUGIN_ID, "problems", "", null);
- // System.err.println("set = " + string);
- // delete general markers
- IProblemReporter problemReporter = CodanRuntime.getInstance()
- .getProblemReporter();
- if (problemReporter instanceof CodanMarkerProblemReporter) {
- ((CodanMarkerProblemReporter) problemReporter)
- .deleteMarkers(resource);
- }
- for (IChecker checker : CheckersRegisry.getInstance()) {
- try {
- boolean run = false;
- if (checker.enabledInContext(resource))
- run = true;
- if (areProblemsForCheckerEnabled(checker, resource))
- run = true;
- if (run)
- checker.processResource(resource);
- } catch (Throwable e) {
- CodanCorePlugin.log(e);
- }
- }
- if (resource instanceof IProject) {
+ processResource(resource, monitor, null, false);
+ }
+
+ protected void processResource(IResource resource,
+ IProgressMonitor monitor, Object model, boolean inEditor) {
+ CheckersRegistry chegistry = CheckersRegistry.getInstance();
+ int checkers = chegistry.getCheckersSize();
+ int memsize = 0;
+ if (resource instanceof IContainer) {
try {
- resource.accept(getResourceVisitor());
+ IResource[] members = ((IContainer) resource).members();
+ memsize = members.length;
} catch (CoreException e) {
CodanCorePlugin.log(e);
}
}
- }
-
- public void reconcileAst(IASTTranslationUnit ast, IProgressMonitor monitor) {
- if (ast == null)
- return;
- String filePath = ast.getFilePath();
- IWorkspace workspace = ResourcesPlugin.getWorkspace();
- IWorkspaceRoot root = workspace.getRoot();
- IFile[] resources;
- URI uri = new File(filePath).toURI();
- resources = root.findFilesForLocationURI(uri);
- if (resources != null && resources.length > 0) {
- IFile resource = resources[0];
+ int tick = 1000;
+ // System.err.println("processing " + resource);
+ monitor.beginTask(Messages.CodanBuilder_Code_Analysis_On + resource,
+ checkers + memsize * tick);
+ try {
IProblemReporter problemReporter = CodanRuntime.getInstance()
.getProblemReporter();
- // TODO: this is wrong - should not delete all markers -
- // only those that contributed by the checker that we run now
- if (problemReporter instanceof CodanMarkerProblemReporter) {
- ((CodanMarkerProblemReporter) problemReporter)
- .deleteMarkers(resource);
- }
- for (IChecker checker : CheckersRegisry.getInstance()) {
+ for (IChecker checker : chegistry) {
try {
- boolean run = false;
- if (checker.enabledInContext(resource))
- run = true;
- if (areProblemsForCheckerEnabled(checker, resource)) {
- run = true;
+ if (monitor.isCanceled())
+ return;
+ if (checker.enabledInContext(resource)) {
+ // delete markers if checker can possibly run on this
+ // resource
+ // this way if checker is not enabled markers would be
+ // deleted too
+ if (problemReporter instanceof IProblemReporterPersistent) {
+ // delete general markers
+ ((IProblemReporterPersistent) problemReporter)
+ .deleteProblems(resource, checker);
+ }
+ if (chegistry.isCheckerEnabled(checker, resource)) {
+ if (inEditor) {
+ if (checker.runInEditor()
+ && checker instanceof IRunnableInEditorChecker) {
+ ((IRunnableInEditorChecker) checker)
+ .processModel(model);
+ }
+ } else {
+ checker.processResource(resource);
+ }
+ }
}
- if (run && checker instanceof ICAstChecker
- && checker.runInEditor())
- ((ICAstChecker) checker).processAst(ast);
+ monitor.worked(1);
} catch (Throwable e) {
CodanCorePlugin.log(e);
}
}
+ if (resource instanceof IContainer) {
+ try {
+ IResource[] members = ((IContainer) resource).members();
+ for (int i = 0; i < members.length; i++) {
+ if (monitor.isCanceled())
+ return;
+ IResource member = members[i];
+ processResource(member, new SubProgressMonitor(monitor,
+ tick));
+ }
+ } catch (CoreException e) {
+ CodanCorePlugin.log(e);
+ }
+ }
+ } finally {
+ monitor.done();
}
}
- /**
- * @param checker
- * @param resource
- * @return
- */
- private boolean areProblemsForCheckerEnabled(IChecker checker,
- IResource resource) {
- IProblemProfile resourceProfile = CheckersRegisry.getInstance()
- .getResourceProfile(resource);
- Collection<IProblem> refProblems = CheckersRegisry.getInstance()
- .getRefProblems(checker);
- for (Iterator iterator = refProblems.iterator(); iterator.hasNext();) {
- IProblem p = (IProblem) iterator.next();
- // we need to check problem enablement in particular profile
- IProblem problem = resourceProfile.findProblem(p.getId());
- if (problem == null)
- throw new IllegalArgumentException("Id is not registered");
- if (problem.isEnabled())
- return true;
- }
- // no problem is enabled for this checker, skip the checker
- return false;
- }
-
protected void fullBuild(final IProgressMonitor monitor)
throws CoreException {
- try {
- getProject().accept(new CodanResourceVisitor());
- } catch (CoreException e) {
- }
+ processResource(getProject(), monitor);
}
protected void incrementalBuild(IResourceDelta delta,
IProgressMonitor monitor) throws CoreException {
// the visitor does the work.
- delta.accept(new CodanDeltaVisitor());
+ delta.accept(new CodanDeltaVisitor(monitor));
}
- /*
- * (non-Javadoc)
+ /**
+ * Run all checkers that support "check as you type" mode
*
- * @see org.eclipse.cdt.codan.core.model.ICodanBuilder#getResourceVisitor()
+ * @param model - model of given resource such as ast
+ * @param resource - resource to process
+ * @param monitor - progress monitor
*/
- public CodanResourceVisitor getResourceVisitor() {
- return new CodanResourceVisitor();
+ public void runInEditor(Object model, IResource resource,
+ IProgressMonitor monitor) {
+ if (model == null)
+ return;
+ processResource(resource, monitor, model, true);
}
}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CodanPreferencesLoader.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CodanPreferencesLoader.java
index bafff9a..38af027 100644
--- a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CodanPreferencesLoader.java
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CodanPreferencesLoader.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,38 +10,50 @@
*******************************************************************************/
package org.eclipse.cdt.codan.internal.core;
+import org.eclipse.cdt.codan.core.CodanCorePlugin;
import org.eclipse.cdt.codan.core.model.CodanSeverity;
import org.eclipse.cdt.codan.core.model.IProblem;
import org.eclipse.cdt.codan.core.model.IProblemProfile;
-import org.eclipse.cdt.codan.internal.core.model.CodanProblem;
-import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.cdt.codan.core.model.IProblemWorkingCopy;
+import org.eclipse.cdt.codan.core.param.IProblemPreference;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.osgi.service.prefs.Preferences;
/**
- * @author Alena
+ * Helper class to load/save problem profile settings in persistent storage
*
*/
public class CodanPreferencesLoader {
private IProblemProfile baseModel;
/**
- * @param workspaceProfile
+ * Constructor
+ *
+ * @param profile - problem profile to work with
*/
public CodanPreferencesLoader(IProblemProfile profile) {
setInput(profile);
}
/**
- *
+ * Default constructor
*/
public CodanPreferencesLoader() {
}
- public void setInput(Object model) {
- baseModel = (IProblemProfile) model;
+ /**
+ * Sets the profile for this class
+ *
+ * @param profile
+ */
+ public void setInput(IProblemProfile profile) {
+ baseModel = profile;
}
/**
- * @return
+ * @return problems array from the profile
*/
public IProblem[] getProblems() {
IProblem[] problems = baseModel.getProblems();
@@ -54,66 +66,144 @@ public class CodanPreferencesLoader {
*/
public void setProperty(String id, String s) {
IProblem prob = baseModel.findProblem(id);
- if (!(prob instanceof CodanProblem))
+ if (!(prob instanceof IProblemWorkingCopy))
return;
String sevs = s;
boolean enabled = true;
- if (sevs.startsWith("-")) {
+ if (sevs.startsWith("-")) { //$NON-NLS-1$
sevs = sevs.substring(1);
enabled = false;
}
- ((CodanProblem) prob).setEnabled(enabled);
+ ((IProblemWorkingCopy) prob).setEnabled(enabled);
CodanSeverity sev;
try {
sev = CodanSeverity.valueOf(sevs);
} catch (RuntimeException e) {
sev = CodanSeverity.Warning;
}
- ((CodanProblem) prob).setSeverity(sev);
+ ((IProblemWorkingCopy) prob).setSeverity(sev);
}
- /*
- * (non-Javadoc)
- *
- * @see java.lang.Object#toString()
- */
@Override
public String toString() {
return getInput().toString();
}
/**
- * @return
+ * @return problem profile set for this class
*/
public IProblemProfile getInput() {
return baseModel;
}
/**
- * @param id
- * @return
+ * @param id - property id, which is the same as problem id
+ * @return get text representation of a "property" value for the given id,
+ * which is severity name, with "-" in front of it it problem is
+ * disabled.
*/
public String getProperty(String id) {
IProblem prob = baseModel.findProblem(id);
- if (!(prob instanceof CodanProblem))
- return null;
- String enabled = prob.isEnabled() ? "" : "-";
+ String enabled = prob.isEnabled() ? "" : "-"; //$NON-NLS-1$ //$NON-NLS-2$
String severity = prob.getSeverity().toString();
String res = enabled + severity;
return res;
}
/**
+ * Takes string values from storePreferences and applies them to the problem
+ * profile
+ *
* @param storePreferences
*/
- public void load(IEclipsePreferences storePreferences) {
+ public void load(Preferences storePreferences) {
IProblem[] probs = getProblems();
for (int i = 0; i < probs.length; i++) {
String id = probs[i].getId();
String s = storePreferences.get(id, null);
if (s != null) {
setProperty(id, s);
+ setProblemPreferenceValues(id, storePreferences);
}
}
}
+
+ /**
+ * Takes string values of the problem preferences from storePreferences
+ * and applies them to the problem profile
+ *
+ * @param problemId
+ * @param storePreferences
+ */
+ private void setProblemPreferenceValues(String problemId,
+ Preferences storePreferences) {
+ IProblem prob = baseModel.findProblem(problemId);
+ String prefKey = getPreferencesKey(problemId);
+ if (prefKey == null)
+ return;
+ String exported = storePreferences.get(prefKey, null);
+ if (exported != null) {
+ //System.err.println(prefKey + " import " + exported);
+ prob.getPreference().importValue(exported);
+ }
+ }
+
+ /**
+ * Return preference node (osgi preferences) for the project
+ *
+ * @param project
+ * @return project preferences node
+ */
+ public static Preferences getProjectNode(IProject project) {
+ if (!project.exists())
+ return null;
+ Preferences prefNode = new ProjectScope(project)
+ .getNode(CodanCorePlugin.PLUGIN_ID);
+ if (prefNode == null)
+ return null;
+ return prefNode;
+ }
+
+ /**
+ * Return preference node (osgi preferences) for the workspace
+ *
+ * @return project preferences node
+ */
+ public static Preferences getWorkspaceNode() {
+ Preferences prefNode = new InstanceScope()
+ .getNode(CodanCorePlugin.PLUGIN_ID);
+ if (prefNode == null)
+ return null;
+ return prefNode;
+ }
+
+ /**
+ * Name of the preference key for the root problem preference in the osgi
+ * preferences
+ *
+ * @param id - problem id
+ * @return top level preference id
+ */
+ public String getPreferencesKey(String id) {
+ IProblem prob = baseModel.findProblem(id);
+ IProblemPreference pref = prob.getPreference();
+ if (pref == null)
+ return null;
+ return id + "." + pref.getKey(); //$NON-NLS-1$
+ }
+
+ /**
+ * @param id - problem id
+ * @return - export value of root problem preference (to be saved in eclipse
+ * preferences)
+ */
+ public String getPreferencesString(String id) {
+ IProblem prob = baseModel.findProblem(id);
+ IProblemPreference pref = prob.getPreference();
+ if (pref == null)
+ return null;
+ String str = pref.exportValue();
+ //System.err.println(id + " set " + str);
+ return str;
+ }
}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CodeAnlysisNature.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CodeAnlysisNature.java
index 5157e16..f73ee61 100644
--- a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CodeAnlysisNature.java
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/CodeAnlysisNature.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
@@ -16,18 +16,16 @@ import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IProjectNature;
import org.eclipse.core.runtime.CoreException;
+/**
+ * Code Analysis Nature for builder
+ */
public class CodeAnlysisNature implements IProjectNature {
/**
* ID of this project nature
*/
- public static final String NATURE_ID = "org.eclipse.cdt.codan.core.codanNature";
+ public static final String NATURE_ID = "org.eclipse.cdt.codan.core.codanNature"; //$NON-NLS-1$
private IProject project;
- /*
- * (non-Javadoc)
- *
- * @see org.eclipse.core.resources.IProjectNature#configure()
- */
public void configure() throws CoreException {
IProjectDescription desc = project.getDescription();
ICommand[] commands = desc.getBuildSpec();
@@ -45,11 +43,6 @@ public class CodeAnlysisNature implements IProjectNature {
project.setDescription(desc, null);
}
- /*
- * (non-Javadoc)
- *
- * @see org.eclipse.core.resources.IProjectNature#deconfigure()
- */
public void deconfigure() throws CoreException {
IProjectDescription description = getProject().getDescription();
ICommand[] commands = description.getBuildSpec();
@@ -66,22 +59,10 @@ public class CodeAnlysisNature implements IProjectNature {
}
}
- /*
- * (non-Javadoc)
- *
- * @see org.eclipse.core.resources.IProjectNature#getProject()
- */
public IProject getProject() {
return project;
}
- /*
- * (non-Javadoc)
- *
- * @see
- * org.eclipse.core.resources.IProjectNature#setProject(org.eclipse.core
- * .resources.IProject)
- */
public void setProject(IProject project) {
this.project = project;
}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/AbstractBasicBlock.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/AbstractBasicBlock.java
new file mode 100644
index 0000000..15a191a
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/AbstractBasicBlock.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.cdt.codan.internal.core.cfg;
+
+import org.eclipse.cdt.codan.core.model.cfg.IBasicBlock;
+import org.eclipse.cdt.codan.core.model.cfg.ICfgData;
+
+/**
+ * Abstract Basic Block for control flow graph.
+ */
+public abstract class AbstractBasicBlock implements IBasicBlock, ICfgData {
+ /**
+ * Empty array of basic blocks
+ */
+ public final static IBasicBlock[] EMPTY_LIST = new IBasicBlock[0];
+ private Object data;
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+
+ /**
+ * Add a node to list of outgoing nodes of this node
+ *
+ * @param node - node to add
+ */
+ public abstract void addOutgoing(IBasicBlock node);
+
+ /**
+ * Add a node to list of incoming nodes of this node
+ *
+ * @param node - node to add
+ */
+ public abstract void addIncoming(IBasicBlock node);
+
+ /**
+ * @return toString for data object
+ */
+ public String toStringData() {
+ if (getData() == null)
+ return "0x" + Integer.toHexString(System.identityHashCode(this)); //$NON-NLS-1$
+ return getData().toString();
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + ": " + toStringData(); //$NON-NLS-1$
+ }
+}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/AbstractSingleIncomingNode.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/AbstractSingleIncomingNode.java
new file mode 100644
index 0000000..9054f2a
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/AbstractSingleIncomingNode.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.cdt.codan.internal.core.cfg;
+
+import org.eclipse.cdt.codan.core.model.cfg.IBasicBlock;
+import org.eclipse.cdt.codan.core.model.cfg.ISingleIncoming;
+
+/**
+ * Abstract node with one incoming arc (node)
+ *
+ */
+public abstract class AbstractSingleIncomingNode extends AbstractBasicBlock
+ implements ISingleIncoming {
+ private IBasicBlock prev;
+
+ /**
+ * Default constructor
+ */
+ public AbstractSingleIncomingNode() {
+ super();
+ }
+
+ public IBasicBlock[] getIncomingNodes() {
+ return new IBasicBlock[] { prev };
+ }
+
+ public int getIncomingSize() {
+ return 1;
+ }
+
+ public IBasicBlock getIncoming() {
+ return prev;
+ }
+
+ /**
+ * Sets the incoming node
+ *
+ * @param prev
+ */
+ public void setIncoming(IBasicBlock prev) {
+ this.prev = prev;
+ }
+
+ @Override
+ public void addIncoming(IBasicBlock node) {
+ setIncoming(node);
+ }
+}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/AbstractSingleOutgoingNode.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/AbstractSingleOutgoingNode.java
new file mode 100644
index 0000000..e4f7fcf
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/AbstractSingleOutgoingNode.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.cdt.codan.internal.core.cfg;
+
+import org.eclipse.cdt.codan.core.model.cfg.IBasicBlock;
+import org.eclipse.cdt.codan.core.model.cfg.ISingleOutgoing;
+
+/**
+ * Abstract implementation of basic block with single outgoing arc (node)
+ *
+ */
+public abstract class AbstractSingleOutgoingNode extends AbstractBasicBlock
+ implements ISingleOutgoing {
+ private IBasicBlock next;
+
+ /**
+ * Default constructor
+ */
+ public AbstractSingleOutgoingNode() {
+ super();
+ }
+
+ public IBasicBlock[] getOutgoingNodes() {
+ return new IBasicBlock[] { next };
+ }
+
+ public int getOutgoingSize() {
+ return 1;
+ }
+
+ public IBasicBlock getOutgoing() {
+ return next;
+ }
+
+ /**
+ * Sets outgoing node
+ *
+ * @param node
+ */
+ public void setOutgoing(IBasicBlock node) {
+ this.next = node;
+ }
+
+ @Override
+ public void addOutgoing(IBasicBlock node) {
+ setOutgoing(node);
+ }
+}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/BranchNode.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/BranchNode.java
new file mode 100644
index 0000000..ecd99e1
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/BranchNode.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.internal.core.cfg;
+
+import org.eclipse.cdt.codan.core.model.cfg.IBranchNode;
+
+/**
+ * Branch node is a node with on incoming arc, one outgoing arc and a "string"
+ * label. Can be used to represent branches of if, switch and labelled
+ * statements.
+ */
+public class BranchNode extends PlainNode implements IBranchNode {
+ protected String label;
+
+ protected BranchNode(String label) {
+ super();
+ this.label = label;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ @Override
+ public String toStringData() {
+ return label;
+ }
+}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/CVS/Entries b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/CVS/Entries
new file mode 100644
index 0000000..bd763ef
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/CVS/Entries
@@ -0,0 +1,12 @@
+/AbstractBasicBlock.java/1.10/Thu Jun 3 17:01:52 2010//TCDT_7_0_0
+/AbstractSingleIncomingNode.java/1.6/Thu Jun 3 17:01:52 2010//TCDT_7_0_0
+/AbstractSingleOutgoingNode.java/1.6/Thu Jun 3 17:01:52 2010//TCDT_7_0_0
+/BranchNode.java/1.5/Thu Jun 3 17:01:52 2010//TCDT_7_0_0
+/ConnectorNode.java/1.7/Thu Jun 3 17:01:52 2010//TCDT_7_0_0
+/ControlFlowGraph.java/1.11/Thu Jun 3 17:01:52 2010//TCDT_7_0_0
+/DecisionNode.java/1.9/Thu Jun 3 17:01:52 2010//TCDT_7_0_0
+/ExitNode.java/1.6/Thu Jun 3 17:01:52 2010//TCDT_7_0_0
+/JumpNode.java/1.9/Thu Jun 3 17:01:52 2010//TCDT_7_0_0
+/NodeFactory.java/1.2/Thu Jun 3 17:01:52 2010//TCDT_7_0_0
+/PlainNode.java/1.8/Thu Jun 3 17:01:52 2010//TCDT_7_0_0
+/StartNode.java/1.8/Thu Jun 3 17:01:52 2010//TCDT_7_0_0
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/CVS/Repository b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/CVS/Repository
new file mode 100644
index 0000000..34bede2
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/CVS/Repository
@@ -0,0 +1 @@
+org.eclipse.cdt/codan/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/CVS/Root b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/CVS/Root
new file mode 100644
index 0000000..04efa23
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/CVS/Root
@@ -0,0 +1 @@
+:pserver:anonymous@dev.eclipse.org:/cvsroot/tools
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/CVS/Tag b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/CVS/Tag
new file mode 100644
index 0000000..49a449a
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/CVS/Tag
@@ -0,0 +1 @@
+NCDT_7_0_0
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/ConnectorNode.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/ConnectorNode.java
new file mode 100644
index 0000000..7c91818
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/ConnectorNode.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * 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.internal.core.cfg;
+
+import java.util.ArrayList;
+
+import org.eclipse.cdt.codan.core.model.cfg.IBasicBlock;
+import org.eclipse.cdt.codan.core.model.cfg.IConnectorNode;
+import org.eclipse.cdt.codan.core.model.cfg.IJumpNode;
+
+/**
+ * TODO: add description
+ */
+public class ConnectorNode extends AbstractSingleOutgoingNode implements
+ IConnectorNode {
+ protected ArrayList<IBasicBlock> incoming = new ArrayList<IBasicBlock>(2);
+
+ protected ConnectorNode() {
+ super();
+ }
+
+ @Override
+ public void addIncoming(IBasicBlock node) {
+ incoming.add(node);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock#
+ * getIncomingIterator()
+ */
+ public IBasicBlock[] getIncomingNodes() {
+ return incoming.toArray(new IBasicBlock[incoming.size()]);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.cdt.codan.core.model.cfg.IBasicBlock#getIncomingSize ()
+ */
+ public int getIncomingSize() {
+ return incoming.size();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IConnectorNode#
+ * hasBackwardIncoming()
+ */
+ public boolean hasBackwardIncoming() {
+ for (IBasicBlock node : incoming) {
+ if (node instanceof IJumpNode) {
+ if (((IJumpNode) node).isBackwardArc())
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/ControlFlowGraph.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/ControlFlowGraph.java
new file mode 100644
index 0000000..8133e8c
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/ControlFlowGraph.java
@@ -0,0 +1,147 @@
+/*******************************************************************************
+ * 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.internal.core.cfg;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+
+import org.eclipse.cdt.codan.core.model.cfg.IBasicBlock;
+import org.eclipse.cdt.codan.core.model.cfg.IBranchNode;
+import org.eclipse.cdt.codan.core.model.cfg.IConnectorNode;
+import org.eclipse.cdt.codan.core.model.cfg.IControlFlowGraph;
+import org.eclipse.cdt.codan.core.model.cfg.IDecisionNode;
+import org.eclipse.cdt.codan.core.model.cfg.IExitNode;
+import org.eclipse.cdt.codan.core.model.cfg.ISingleOutgoing;
+import org.eclipse.cdt.codan.core.model.cfg.IStartNode;
+
+/**
+ * Implementation of control flow graph
+ */
+public class ControlFlowGraph implements IControlFlowGraph {
+ private List<IExitNode> exitNodes;
+ private List<IBasicBlock> deadNodes = new ArrayList<IBasicBlock>();
+ private IStartNode start;
+
+ public ControlFlowGraph(IStartNode start, Collection<IExitNode> exitNodes) {
+ setExitNodes(exitNodes);
+ this.start = start;
+ }
+
+ public Iterator<IExitNode> getExitNodeIterator() {
+ return exitNodes.iterator();
+ }
+
+ public int getExitNodeSize() {
+ return exitNodes.size();
+ }
+
+ public void setExitNodes(Collection<IExitNode> exitNodes) {
+ if (this.exitNodes != null)
+ throw new IllegalArgumentException(
+ "Cannot modify already exiting connector"); //$NON-NLS-1$
+ this.exitNodes = Collections.unmodifiableList(new ArrayList<IExitNode>(
+ exitNodes));
+ }
+
+ public void setUnconnectedNodes(Collection<IBasicBlock> nodes) {
+ this.deadNodes = Collections
+ .unmodifiableList(new ArrayList<IBasicBlock>(nodes));
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IControlFlowGraph#
+ * getStartNode()
+ */
+ public IStartNode getStartNode() {
+ return start;
+ }
+
+ void setStartNode(IStartNode start) {
+ this.start = start;
+ }
+
+ public void print(IBasicBlock node) {
+ System.out.println(node.getClass().getSimpleName() + ": " //$NON-NLS-1$
+ + ((AbstractBasicBlock) node).toStringData());
+ if (node instanceof IDecisionNode) {
+ // todo
+ IBasicBlock[] branches = ((IDecisionNode) node).getOutgoingNodes();
+ for (int i = 0; i < branches.length; i++) {
+ IBasicBlock brNode = branches[i];
+ System.out.println("{"); //$NON-NLS-1$
+ print(brNode);
+ System.out.println("}"); //$NON-NLS-1$
+ }
+ print(((IDecisionNode) node).getMergeNode());
+ } else if (node instanceof ISingleOutgoing) {
+ IBasicBlock next = ((ISingleOutgoing) node).getOutgoing();
+ if (!(next instanceof IConnectorNode && !(next instanceof IBranchNode)))
+ print(next);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IControlFlowGraph#
+ * getUnconnectedNodeIterator()
+ */
+ public Iterator<IBasicBlock> getUnconnectedNodeIterator() {
+ return deadNodes.iterator();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IControlFlowGraph#
+ * getUnconnectedNodeSize()
+ */
+ public int getUnconnectedNodeSize() {
+ return deadNodes.size();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.cdt.codan.core.model.cfg.IControlFlowGraph#getNodes ()
+ */
+ public Collection<IBasicBlock> getNodes() {
+ Collection<IBasicBlock> result = new LinkedHashSet<IBasicBlock>();
+ getNodes(getStartNode(), result);
+ for (Iterator<IBasicBlock> iterator = deadNodes.iterator(); iterator
+ .hasNext();) {
+ IBasicBlock d = iterator.next();
+ getNodes(d, result);
+ }
+ return result;
+ }
+
+ /**
+ * @param d
+ * @param result
+ */
+ private void getNodes(IBasicBlock start, Collection<IBasicBlock> result) {
+ if (result.contains(start))
+ return;
+ result.add(start);
+ IBasicBlock[] outgoingNodes = start.getOutgoingNodes();
+ for (int i = 0; i < outgoingNodes.length; i++) {
+ IBasicBlock b = outgoingNodes[i];
+ getNodes(b, result);
+ }
+ }
+}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/DecisionNode.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/DecisionNode.java
new file mode 100644
index 0000000..df0da9c
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/DecisionNode.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * 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.internal.core.cfg;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.cdt.codan.core.model.cfg.IBasicBlock;
+import org.eclipse.cdt.codan.core.model.cfg.IBranchNode;
+import org.eclipse.cdt.codan.core.model.cfg.IConnectorNode;
+import org.eclipse.cdt.codan.core.model.cfg.IDecisionNode;
+
+/**
+ * @see {@link IDecisionNode}
+ */
+public class DecisionNode extends AbstractSingleIncomingNode implements
+ IDecisionNode {
+ private List<IBasicBlock> next = new ArrayList<IBasicBlock>(2);
+ private IConnectorNode conn;
+
+ /**
+ * @param prev
+ */
+ protected DecisionNode() {
+ super();
+ }
+
+ @Override
+ public void addOutgoing(IBasicBlock node) {
+ IBranchNode cnode = (IBranchNode) node; // cast to throw CCE
+ next.add(cnode);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock#
+ * getOutgoingIterator()
+ */
+ public IBasicBlock[] getOutgoingNodes() {
+ return next.toArray(new IBasicBlock[next.size()]);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.cdt.codan.core.model.cfg.IBasicBlock#getOutgoingSize ()
+ */
+ public int getOutgoingSize() {
+ return next.size();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IDecisionNode#
+ * getConnectionNode()
+ */
+ public IConnectorNode getMergeNode() {
+ return conn;
+ }
+
+ public void setMergeNode(IConnectorNode conn) {
+ this.conn = conn;
+ }
+}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/ExitNode.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/ExitNode.java
new file mode 100644
index 0000000..7bd9848
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/ExitNode.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.cdt.codan.internal.core.cfg;
+
+import org.eclipse.cdt.codan.core.model.cfg.IBasicBlock;
+import org.eclipse.cdt.codan.core.model.cfg.IExitNode;
+import org.eclipse.cdt.codan.core.model.cfg.IStartNode;
+
+/**
+ * Plain node has one prev one jump
+ *
+ */
+public class ExitNode extends AbstractSingleIncomingNode implements IExitNode {
+ private IStartNode start;
+
+ protected ExitNode() {
+ super();
+ }
+
+ public IBasicBlock[] getOutgoingNodes() {
+ return EMPTY_LIST;
+ }
+
+ public int getOutgoingSize() {
+ return 0;
+ }
+
+ public IStartNode getStartNode() {
+ return start;
+ }
+
+ public void setStartNode(IStartNode start) {
+ this.start = start;
+ }
+
+ @Override
+ public void addOutgoing(IBasicBlock node) {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/JumpNode.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/JumpNode.java
new file mode 100644
index 0000000..b5198d0
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/JumpNode.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.cdt.codan.internal.core.cfg;
+
+import org.eclipse.cdt.codan.core.model.cfg.IBasicBlock;
+import org.eclipse.cdt.codan.core.model.cfg.IConnectorNode;
+import org.eclipse.cdt.codan.core.model.cfg.IJumpNode;
+
+/**
+ * Jump node is node that connects unusual control pass, such as goto, break and
+ * continue
+ *
+ */
+public class JumpNode extends AbstractSingleIncomingNode implements IJumpNode {
+ private IConnectorNode jump;
+ private boolean backward;
+
+ protected JumpNode() {
+ super();
+ }
+
+ public IBasicBlock[] getOutgoingNodes() {
+ return new IBasicBlock[] { jump };
+ }
+
+ public int getOutgoingSize() {
+ return 1;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.cdt.codan.core.model.cfg.IJumpNode#getJumpNode()
+ */
+ public IConnectorNode getJumpNode() {
+ return jump;
+ }
+
+ public IBasicBlock getOutgoing() {
+ return jump;
+ }
+
+ public boolean isBackwardArc() {
+ return backward;
+ }
+
+ public void setJump(IConnectorNode jump, boolean backward) {
+ if (this.jump != null && this.jump != jump)
+ throw new IllegalArgumentException(
+ "Cannot modify exiting connector"); //$NON-NLS-1$
+ this.jump = jump;
+ this.backward = backward;
+ }
+
+ public void setBackward(boolean backward) {
+ this.backward = backward;
+ }
+
+ @Override
+ public void addOutgoing(IBasicBlock node) {
+ setJump((IConnectorNode) node, backward);
+ }
+}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/NodeFactory.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/NodeFactory.java
new file mode 100644
index 0000000..0de0734
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/NodeFactory.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * 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.internal.core.cfg;
+
+import org.eclipse.cdt.codan.core.model.cfg.IBranchNode;
+import org.eclipse.cdt.codan.core.model.cfg.IConnectorNode;
+import org.eclipse.cdt.codan.core.model.cfg.IControlFlowGraph;
+import org.eclipse.cdt.codan.core.model.cfg.IDecisionNode;
+import org.eclipse.cdt.codan.core.model.cfg.IExitNode;
+import org.eclipse.cdt.codan.core.model.cfg.IJumpNode;
+import org.eclipse.cdt.codan.core.model.cfg.INodeFactory;
+import org.eclipse.cdt.codan.core.model.cfg.IPlainNode;
+import org.eclipse.cdt.codan.core.model.cfg.IStartNode;
+
+/**
+ * Factory that creates cfg nodes
+ */
+public class NodeFactory implements INodeFactory {
+ IControlFlowGraph graph;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.INodeFactory#
+ * getControlFlowGraph()
+ */
+ public IControlFlowGraph getControlFlowGraph() {
+ return graph;
+ }
+
+ public NodeFactory() {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.cdt.codan.core.model.cfg.INodeFactory#createPlainNode ()
+ */
+ public IPlainNode createPlainNode() {
+ return new PlainNode();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.cdt.codan.core.model.cfg.INodeFactory#createJumpNode ()
+ */
+ public IJumpNode createJumpNode() {
+ return new JumpNode();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.INodeFactory#
+ * createDecisionNode()
+ */
+ public IDecisionNode createDecisionNode() {
+ return new DecisionNode();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.INodeFactory#
+ * createConnectiorNode()
+ */
+ public IConnectorNode createConnectorNode() {
+ return new ConnectorNode();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.cdt.codan.core.model.cfg.INodeFactory#createStartNode ()
+ */
+ public IStartNode createStartNode() {
+ return new StartNode();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.cdt.codan.core.model.cfg.INodeFactory#createExitNode ()
+ */
+ public IExitNode createExitNode() {
+ return new ExitNode();
+ }
+
+ public IBranchNode createBranchNode(String label) {
+ return new BranchNode(label);
+ }
+}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/PlainNode.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/PlainNode.java
new file mode 100644
index 0000000..d382fb4
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/PlainNode.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.cdt.codan.internal.core.cfg;
+
+import org.eclipse.cdt.codan.core.model.cfg.IBasicBlock;
+import org.eclipse.cdt.codan.core.model.cfg.IPlainNode;
+
+/**
+ * Plain node has one incoming arc and one outgoing arc
+ *
+ */
+public class PlainNode extends AbstractSingleIncomingNode implements IPlainNode {
+ protected IBasicBlock next;
+
+ protected PlainNode() {
+ super();
+ }
+
+ public IBasicBlock[] getOutgoingNodes() {
+ return new IBasicBlock[] { next };
+ }
+
+ public int getOutgoingSize() {
+ return 1;
+ }
+
+ public IBasicBlock getOutgoing() {
+ return next;
+ }
+
+ public void setOutgoing(IBasicBlock exit) {
+ this.next = exit;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.cdt.codan.internal.core.cfg.AbstractBasicBlock#addOutgoing
+ * (org.eclipse.cdt.codan.core.model.cfg.IBasicBlock)
+ */
+ @Override
+ public void addOutgoing(IBasicBlock node) {
+ setOutgoing(node);
+ }
+}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/StartNode.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/StartNode.java
new file mode 100644
index 0000000..4d64bad
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/cfg/StartNode.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.cdt.codan.internal.core.cfg;
+
+import org.eclipse.cdt.codan.core.model.cfg.IBasicBlock;
+import org.eclipse.cdt.codan.core.model.cfg.IStartNode;
+
+/**
+ * Start node has no incoming, one outgoing and it is connect to function exits
+ *
+ */
+public class StartNode extends AbstractSingleOutgoingNode implements IStartNode {
+ protected StartNode() {
+ super();
+ }
+
+ public IBasicBlock[] getIncomingNodes() {
+ return EMPTY_LIST;
+ }
+
+ public int getIncomingSize() {
+ return 0;
+ }
+
+ @Override
+ public void addOutgoing(IBasicBlock node) {
+ setOutgoing(node);
+ }
+
+ @Override
+ public void addIncoming(IBasicBlock node) {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CVS/Entries b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CVS/Entries
index 5f7a029..182ee54 100644
--- a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CVS/Entries
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CVS/Entries
@@ -1,5 +1,6 @@
-/CodanMarkerProblemReporter.java/1.2/Wed Dec 16 21:48:48 2009//
-/CodanProblem.java/1.1/Sat Aug 22 21:16:48 2009//
-/CodanProblemCategory.java/1.2/Wed Dec 16 21:48:48 2009//
-/ProblemProfile.java/1.1/Wed Sep 23 23:29:36 2009//
-D
+/CodanMarkerProblemReporter.java/1.15/Sun Jun 27 01:30:42 2010//TCDT_7_0_0
+/CodanProblem.java/1.9/Sun Jun 27 01:30:42 2010//TCDT_7_0_0
+/CodanProblemCategory.java/1.4/Sun Jun 27 01:30:42 2010//TCDT_7_0_0
+/CodanProblemLocation.java/1.4/Sun Jun 27 01:30:42 2010//TCDT_7_0_0
+/ProblemLocationFactory.java/1.3/Sun Jun 27 01:30:42 2010//TCDT_7_0_0
+/ProblemProfile.java/1.3/Sun Jun 27 01:30:42 2010//TCDT_7_0_0
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CVS/Tag b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CVS/Tag
new file mode 100644
index 0000000..49a449a
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CVS/Tag
@@ -0,0 +1 @@
+NCDT_7_0_0
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanMarkerProblemReporter.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanMarkerProblemReporter.java
index a4599c5..51a4794 100644
--- a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanMarkerProblemReporter.java
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanMarkerProblemReporter.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,39 +11,40 @@
package org.eclipse.cdt.codan.internal.core.model;
import java.text.MessageFormat;
+import java.util.Collection;
+import java.util.Iterator;
+import org.eclipse.cdt.codan.core.CodanCorePlugin;
+import org.eclipse.cdt.codan.core.CodanRuntime;
+import org.eclipse.cdt.codan.core.model.IChecker;
+import org.eclipse.cdt.codan.core.model.ICheckersRegistry;
import org.eclipse.cdt.codan.core.model.IProblem;
import org.eclipse.cdt.codan.core.model.IProblemLocation;
-import org.eclipse.cdt.codan.core.model.IProblemReporter;
-import org.eclipse.cdt.codan.internal.core.CheckersRegisry;
-import org.eclipse.core.resources.IFile;
+import org.eclipse.cdt.codan.core.model.IProblemReporterPersistent;
+import org.eclipse.cdt.codan.internal.core.CheckersRegistry;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
-public class CodanMarkerProblemReporter implements IProblemReporter {
-
-
- /*
- * (non-Javadoc)
- *
- * @see
- * org.eclipse.cdt.codan.core.model.IProblemReporter#reportProblem(java.
- * lang.String, org.eclipse.cdt.codan.core.model.IProblemLocation,
- * java.lang.Object[])
- */
+/**
+ * Problem reported that created eclipse markers
+ */
+public class CodanMarkerProblemReporter implements IProblemReporterPersistent {
public void reportProblem(String id, IProblemLocation loc, Object... args) {
- IFile file = loc.getFile();
+ IResource file = loc.getFile();
int lineNumber = loc.getLineNumber();
if (file == null)
- throw new NullPointerException("file");
+ throw new NullPointerException("file"); //$NON-NLS-1$
if (id == null)
- throw new NullPointerException("id");
- IProblem problem = CheckersRegisry.getInstance().getResourceProfile(
- file).findProblem(id);
+ throw new NullPointerException("id"); //$NON-NLS-1$
+ IProblem problem = CheckersRegistry.getInstance()
+ .getResourceProfile(file).findProblem(id);
if (problem == null)
- throw new IllegalArgumentException("Id is not registered");
+ throw new IllegalArgumentException("Id is not registered:" + id); //$NON-NLS-1$
if (problem.isEnabled() == false)
return; // skip
int severity = problem.getSeverity().intValue();
@@ -53,25 +54,31 @@ public class CodanMarkerProblemReporter implements IProblemReporter {
if (args != null && args.length > 0 && args[0] instanceof String)
message = (String) args[0];
} else {
- MessageFormat.format(messagePattern, args);
+ message = MessageFormat.format(messagePattern, args);
}
- reportProblem(id, severity, file, lineNumber, loc.getStartingChar(),
- loc.getEndingChar(), message);
+ reportProblem(id, problem.getMarkerType(), severity, file, lineNumber,
+ loc.getStartingChar(), loc.getEndingChar(), message);
}
- /*
- * (non-Javadoc)
- *
- * @see
- * org.eclipse.cdt.codan.core.model.IProblemReporter#reportProblem(java.
- * lang.String, org.eclipse.core.resources.IFile, int, java.lang.String)
+ /**
+ * @param id - problem id
+ * @param markerType - marker id
+ * @param severity - marker severity
+ * @param file - resource
+ * @param lineNumber - line number for error
+ * @param startChar - start char (offset in charts from the begging of the
+ * document)
+ * @param endChar - end char (offset in charts from the begging of the
+ * document, exclusive)
+ * @param message - marker message
*/
- public void reportProblem(String id, int severity, IFile file,
- int lineNumber, int startChar, int endChar, String message) {
+ public void reportProblem(String id, String markerType, int severity,
+ IResource file, int lineNumber, int startChar, int endChar,
+ String message) {
try {
// Do not put in duplicates
- IMarker[] cur = file.findMarkers(GENERIC_CODE_ANALYSIS_MARKER_TYPE,
- false, IResource.DEPTH_ZERO);
+ IMarker[] cur = file.findMarkers(markerType, false,
+ IResource.DEPTH_ZERO);
if (cur != null) {
for (IMarker element : cur) {
int line = ((Integer) element
@@ -86,37 +93,72 @@ public class CodanMarkerProblemReporter implements IProblemReporter {
}
}
}
- IMarker marker = file
- .createMarker(GENERIC_CODE_ANALYSIS_MARKER_TYPE);
+ IMarker marker = file.createMarker(markerType);
marker.setAttribute(IMarker.MESSAGE, message);
marker.setAttribute(IMarker.SEVERITY, severity);
marker.setAttribute(IMarker.LINE_NUMBER, lineNumber);
marker.setAttribute(IMarker.PROBLEM, id);
marker.setAttribute(IMarker.CHAR_END, endChar);
marker.setAttribute(IMarker.CHAR_START, startChar);
+ marker.setAttribute("org.eclipse.cdt.core.problem", 42); //$NON-NLS-1$
} catch (CoreException e) {
e.printStackTrace();
}
}
- public void deleteMarkers(IResource file) {
+ public void deleteProblems(IResource file) {
try {
- file.deleteMarkers(GENERIC_CODE_ANALYSIS_MARKER_TYPE, false,
+ file.deleteMarkers(GENERIC_CODE_ANALYSIS_MARKER_TYPE, true,
IResource.DEPTH_ZERO);
} catch (CoreException ce) {
ce.printStackTrace();
}
}
- public void deleteAllMarkers() {
+ public void deleteAllProblems() {
try {
- // TODO delete contributed markers too
- ResourcesPlugin.getWorkspace().getRoot().deleteMarkers(
- GENERIC_CODE_ANALYSIS_MARKER_TYPE, false,
- IResource.DEPTH_INFINITE);
+ ResourcesPlugin
+ .getWorkspace()
+ .getRoot()
+ .deleteMarkers(GENERIC_CODE_ANALYSIS_MARKER_TYPE, true,
+ IResource.DEPTH_INFINITE);
} catch (CoreException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ CodanCorePlugin.log(e);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.cdt.codan.core.model.IProblemReporterPersistent#deleteProblems
+ * (org.eclipse.core.resources.IResource,
+ * org.eclipse.cdt.codan.core.model.IChecker)
+ */
+ public void deleteProblems(final IResource file, final IChecker checker) {
+ try {
+ ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
+ public void run(IProgressMonitor monitor) throws CoreException {
+ IMarker[] markers = file.findMarkers(
+ GENERIC_CODE_ANALYSIS_MARKER_TYPE, true,
+ IResource.DEPTH_INFINITE);
+ ICheckersRegistry reg = CodanRuntime.getInstance()
+ .getChechersRegistry();
+ for (int i = 0; i < markers.length; i++) {
+ IMarker m = markers[i];
+ String id = m.getAttribute(IMarker.PROBLEM, ""); //$NON-NLS-1$
+ Collection<IProblem> problems = reg.getRefProblems(checker);
+ for (Iterator<IProblem> iterator = problems.iterator(); iterator
+ .hasNext();) {
+ IProblem iProblem = iterator.next();
+ if (iProblem.getId().equals(id))
+ m.delete();
+ }
+ }
+ }
+ }, null, IWorkspace.AVOID_UPDATE, null);
+ } catch (CoreException e) {
+ CodanCorePlugin.log(e);
}
}
}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblem.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblem.java
index a094cc1..56b43c5 100644
--- a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblem.java
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblem.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,20 +10,21 @@
*******************************************************************************/
package org.eclipse.cdt.codan.internal.core.model;
-import java.util.Collection;
-import java.util.HashMap;
-
import org.eclipse.cdt.codan.core.model.CodanSeverity;
-import org.eclipse.cdt.codan.core.model.IProblem;
-import org.eclipse.cdt.codan.core.model.IProblemCategory;
+import org.eclipse.cdt.codan.core.model.IProblemReporter;
+import org.eclipse.cdt.codan.core.model.IProblemWorkingCopy;
+import org.eclipse.cdt.codan.core.param.IProblemPreference;
-public class CodanProblem implements IProblem {
+public class CodanProblem implements IProblemWorkingCopy {
private String id;
private String name;
private String message;
private CodanSeverity severity = CodanSeverity.Warning;
private boolean enabled = true;
- private HashMap<Object, Object> properties = new HashMap<Object, Object>(0);
+ private IProblemPreference preference;
+ private boolean frozen;
+ private String description;
+ private String markerType = IProblemReporter.GENERIC_CODE_ANALYSIS_MARKER_TYPE;
public CodanSeverity getSeverity() {
return severity;
@@ -32,6 +33,7 @@ public class CodanProblem implements IProblem {
public CodanProblem(String problemId, String name) {
this.id = problemId;
this.name = name;
+ this.frozen = false;
}
public String getName() {
@@ -42,11 +44,6 @@ public class CodanProblem implements IProblem {
return id;
}
- public IProblemCategory getCategory() {
- // TODO Auto-generated method stub
- return null;
- }
-
@Override
public String toString() {
return name;
@@ -73,19 +70,19 @@ public class CodanProblem implements IProblem {
*/
@Override
public Object clone() throws CloneNotSupportedException {
- return super.clone();
+ CodanProblem prob = (CodanProblem) super.clone();
+ if (preference != null) {
+ prob.preference = (IProblemPreference) preference.clone();
+ }
+ return prob;
}
- public void setProperty(Object key, Object value) {
- properties.put(key, value);
+ public void setPreference(IProblemPreference value) {
+ preference = value;
}
- public Object getProperty(Object key) {
- return properties.get(key);
- };
-
- public Collection<Object> getPropertyKeys() {
- return properties.keySet();
+ public IProblemPreference getPreference() {
+ return preference;
}
/*
@@ -97,10 +94,54 @@ public class CodanProblem implements IProblem {
return message;
}
+ protected void freeze() {
+ frozen = true;
+ }
+
/**
- * @param message the message to set
+ * @param message
+ * the message to set
*/
public void setMessagePattern(String message) {
+ checkSet();
this.message = message;
}
+
+ protected void checkSet() {
+ if (frozen)
+ throw new IllegalStateException("Object is unmodifieble"); //$NON-NLS-1$
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.cdt.codan.core.model.IProblem#getDescription()
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.cdt.codan.core.model.IProblemWorkingCopy#setDescription(java
+ * .lang.String)
+ */
+ public void setDescription(String desc) {
+ this.description = desc;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.cdt.codan.core.model.IProblem#getMarkerType()
+ */
+ public String getMarkerType() {
+ return markerType;
+ }
+
+ public void setMarkerType(String type) {
+ markerType = type;
+ }
}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblemCategory.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblemCategory.java
index fc63480..0156211 100644
--- a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblemCategory.java
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblemCategory.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
@@ -41,40 +41,36 @@ public class CodanProblemCategory implements IProblemCategory, Cloneable {
}
public IProblemElement[] getChildren() {
- return (IProblemElement[]) list.toArray(new IProblemElement[list.size()]);
+ return list.toArray(new IProblemElement[list.size()]);
}
public void addChild(IProblemElement p) {
list.add(p);
}
- public IProblem findProblem(String id) {
- Object[] children = this.getChildren();
+ public static IProblem findProblem(IProblemCategory c, String id) {
+ Object[] children = c.getChildren();
for (Object object : children) {
if (object instanceof IProblemCategory) {
IProblemCategory cat = (IProblemCategory) object;
- IProblem found = cat.findProblem(id);
- if (found != null)
- return found;
+ IProblem found = findProblem(cat, id);
+ if (found != null) return found;
} else if (object instanceof IProblem) {
IProblem p = (IProblem) object;
- if (p.getId().equals(id))
- return p;
+ if (p.getId().equals(id)) return p;
}
}
return null;
}
- public IProblemCategory findCategory(String id) {
- if (getId().equals(id))
- return this;
- Object[] children = getChildren();
+ public static IProblemCategory findCategory(IProblemCategory cat, String id) {
+ if (cat.getId().equals(id)) return cat;
+ Object[] children = cat.getChildren();
for (Object object : children) {
if (object instanceof IProblemCategory) {
- IProblemCategory cat = (IProblemCategory) object;
- IProblemCategory found = cat.findCategory(id);
- if (found != null)
- return found;
+ IProblemCategory cat2 = (IProblemCategory) object;
+ IProblemCategory found = findCategory(cat2, id);
+ if (found != null) return found;
}
}
return null;
@@ -90,8 +86,7 @@ public class CodanProblemCategory implements IProblemCategory, Cloneable {
try {
CodanProblemCategory clone = (CodanProblemCategory) super.clone();
clone.list = new ArrayList<IProblemElement>();
- for (Iterator<IProblemElement> iterator = this.list.iterator(); iterator
- .hasNext();) {
+ for (Iterator<IProblemElement> iterator = this.list.iterator(); iterator.hasNext();) {
IProblemElement child = iterator.next();
clone.list.add((IProblemElement) child.clone());
}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblemLocation.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblemLocation.java
new file mode 100644
index 0000000..ca6bd02
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/CodanProblemLocation.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * 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.internal.core.model;
+
+import org.eclipse.cdt.codan.core.model.AbstractProblemLocation;
+import org.eclipse.core.resources.IFile;
+
+/**
+ * Codan Problem Location, so far same as abstract class
+ *
+ */
+public class CodanProblemLocation extends AbstractProblemLocation {
+ public CodanProblemLocation(IFile file, int startChar, int endChar) {
+ super(file, startChar, endChar);
+ }
+
+ public CodanProblemLocation(IFile file, int startChar, int endChar, int line) {
+ super(file, startChar, endChar);
+ this.line = line;
+ }
+
+ protected CodanProblemLocation(IFile file, int line) {
+ super(file, line);
+ }
+}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/ProblemLocationFactory.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/ProblemLocationFactory.java
new file mode 100644
index 0000000..835f6bf
--- /dev/null
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/ProblemLocationFactory.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * 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.internal.core.model;
+
+import org.eclipse.cdt.codan.core.model.IProblemLocation;
+import org.eclipse.cdt.codan.core.model.IProblemLocationFactory;
+import org.eclipse.core.resources.IFile;
+
+/**
+ * Factory class that allows to create problem locations
+ *
+ */
+public class ProblemLocationFactory implements IProblemLocationFactory {
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.cdt.codan.core.model.IProblemLocationFactory#
+ * createProblemLocation(org.eclipse.core.resources.IFile, int)
+ */
+ public IProblemLocation createProblemLocation(IFile file, int line) {
+ return new CodanProblemLocation(file, line);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.cdt.codan.core.model.IProblemLocationFactory#
+ * createProblemLocation(org.eclipse.core.resources.IFile, int, int)
+ */
+ public IProblemLocation createProblemLocation(IFile file, int startChar,
+ int endChar) {
+ return new CodanProblemLocation(file, startChar, endChar);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.cdt.codan.core.model.IProblemLocationFactory#
+ * createProblemLocation(org.eclipse.core.resources.IFile, int, int, int)
+ */
+ public IProblemLocation createProblemLocation(IFile file, int startChar,
+ int endChar, int line) {
+ return new CodanProblemLocation(file, startChar, endChar, line);
+ }
+}
diff --git a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/ProblemProfile.java b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/ProblemProfile.java
index d2330f1..1eb045b 100644
--- a/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/ProblemProfile.java
+++ b/org.eclipse.cdt.codan.core/src/org/eclipse/cdt/codan/internal/core/model/ProblemProfile.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
@@ -22,8 +22,7 @@ import org.eclipse.cdt.codan.core.model.IProblemProfile;
*
*/
public class ProblemProfile implements IProblemProfile, Cloneable {
- private IProblemCategory rootCategory = new CodanProblemCategory("root",
- "root");
+ private IProblemCategory rootCategory = new CodanProblemCategory("root", "root"); //$NON-NLS-1$ //$NON-NLS-2$
/*
* (non-Javadoc)
@@ -33,7 +32,7 @@ public class ProblemProfile implements IProblemProfile, Cloneable {
* .String)
*/
public IProblem findProblem(String id) {
- return getRoot().findProblem(id);
+ return CodanProblemCategory.findProblem(getRoot(), id);
}
/*
@@ -51,8 +50,7 @@ public class ProblemProfile implements IProblemProfile, Cloneable {
* @param root
* @param problems
*/
- protected void collectProblems(IProblemCategory parent,
- Collection<IProblem> problems) {
+ protected void collectProblems(IProblemCategory parent, Collection<IProblem> problems) {
Object[] children = parent.getChildren();
for (Object object : children) {
if (object instanceof IProblemCategory) {
@@ -69,13 +67,12 @@ public class ProblemProfile implements IProblemProfile, Cloneable {
}
public void addProblem(IProblem p, IProblemCategory cat) {
- if (cat == null)
- cat = getRoot();
+ if (cat == null) cat = getRoot();
((CodanProblemCategory) cat).addChild(p);
}
public IProblemCategory findCategory(String id) {
- return getRoot().findCategory(id);
+ return CodanProblemCategory.findCategory(getRoot(), id);
}
/*
@@ -87,8 +84,7 @@ public class ProblemProfile implements IProblemProfile, Cloneable {
public Object clone() {
try {
ProblemProfile clone = (ProblemProfile) super.clone();
- clone.rootCategory = (IProblemCategory) ((CodanProblemCategory) this.rootCategory)
- .clone();
+ clone.rootCategory = (IProblemCategory) ((CodanProblemCategory) this.rootCategory).clone();
return clone;
} catch (CloneNotSupportedException e) {
return this;