diff options
Diffstat (limited to 'sonar-duplications')
44 files changed, 5415 insertions, 0 deletions
diff --git a/sonar-duplications/pom.xml b/sonar-duplications/pom.xml new file mode 100644 index 00000000000..9b0554bc921 --- /dev/null +++ b/sonar-duplications/pom.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.codehaus.sonar</groupId> + <artifactId>sonar</artifactId> + <version>2.3-SNAPSHOT</version> + </parent> + <artifactId>sonar-duplications</artifactId> + <name>Sonar :: Duplications</name> + <description>Detect duplicated code</description> + + <dependencies> + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>pmd</groupId> + <artifactId>pmd</artifactId> + <version>4.2.5</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>hamcrest-all</artifactId> + <scope>test</scope> + </dependency> + </dependencies> +</project>
\ No newline at end of file diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/AbstractLanguage.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/AbstractLanguage.java new file mode 100644 index 00000000000..b10585d5f97 --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/AbstractLanguage.java @@ -0,0 +1,23 @@ +package net.sourceforge.pmd.cpd;
+
+import net.sourceforge.pmd.util.filter.Filters;
+
+import java.io.FilenameFilter;
+
+public abstract class AbstractLanguage implements Language {
+ private final Tokenizer tokenizer;
+ private final FilenameFilter fileFilter;
+
+ public AbstractLanguage(Tokenizer tokenizer, String... extensions) {
+ this.tokenizer = tokenizer;
+ fileFilter = net.sourceforge.pmd.util.filter.Filters.toFilenameFilter(Filters.getFileExtensionOrDirectoryFilter(extensions));
+ }
+
+ public FilenameFilter getFileFilter() {
+ return fileFilter;
+ }
+
+ public Tokenizer getTokenizer() {
+ return tokenizer;
+ }
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/AbstractTokenizer.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/AbstractTokenizer.java new file mode 100644 index 00000000000..be76b12b139 --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/AbstractTokenizer.java @@ -0,0 +1,136 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + * @author Zev Blut zb@ubit.com + * @author Romain PELISSE belaran@gmail.com + */ +package net.sourceforge.pmd.cpd; + +import java.util.List; + +public abstract class AbstractTokenizer implements Tokenizer +{ + + protected List<String> stringToken; // List<String>, should be setted by children classes + protected List<String> ignorableCharacter; // List<String>, should be setted by children classes + // FIXME:Maybe an array of 'char' would be better for perfomance ? + protected List<String> ignorableStmt; // List<String>, should be setted by children classes + protected char ONE_LINE_COMMENT_CHAR = '#'; // Most script language ( shell, ruby, python,...) use this symbol for comment line + + private List<String> code; + private int lineNumber = 0; + private String currentLine; + + protected boolean spanMultipleLinesString = true; // Most language does, so default is true + + private boolean downcaseString = true; + + public void tokenize(SourceCode tokens, Tokens tokenEntries) { + this.code = tokens.getCode(); + + for ( this.lineNumber = 0; lineNumber < this.code.size(); lineNumber++ ) { + this.currentLine = this.code.get(this.lineNumber); + int loc = 0; + while ( loc < currentLine.length() ) { + StringBuffer token = new StringBuffer(); + loc = getTokenFromLine(token,loc); + if (token.length() > 0 && !isIgnorableString(token.toString())) { + if (downcaseString) { + token = new StringBuffer(token.toString().toLowerCase()); + } + } + } + } + tokenEntries.add(TokenEntry.getEOF()); + } + + private int getTokenFromLine(StringBuffer token, int loc) { + for (int j = loc; j < this.currentLine.length(); j++) { + char tok = this.currentLine.charAt(j); + if (!Character.isWhitespace(tok) && !ignoreCharacter(tok)) { + if (isComment(tok)) { + if (token.length() > 0) { + return j; + } else { + return getCommentToken(token, loc); + } + } else if (isString(tok)) { + if (token.length() > 0) { + return j; // we need to now parse the string as a seperate token. + } else { + // we are at the start of a string + return parseString(token, j, tok); + } + } else { + token.append(tok); + } + } else { + if (token.length() > 0) { + return j; + } + } + loc = j; + } + return loc + 1; + } + + private int parseString(StringBuffer token, int loc, char stringDelimiter) { + boolean escaped = false; + boolean done = false; + char tok = ' '; // this will be replaced. + while ((loc < currentLine.length()) && ! done) { + tok = currentLine.charAt(loc); + if (escaped && tok == stringDelimiter) // Found an escaped string + escaped = false; + else if (tok == stringDelimiter && (token.length() > 0)) // We are done, we found the end of the string... + done = true; + else if (tok == '\\') // Found an escaped char + escaped = true; + else // Adding char... + escaped = false; + //Adding char to String:" + token.toString()); + token.append(tok); + loc++; + } + // Handling multiple lines string + if ( ! done && // ... we didn't find the end of the string + loc >= currentLine.length() && // ... we have reach the end of the line ( the String is incomplete, for the moment at least) + this.spanMultipleLinesString && // ... the language allow multiple line span Strings + ++this.lineNumber < this.code.size() // ... there is still more lines to parse + ) { + // parsing new line + this.currentLine = this.code.get(this.lineNumber); + // Warning : recursive call ! + loc = this.parseString(token, loc, stringDelimiter); + } + return loc + 1; + } + + private boolean ignoreCharacter(char tok) + { + return this.ignorableCharacter.contains("" + tok); + } + + private boolean isString(char tok) + { + return this.stringToken.contains("" + tok); + } + + private boolean isComment(char tok) + { + return tok == ONE_LINE_COMMENT_CHAR; + } + + private int getCommentToken(StringBuffer token, int loc) + { + while (loc < this.currentLine.length()) + { + token.append(this.currentLine.charAt(loc++)); + } + return loc; + } + + private boolean isIgnorableString(String token) + { + return this.ignorableStmt.contains(token); + } +} diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/AnyLanguage.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/AnyLanguage.java new file mode 100644 index 00000000000..2bf3f913f3d --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/AnyLanguage.java @@ -0,0 +1,10 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ +package net.sourceforge.pmd.cpd; + +public class AnyLanguage extends AbstractLanguage { + public AnyLanguage(String extension) { + super(new AnyTokenizer(), extension); + } +} diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/AnyTokenizer.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/AnyTokenizer.java new file mode 100644 index 00000000000..cd2bd17ade8 --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/AnyTokenizer.java @@ -0,0 +1,52 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ +package net.sourceforge.pmd.cpd; + +import java.io.BufferedReader; +import java.io.CharArrayReader; +import java.util.NoSuchElementException; +import java.util.StringTokenizer; + +/** + * This class does a best-guess try-anything tokenization. + * + * @author jheintz + */ +public class AnyTokenizer implements Tokenizer { + public static final String TOKENS = " \t!#$%^&*(){}-=+<>/\\`~;:"; + + public void tokenize(SourceCode sourceCode, Tokens tokenEntries) { + StringBuffer sb = sourceCode.getCodeBuffer(); + BufferedReader reader = new BufferedReader(new CharArrayReader(sb.toString().toCharArray())); + try { + int lineNumber = 1; + String line = reader.readLine(); + while (line != null) { + StringTokenizer tokenizer = new StringTokenizer(line, TOKENS, true); + try { + String token = tokenizer.nextToken(); + while (token != null) { + if (!token.equals(" ") && !token.equals("\t")) { + tokenEntries.add(new TokenEntry(token, sourceCode.getFileName(), lineNumber)); + } + token = tokenizer.nextToken(); + } + } catch (NoSuchElementException ex) { + // done with tokens + } + // advance iteration variables + line = reader.readLine(); + lineNumber++; + } + } catch (Exception ex) { + ex.printStackTrace(); + } finally { + try { + reader.close(); + } catch (Exception ex) { + } + tokenEntries.add(TokenEntry.getEOF()); + } + } +} diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/CPDListener.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/CPDListener.java new file mode 100644 index 00000000000..a675007718b --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/CPDListener.java @@ -0,0 +1,19 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ +package net.sourceforge.pmd.cpd; + +import java.io.File; + +public interface CPDListener { + + public static final int INIT = 0; + public static final int HASH = 1; + public static final int MATCH = 2; + public static final int GROUPING = 3; + public static final int DONE = 4; + + void addedFile(int fileCount, File file); + + void phaseUpdate(int phase); +} diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/CPDNullListener.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/CPDNullListener.java new file mode 100644 index 00000000000..8a8a1e6ddc0 --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/CPDNullListener.java @@ -0,0 +1,14 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ +package net.sourceforge.pmd.cpd; + +import java.io.File; + +public class CPDNullListener implements CPDListener { + public void addedFile(int fileCount, File file) { + } + + public void phaseUpdate(int phase) { + } +} diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/FileFinder.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/FileFinder.java new file mode 100644 index 00000000000..587c9d8aca1 --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/FileFinder.java @@ -0,0 +1,10 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ +package net.sourceforge.pmd.cpd; + +/** + * @deprecated Use net.sourceforge.pmd.util.FileFinder instead. + */ +public class FileFinder extends net.sourceforge.pmd.util.FileFinder { +} diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/FileReporter.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/FileReporter.java new file mode 100644 index 00000000000..a4fff9ea0aa --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/FileReporter.java @@ -0,0 +1,47 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ +package net.sourceforge.pmd.cpd; + +import java.io.*; + +/** + * @author Philippe T'Seyen + */ +public class FileReporter { + private File reportFile; + private String encoding; + + public FileReporter(String encoding) { + this(null, encoding); + } + + public FileReporter(File reportFile) { + this(reportFile, System.getProperty("file.encoding")); + } + + public FileReporter(File reportFile, String encoding) { + this.reportFile = reportFile; + this.encoding = encoding; + } + + public void report(String content) throws ReportException { + try { + Writer writer = null; + try { + OutputStream outputStream; + if (reportFile == null) { + outputStream = System.out; + } else { + outputStream = new FileOutputStream(reportFile); + } + writer = new BufferedWriter(new OutputStreamWriter(outputStream, encoding)); + writer.write(content); + } finally { + if (writer != null) writer.close(); + } + } catch (IOException ioe) { + throw new ReportException(ioe); + } + } +} diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/Language.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/Language.java new file mode 100644 index 00000000000..dc861835a49 --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/Language.java @@ -0,0 +1,15 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ +package net.sourceforge.pmd.cpd; + +import java.io.FilenameFilter; + +public interface Language { + + String fileSeparator = System.getProperty("file.separator"); + + public Tokenizer getTokenizer(); + + public FilenameFilter getFileFilter(); +} diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/ReportException.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/ReportException.java new file mode 100644 index 00000000000..680da398bf6 --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/ReportException.java @@ -0,0 +1,14 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ +package net.sourceforge.pmd.cpd; + +/** + * @author Philippe T'Seyen + */ +public class ReportException extends Exception { + + public ReportException(Throwable cause) { + super(); + } +} diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/SourceCode.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/SourceCode.java new file mode 100644 index 00000000000..1c79e203561 --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/SourceCode.java @@ -0,0 +1,136 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ +package net.sourceforge.pmd.cpd; + +import java.io.*; +import java.lang.ref.SoftReference; +import java.util.ArrayList; +import java.util.List; + +public class SourceCode { + + public static final String EOL = System.getProperty("line.separator", "\n"); + + public static abstract class CodeLoader { + private SoftReference<List<String>> code; + + public List<String> getCode() { + List<String> c = null; + if (code != null) { + c = code.get(); + } + if (c != null) { + return c; + } + this.code = new SoftReference<List<String>>(load()); + return code.get(); + } + + public abstract String getFileName(); + + protected abstract Reader getReader() throws Exception; + + protected List<String> load() { + LineNumberReader lnr = null; + try { + lnr = new LineNumberReader(getReader()); + List<String> lines = new ArrayList<String>(); + String currentLine; + while ((currentLine = lnr.readLine()) != null) { + lines.add(currentLine); + } + return lines; + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("Problem while reading " + getFileName() + ":" + e.getMessage()); + } finally { + try { + if (lnr != null) + lnr.close(); + } catch (Exception e) { + throw new RuntimeException("Problem while reading " + getFileName() + ":" + e.getMessage()); + } + } + } + } + + public static class FileCodeLoader extends CodeLoader { + private File file; + private String encoding; + + public FileCodeLoader(File file, String encoding) { + this.file = file; + this.encoding = encoding; + } + + public Reader getReader() throws Exception { + return new InputStreamReader(new FileInputStream(file), encoding); + } + + public String getFileName() { + return this.file.getAbsolutePath(); + } + } + + public static class StringCodeLoader extends CodeLoader { + public static final String DEFAULT_NAME = "CODE_LOADED_FROM_STRING"; + + private String source_code; + + private String name; + + public StringCodeLoader(String code) { + this(code, DEFAULT_NAME); + } + + public StringCodeLoader(String code, String name) { + this.source_code = code; + this.name = name; + } + + public Reader getReader() { + return new StringReader(source_code); + } + + public String getFileName() { + return name; + } + } + + private CodeLoader cl; + + public SourceCode(CodeLoader cl) { + this.cl = cl; + } + + public List<String> getCode() { + return cl.getCode(); + } + + public StringBuffer getCodeBuffer() { + StringBuffer sb = new StringBuffer(); + List<String> lines = cl.getCode(); + for ( String line : lines ) { + sb.append(line); + sb.append(EOL); + } + return sb; + } + + public String getSlice(int startLine, int endLine) { + StringBuffer sb = new StringBuffer(); + List lines = cl.getCode(); + for (int i = (startLine == 0 ? startLine :startLine - 1); i < endLine && i < lines.size(); i++) { + if (sb.length() != 0) { + sb.append(EOL); + } + sb.append((String) lines.get(i)); + } + return sb.toString(); + } + + public String getFileName() { + return cl.getFileName(); + } +} diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/TokenEntry.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/TokenEntry.java new file mode 100644 index 00000000000..07092e78423 --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/TokenEntry.java @@ -0,0 +1,84 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ +package net.sourceforge.pmd.cpd; + +import java.util.HashMap; +import java.util.Map; + +public class TokenEntry implements Comparable<TokenEntry> { + + public static final TokenEntry EOF = new TokenEntry(); + + private String tokenSrcID; + private int beginLine; + private int index; + private int identifier; + private int hashCode; + + private final static Map<String, Integer> Tokens = new HashMap<String, Integer>(); + private static int TokenCount = 0; + + private TokenEntry() { + this.identifier = 0; + this.tokenSrcID = "EOFMarker"; + } + + public TokenEntry(String image, String tokenSrcID, int beginLine) { + Integer i = Tokens.get(image); + if (i == null) { + i = Tokens.size() + 1; + Tokens.put(image, i); + } + this.identifier = i.intValue(); + this.tokenSrcID = tokenSrcID; + this.beginLine = beginLine; + this.index = TokenCount++; + } + + public static TokenEntry getEOF() { + TokenCount++; + return EOF; + } + + public static void clearImages() { + Tokens.clear(); + TokenCount = 0; + } + + public String getTokenSrcID() { + return tokenSrcID; + } + + public int getBeginLine() { + return beginLine; + } + + public int getIdentifier() { + return this.identifier; + } + + public int getIndex() { + return this.index; + } + + public int hashCode() { + return hashCode; + } + + public void setHashCode(int hashCode) { + this.hashCode = hashCode; + } + + public boolean equals(Object o) { + if (!(o instanceof TokenEntry)) { + return false; + } + TokenEntry other = (TokenEntry) o; + return other.hashCode == hashCode; + } + + public int compareTo(TokenEntry other) { + return getIndex() - other.getIndex(); + } +}
\ No newline at end of file diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/Tokenizer.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/Tokenizer.java new file mode 100644 index 00000000000..f95c312d496 --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/Tokenizer.java @@ -0,0 +1,10 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ +package net.sourceforge.pmd.cpd; + +import java.io.IOException; + +public interface Tokenizer { + void tokenize(SourceCode tokens, Tokens tokenEntries) throws IOException; +} diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/Tokens.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/Tokens.java new file mode 100644 index 00000000000..c90cf526551 --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/Tokens.java @@ -0,0 +1,44 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ +package net.sourceforge.pmd.cpd; + +import org.sonar.duplications.cpd.Match; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class Tokens { + + private List<TokenEntry> tokens = new ArrayList<TokenEntry>(); + + public void add(TokenEntry tokenEntry) { + this.tokens.add(tokenEntry); + } + + public Iterator<TokenEntry> iterator() { + return tokens.iterator(); + } + + private TokenEntry get(int index) { + return tokens.get(index); + } + + public int size() { + return tokens.size(); + } + + public int getLineCount(TokenEntry mark, Match match) { + TokenEntry endTok = get(mark.getIndex() + match.getTokenCount() - 1); + if (endTok == TokenEntry.EOF) { + endTok = get(mark.getIndex() + match.getTokenCount() - 2); + } + return endTok.getBeginLine() - mark.getBeginLine() + 1; + } + + public List<TokenEntry> getTokens() { + return tokens; + } + +} diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/CPPParserConstants.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/CPPParserConstants.java new file mode 100644 index 00000000000..79b06785b69 --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/CPPParserConstants.java @@ -0,0 +1,397 @@ +/* Generated By:JavaCC: Do not edit this line. CPPParserConstants.java */ +package net.sourceforge.pmd.cpd.cppast; + + +/** + * Token literal values and constants. + * Generated by org.javacc.parser.OtherFilesGen#start() + */ +public interface CPPParserConstants { + + /** End of File. */ + int EOF = 0; + /** RegularExpression Id. */ + int LCURLYBRACE = 19; + /** RegularExpression Id. */ + int RCURLYBRACE = 20; + /** RegularExpression Id. */ + int LSQUAREBRACKET = 21; + /** RegularExpression Id. */ + int RSQUAREBRACKET = 22; + /** RegularExpression Id. */ + int LPARENTHESIS = 23; + /** RegularExpression Id. */ + int RPARENTHESIS = 24; + /** RegularExpression Id. */ + int SCOPE = 25; + /** RegularExpression Id. */ + int COLON = 26; + /** RegularExpression Id. */ + int SEMICOLON = 27; + /** RegularExpression Id. */ + int COMMA = 28; + /** RegularExpression Id. */ + int QUESTIONMARK = 29; + /** RegularExpression Id. */ + int ELLIPSIS = 30; + /** RegularExpression Id. */ + int ASSIGNEQUAL = 31; + /** RegularExpression Id. */ + int TIMESEQUAL = 32; + /** RegularExpression Id. */ + int DIVIDEEQUAL = 33; + /** RegularExpression Id. */ + int MODEQUAL = 34; + /** RegularExpression Id. */ + int PLUSEQUAL = 35; + /** RegularExpression Id. */ + int MINUSEQUAL = 36; + /** RegularExpression Id. */ + int SHIFTLEFTEQUAL = 37; + /** RegularExpression Id. */ + int SHIFTRIGHTEQUAL = 38; + /** RegularExpression Id. */ + int BITWISEANDEQUAL = 39; + /** RegularExpression Id. */ + int BITWISEXOREQUAL = 40; + /** RegularExpression Id. */ + int BITWISEOREQUAL = 41; + /** RegularExpression Id. */ + int OR = 42; + /** RegularExpression Id. */ + int AND = 43; + /** RegularExpression Id. */ + int BITWISEOR = 44; + /** RegularExpression Id. */ + int BITWISEXOR = 45; + /** RegularExpression Id. */ + int AMPERSAND = 46; + /** RegularExpression Id. */ + int EQUAL = 47; + /** RegularExpression Id. */ + int NOTEQUAL = 48; + /** RegularExpression Id. */ + int LESSTHAN = 49; + /** RegularExpression Id. */ + int GREATERTHAN = 50; + /** RegularExpression Id. */ + int LESSTHANOREQUALTO = 51; + /** RegularExpression Id. */ + int GREATERTHANOREQUALTO = 52; + /** RegularExpression Id. */ + int SHIFTLEFT = 53; + /** RegularExpression Id. */ + int SHIFTRIGHT = 54; + /** RegularExpression Id. */ + int PLUS = 55; + /** RegularExpression Id. */ + int MINUS = 56; + /** RegularExpression Id. */ + int STAR = 57; + /** RegularExpression Id. */ + int DIVIDE = 58; + /** RegularExpression Id. */ + int MOD = 59; + /** RegularExpression Id. */ + int PLUSPLUS = 60; + /** RegularExpression Id. */ + int MINUSMINUS = 61; + /** RegularExpression Id. */ + int TILDE = 62; + /** RegularExpression Id. */ + int NOT = 63; + /** RegularExpression Id. */ + int DOT = 64; + /** RegularExpression Id. */ + int POINTERTO = 65; + /** RegularExpression Id. */ + int DOTSTAR = 66; + /** RegularExpression Id. */ + int ARROWSTAR = 67; + /** RegularExpression Id. */ + int AUTO = 68; + /** RegularExpression Id. */ + int BREAK = 69; + /** RegularExpression Id. */ + int CASE = 70; + /** RegularExpression Id. */ + int CATCH = 71; + /** RegularExpression Id. */ + int CHAR = 72; + /** RegularExpression Id. */ + int CONST = 73; + /** RegularExpression Id. */ + int CONTINUE = 74; + /** RegularExpression Id. */ + int _DEFAULT = 75; + /** RegularExpression Id. */ + int DELETE = 76; + /** RegularExpression Id. */ + int DO = 77; + /** RegularExpression Id. */ + int DOUBLE = 78; + /** RegularExpression Id. */ + int ELSE = 79; + /** RegularExpression Id. */ + int ENUM = 80; + /** RegularExpression Id. */ + int EXTERN = 81; + /** RegularExpression Id. */ + int FLOAT = 82; + /** RegularExpression Id. */ + int FOR = 83; + /** RegularExpression Id. */ + int FRIEND = 84; + /** RegularExpression Id. */ + int GOTO = 85; + /** RegularExpression Id. */ + int IF = 86; + /** RegularExpression Id. */ + int INLINE = 87; + /** RegularExpression Id. */ + int INT = 88; + /** RegularExpression Id. */ + int LONG = 89; + /** RegularExpression Id. */ + int NEW = 90; + /** RegularExpression Id. */ + int PRIVATE = 91; + /** RegularExpression Id. */ + int PROTECTED = 92; + /** RegularExpression Id. */ + int PUBLIC = 93; + /** RegularExpression Id. */ + int REDECLARED = 94; + /** RegularExpression Id. */ + int REGISTER = 95; + /** RegularExpression Id. */ + int RETURN = 96; + /** RegularExpression Id. */ + int SHORT = 97; + /** RegularExpression Id. */ + int SIGNED = 98; + /** RegularExpression Id. */ + int SIZEOF = 99; + /** RegularExpression Id. */ + int STATIC = 100; + /** RegularExpression Id. */ + int STRUCT = 101; + /** RegularExpression Id. */ + int CLASS = 102; + /** RegularExpression Id. */ + int SWITCH = 103; + /** RegularExpression Id. */ + int TEMPLATE = 104; + /** RegularExpression Id. */ + int THIS = 105; + /** RegularExpression Id. */ + int TRY = 106; + /** RegularExpression Id. */ + int TYPEDEF = 107; + /** RegularExpression Id. */ + int UNION = 108; + /** RegularExpression Id. */ + int UNSIGNED = 109; + /** RegularExpression Id. */ + int VIRTUAL = 110; + /** RegularExpression Id. */ + int VOID = 111; + /** RegularExpression Id. */ + int VOLATILE = 112; + /** RegularExpression Id. */ + int WHILE = 113; + /** RegularExpression Id. */ + int OPERATOR = 114; + /** RegularExpression Id. */ + int TRUETOK = 115; + /** RegularExpression Id. */ + int FALSETOK = 116; + /** RegularExpression Id. */ + int THROW = 117; + /** RegularExpression Id. */ + int OCTALINT = 118; + /** RegularExpression Id. */ + int OCTALLONG = 119; + /** RegularExpression Id. */ + int UNSIGNED_OCTALINT = 120; + /** RegularExpression Id. */ + int UNSIGNED_OCTALLONG = 121; + /** RegularExpression Id. */ + int DECIMALINT = 122; + /** RegularExpression Id. */ + int DECIMALLONG = 123; + /** RegularExpression Id. */ + int UNSIGNED_DECIMALINT = 124; + /** RegularExpression Id. */ + int UNSIGNED_DECIMALLONG = 125; + /** RegularExpression Id. */ + int HEXADECIMALINT = 126; + /** RegularExpression Id. */ + int HEXADECIMALLONG = 127; + /** RegularExpression Id. */ + int UNSIGNED_HEXADECIMALINT = 128; + /** RegularExpression Id. */ + int UNSIGNED_HEXADECIMALLONG = 129; + /** RegularExpression Id. */ + int FLOATONE = 130; + /** RegularExpression Id. */ + int FLOATTWO = 131; + /** RegularExpression Id. */ + int CHARACTER = 132; + /** RegularExpression Id. */ + int STRING = 133; + /** RegularExpression Id. */ + int ID = 135; + + /** Lexical state. */ + int DEFAULT = 0; + /** Lexical state. */ + int IN_LINE_COMMENT = 1; + /** Lexical state. */ + int IN_COMMENT = 2; + /** Lexical state. */ + int IN_PREPROCESSOR_OUTPUT_COMMENT = 3; + /** Lexical state. */ + int PREPROCESSOR_OUTPUT = 4; + + /** Literal token values. */ + String[] tokenImage = { + "<EOF>", + "\" \"", + "\"\\f\"", + "\"\\t\"", + "\"\\r\\n\"", + "\"\\n\"", + "\"//\"", + "\"/*\"", + "\"#\"", + "\"\\n\"", + "<token of kind 10>", + "\"*/\"", + "<token of kind 12>", + "\"*/\"", + "\"\\n\"", + "\"/*\"", + "\"\\\\\\n\"", + "\"\\\\\\r\\n\"", + "<token of kind 18>", + "\"{\"", + "\"}\"", + "\"[\"", + "\"]\"", + "\"(\"", + "\")\"", + "\"::\"", + "\":\"", + "\";\"", + "\",\"", + "\"?\"", + "\"...\"", + "\"=\"", + "\"*=\"", + "\"/=\"", + "\"%=\"", + "\"+=\"", + "\"-=\"", + "\"<<=\"", + "\">>=\"", + "\"&=\"", + "\"^=\"", + "\"|=\"", + "\"||\"", + "\"&&\"", + "\"|\"", + "\"^\"", + "\"&\"", + "\"==\"", + "\"!=\"", + "\"<\"", + "\">\"", + "\"<=\"", + "\">=\"", + "\"<<\"", + "\">>\"", + "\"+\"", + "\"-\"", + "\"*\"", + "\"/\"", + "\"%\"", + "\"++\"", + "\"--\"", + "\"~\"", + "\"!\"", + "\".\"", + "\"->\"", + "\".*\"", + "\"->*\"", + "\"auto\"", + "\"break\"", + "\"case\"", + "\"catch\"", + "\"char\"", + "\"const\"", + "\"continue\"", + "\"default\"", + "\"delete\"", + "\"do\"", + "\"double\"", + "\"else\"", + "\"enum\"", + "\"extern\"", + "\"float\"", + "\"for\"", + "\"friend\"", + "\"goto\"", + "\"if\"", + "\"inline\"", + "\"int\"", + "\"long\"", + "\"new\"", + "\"private\"", + "\"protected\"", + "\"public\"", + "\"redeclared\"", + "\"register\"", + "\"return\"", + "\"short\"", + "\"signed\"", + "\"sizeof\"", + "\"static\"", + "\"struct\"", + "\"class\"", + "\"switch\"", + "\"template\"", + "\"this\"", + "\"try\"", + "\"typedef\"", + "\"union\"", + "\"unsigned\"", + "\"virtual\"", + "\"void\"", + "\"volatile\"", + "\"while\"", + "\"operator\"", + "\"true\"", + "\"false\"", + "\"throw\"", + "<OCTALINT>", + "<OCTALLONG>", + "<UNSIGNED_OCTALINT>", + "<UNSIGNED_OCTALLONG>", + "<DECIMALINT>", + "<DECIMALLONG>", + "<UNSIGNED_DECIMALINT>", + "<UNSIGNED_DECIMALLONG>", + "<HEXADECIMALINT>", + "<HEXADECIMALLONG>", + "<UNSIGNED_HEXADECIMALINT>", + "<UNSIGNED_HEXADECIMALLONG>", + "<FLOATONE>", + "<FLOATTWO>", + "<CHARACTER>", + "<STRING>", + "\"finally\"", + "<ID>", + }; + +} diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/CPPParserTokenManager.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/CPPParserTokenManager.java new file mode 100644 index 00000000000..673307e1450 --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/CPPParserTokenManager.java @@ -0,0 +1,1687 @@ +/* Generated By:JavaCC: Do not edit this line. CPPParserTokenManager.java */ +package net.sourceforge.pmd.cpd.cppast; + +/** Token Manager. */ +public class CPPParserTokenManager implements CPPParserConstants +{ + private static String filename; + public static void setFileName(String name) { + filename = name; + } + public static String getFileName() { + return filename; + } + + /** Debug output. */ + public static java.io.PrintStream debugStream = System.out; + /** Set debug output. */ + public static void setDebugStream(java.io.PrintStream ds) { debugStream = ds; } +private static final int jjStopStringLiteralDfa_0(int pos, long active0, long active1, long active2) +{ + switch (pos) + { + case 0: + if ((active1 & 0x3ffffffffffff0L) != 0L || (active2 & 0x40L) != 0L) + { + jjmatchedKind = 135; + return 29; + } + if ((active0 & 0x40000000L) != 0L || (active1 & 0x5L) != 0L) + return 1; + return -1; + case 1: + if ((active1 & 0x3fffffffbf9ff0L) != 0L || (active2 & 0x40L) != 0L) + { + if (jjmatchedPos != 1) + { + jjmatchedKind = 135; + jjmatchedPos = 1; + } + return 29; + } + if ((active1 & 0x406000L) != 0L) + return 29; + return -1; + case 2: + if ((active1 & 0x3ffbfffab7dff0L) != 0L || (active2 & 0x40L) != 0L) + { + jjmatchedKind = 135; + jjmatchedPos = 2; + return 29; + } + if ((active1 & 0x40005080000L) != 0L) + return 29; + return -1; + case 3: + if ((active1 & 0x3779fff8965ea0L) != 0L || (active2 & 0x40L) != 0L) + { + jjmatchedKind = 135; + jjmatchedPos = 3; + return 29; + } + if ((active1 & 0x8820002218150L) != 0L) + return 29; + return -1; + case 4: + if ((active1 & 0x569bdf8925c00L) != 0L || (active2 & 0x40L) != 0L) + { + jjmatchedKind = 135; + jjmatchedPos = 4; + return 29; + } + if ((active1 & 0x321042000402a0L) != 0L) + return 29; + return -1; + case 5: + if ((active1 & 0x56900d8000c00L) != 0L || (active2 & 0x40L) != 0L) + { + jjmatchedKind = 135; + jjmatchedPos = 5; + return 29; + } + if ((active1 & 0xbd20925000L) != 0L) + return 29; + return -1; + case 6: + if ((active1 & 0x52100d0000400L) != 0L) + { + jjmatchedKind = 135; + jjmatchedPos = 6; + return 29; + } + if ((active1 & 0x480008000800L) != 0L || (active2 & 0x40L) != 0L) + return 29; + return -1; + case 7: + if ((active1 & 0x50000000L) != 0L) + { + jjmatchedKind = 135; + jjmatchedPos = 7; + return 29; + } + if ((active1 & 0x5210080000400L) != 0L) + return 29; + return -1; + case 8: + if ((active1 & 0x40000000L) != 0L) + { + jjmatchedKind = 135; + jjmatchedPos = 8; + return 29; + } + if ((active1 & 0x10000000L) != 0L) + return 29; + return -1; + default : + return -1; + } +} +private static final int jjStartNfa_0(int pos, long active0, long active1, long active2) +{ + return jjMoveNfa_0(jjStopStringLiteralDfa_0(pos, active0, active1, active2), pos + 1); +} +static private int jjStopAtPos(int pos, int kind) +{ + jjmatchedKind = kind; + jjmatchedPos = pos; + return pos + 1; +} +static private int jjMoveStringLiteralDfa0_0() +{ + switch(curChar) + { + case 13: + return jjMoveStringLiteralDfa1_0(0x10L, 0x0L, 0x0L); + case 33: + jjmatchedKind = 63; + return jjMoveStringLiteralDfa1_0(0x1000000000000L, 0x0L, 0x0L); + case 35: + return jjStopAtPos(0, 8); + case 37: + jjmatchedKind = 59; + return jjMoveStringLiteralDfa1_0(0x400000000L, 0x0L, 0x0L); + case 38: + jjmatchedKind = 46; + return jjMoveStringLiteralDfa1_0(0x88000000000L, 0x0L, 0x0L); + case 40: + return jjStopAtPos(0, 23); + case 41: + return jjStopAtPos(0, 24); + case 42: + jjmatchedKind = 57; + return jjMoveStringLiteralDfa1_0(0x100000000L, 0x0L, 0x0L); + case 43: + jjmatchedKind = 55; + return jjMoveStringLiteralDfa1_0(0x1000000800000000L, 0x0L, 0x0L); + case 44: + return jjStopAtPos(0, 28); + case 45: + jjmatchedKind = 56; + return jjMoveStringLiteralDfa1_0(0x2000001000000000L, 0xaL, 0x0L); + case 46: + jjmatchedKind = 64; + return jjMoveStringLiteralDfa1_0(0x40000000L, 0x4L, 0x0L); + case 47: + jjmatchedKind = 58; + return jjMoveStringLiteralDfa1_0(0x2000000c0L, 0x0L, 0x0L); + case 58: + jjmatchedKind = 26; + return jjMoveStringLiteralDfa1_0(0x2000000L, 0x0L, 0x0L); + case 59: + return jjStopAtPos(0, 27); + case 60: + jjmatchedKind = 49; + return jjMoveStringLiteralDfa1_0(0x28002000000000L, 0x0L, 0x0L); + case 61: + jjmatchedKind = 31; + return jjMoveStringLiteralDfa1_0(0x800000000000L, 0x0L, 0x0L); + case 62: + jjmatchedKind = 50; + return jjMoveStringLiteralDfa1_0(0x50004000000000L, 0x0L, 0x0L); + case 63: + return jjStopAtPos(0, 29); + case 91: + return jjStopAtPos(0, 21); + case 93: + return jjStopAtPos(0, 22); + case 94: + jjmatchedKind = 45; + return jjMoveStringLiteralDfa1_0(0x10000000000L, 0x0L, 0x0L); + case 97: + return jjMoveStringLiteralDfa1_0(0x0L, 0x10L, 0x0L); + case 98: + return jjMoveStringLiteralDfa1_0(0x0L, 0x20L, 0x0L); + case 99: + return jjMoveStringLiteralDfa1_0(0x0L, 0x40000007c0L, 0x0L); + case 100: + return jjMoveStringLiteralDfa1_0(0x0L, 0x7800L, 0x0L); + case 101: + return jjMoveStringLiteralDfa1_0(0x0L, 0x38000L, 0x0L); + case 102: + return jjMoveStringLiteralDfa1_0(0x0L, 0x100000001c0000L, 0x40L); + case 103: + return jjMoveStringLiteralDfa1_0(0x0L, 0x200000L, 0x0L); + case 105: + return jjMoveStringLiteralDfa1_0(0x0L, 0x1c00000L, 0x0L); + case 108: + return jjMoveStringLiteralDfa1_0(0x0L, 0x2000000L, 0x0L); + case 110: + return jjMoveStringLiteralDfa1_0(0x0L, 0x4000000L, 0x0L); + case 111: + return jjMoveStringLiteralDfa1_0(0x0L, 0x4000000000000L, 0x0L); + case 112: + return jjMoveStringLiteralDfa1_0(0x0L, 0x38000000L, 0x0L); + case 114: + return jjMoveStringLiteralDfa1_0(0x0L, 0x1c0000000L, 0x0L); + case 115: + return jjMoveStringLiteralDfa1_0(0x0L, 0xbe00000000L, 0x0L); + case 116: + return jjMoveStringLiteralDfa1_0(0x0L, 0x280f0000000000L, 0x0L); + case 117: + return jjMoveStringLiteralDfa1_0(0x0L, 0x300000000000L, 0x0L); + case 118: + return jjMoveStringLiteralDfa1_0(0x0L, 0x1c00000000000L, 0x0L); + case 119: + return jjMoveStringLiteralDfa1_0(0x0L, 0x2000000000000L, 0x0L); + case 123: + return jjStopAtPos(0, 19); + case 124: + jjmatchedKind = 44; + return jjMoveStringLiteralDfa1_0(0x60000000000L, 0x0L, 0x0L); + case 125: + return jjStopAtPos(0, 20); + case 126: + return jjStopAtPos(0, 62); + default : + return jjMoveNfa_0(28, 0); + } +} +static private int jjMoveStringLiteralDfa1_0(long active0, long active1, long active2) +{ + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(0, active0, active1, active2); + return 1; + } + switch(curChar) + { + case 10: + if ((active0 & 0x10L) != 0L) + return jjStopAtPos(1, 4); + break; + case 38: + if ((active0 & 0x80000000000L) != 0L) + return jjStopAtPos(1, 43); + break; + case 42: + if ((active0 & 0x80L) != 0L) + return jjStopAtPos(1, 7); + else if ((active1 & 0x4L) != 0L) + return jjStopAtPos(1, 66); + break; + case 43: + if ((active0 & 0x1000000000000000L) != 0L) + return jjStopAtPos(1, 60); + break; + case 45: + if ((active0 & 0x2000000000000000L) != 0L) + return jjStopAtPos(1, 61); + break; + case 46: + return jjMoveStringLiteralDfa2_0(active0, 0x40000000L, active1, 0L, active2, 0L); + case 47: + if ((active0 & 0x40L) != 0L) + return jjStopAtPos(1, 6); + break; + case 58: + if ((active0 & 0x2000000L) != 0L) + return jjStopAtPos(1, 25); + break; + case 60: + if ((active0 & 0x20000000000000L) != 0L) + { + jjmatchedKind = 53; + jjmatchedPos = 1; + } + return jjMoveStringLiteralDfa2_0(active0, 0x2000000000L, active1, 0L, active2, 0L); + case 61: + if ((active0 & 0x100000000L) != 0L) + return jjStopAtPos(1, 32); + else if ((active0 & 0x200000000L) != 0L) + return jjStopAtPos(1, 33); + else if ((active0 & 0x400000000L) != 0L) + return jjStopAtPos(1, 34); + else if ((active0 & 0x800000000L) != 0L) + return jjStopAtPos(1, 35); + else if ((active0 & 0x1000000000L) != 0L) + return jjStopAtPos(1, 36); + else if ((active0 & 0x8000000000L) != 0L) + return jjStopAtPos(1, 39); + else if ((active0 & 0x10000000000L) != 0L) + return jjStopAtPos(1, 40); + else if ((active0 & 0x20000000000L) != 0L) + return jjStopAtPos(1, 41); + else if ((active0 & 0x800000000000L) != 0L) + return jjStopAtPos(1, 47); + else if ((active0 & 0x1000000000000L) != 0L) + return jjStopAtPos(1, 48); + else if ((active0 & 0x8000000000000L) != 0L) + return jjStopAtPos(1, 51); + else if ((active0 & 0x10000000000000L) != 0L) + return jjStopAtPos(1, 52); + break; + case 62: + if ((active0 & 0x40000000000000L) != 0L) + { + jjmatchedKind = 54; + jjmatchedPos = 1; + } + else if ((active1 & 0x2L) != 0L) + { + jjmatchedKind = 65; + jjmatchedPos = 1; + } + return jjMoveStringLiteralDfa2_0(active0, 0x4000000000L, active1, 0x8L, active2, 0L); + case 97: + return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x100000000000c0L, active2, 0L); + case 101: + return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x101c4001800L, active2, 0L); + case 102: + if ((active1 & 0x400000L) != 0L) + return jjStartNfaWithStates_0(1, 86, 29); + break; + case 104: + return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x22020200000100L, active2, 0L); + case 105: + return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x400c00000000L, active2, 0x40L); + case 108: + return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x4000048000L, active2, 0L); + case 110: + return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x300001810000L, active2, 0L); + case 111: + if ((active1 & 0x2000L) != 0L) + { + jjmatchedKind = 77; + jjmatchedPos = 1; + } + return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x1800002284600L, active2, 0L); + case 112: + return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x4000000000000L, active2, 0L); + case 114: + return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x8040018100020L, active2, 0L); + case 116: + return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x3000000000L, active2, 0L); + case 117: + return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x20000010L, active2, 0L); + case 119: + return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x8000000000L, active2, 0L); + case 120: + return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x20000L, active2, 0L); + case 121: + return jjMoveStringLiteralDfa2_0(active0, 0L, active1, 0x80000000000L, active2, 0L); + case 124: + if ((active0 & 0x40000000000L) != 0L) + return jjStopAtPos(1, 42); + break; + default : + break; + } + return jjStartNfa_0(0, active0, active1, active2); +} +static private int jjMoveStringLiteralDfa2_0(long old0, long active0, long old1, long active1, long old2, long active2) +{ + if (((active0 &= old0) | (active1 &= old1) | (active2 &= old2)) == 0L) + return jjStartNfa_0(0, old0, old1, old2); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(1, active0, active1, active2); + return 2; + } + switch(curChar) + { + case 42: + if ((active1 & 0x8L) != 0L) + return jjStopAtPos(2, 67); + break; + case 46: + if ((active0 & 0x40000000L) != 0L) + return jjStopAtPos(2, 30); + break; + case 61: + if ((active0 & 0x2000000000L) != 0L) + return jjStopAtPos(2, 37); + else if ((active0 & 0x4000000000L) != 0L) + return jjStopAtPos(2, 38); + break; + case 97: + return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x5000000100L, active2, 0L); + case 98: + return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x20000000L, active2, 0L); + case 100: + return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x40000000L, active2, 0L); + case 101: + return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x4000000000020L, active2, 0L); + case 102: + return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x800L, active2, 0L); + case 103: + return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x480000000L, active2, 0L); + case 105: + return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x2928008100000L, active2, 0L); + case 108: + return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x11000000801000L, active2, 0L); + case 109: + return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x10000000000L, active2, 0L); + case 110: + return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x2000600L, active2, 0x40L); + case 111: + return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x210040000L, active2, 0L); + case 112: + return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x80000000000L, active2, 0L); + case 114: + if ((active1 & 0x80000L) != 0L) + return jjStartNfaWithStates_0(2, 83, 29); + return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x20402000000000L, active2, 0L); + case 115: + return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x200000008040L, active2, 0L); + case 116: + if ((active1 & 0x1000000L) != 0L) + return jjStartNfaWithStates_0(2, 88, 29); + return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x100220090L, active2, 0L); + case 117: + return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x8000000014000L, active2, 0L); + case 119: + if ((active1 & 0x4000000L) != 0L) + return jjStartNfaWithStates_0(2, 90, 29); + break; + case 121: + if ((active1 & 0x40000000000L) != 0L) + return jjStartNfaWithStates_0(2, 106, 29); + break; + case 122: + return jjMoveStringLiteralDfa3_0(active0, 0L, active1, 0x800000000L, active2, 0L); + default : + break; + } + return jjStartNfa_0(1, active0, active1, active2); +} +static private int jjMoveStringLiteralDfa3_0(long old0, long active0, long old1, long active1, long old2, long active2) +{ + if (((active0 &= old0) | (active1 &= old1) | (active2 &= old2)) == 0L) + return jjStartNfa_0(1, old0, old1, old2); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(2, 0L, active1, active2); + return 3; + } + switch(curChar) + { + case 97: + return jjMoveStringLiteralDfa4_0(active1, 0x1000000040820L, active2, 0x40L); + case 98: + return jjMoveStringLiteralDfa4_0(active1, 0x4000L, active2, 0L); + case 99: + return jjMoveStringLiteralDfa4_0(active1, 0x80L, active2, 0L); + case 100: + if ((active1 & 0x800000000000L) != 0L) + return jjStartNfaWithStates_0(3, 111, 29); + break; + case 101: + if ((active1 & 0x40L) != 0L) + return jjStartNfaWithStates_0(3, 70, 29); + else if ((active1 & 0x8000L) != 0L) + return jjStartNfaWithStates_0(3, 79, 29); + else if ((active1 & 0x8000000000000L) != 0L) + return jjStartNfaWithStates_0(3, 115, 29); + return jjMoveStringLiteralDfa4_0(active1, 0x80840121000L, active2, 0L); + case 103: + if ((active1 & 0x2000000L) != 0L) + return jjStartNfaWithStates_0(3, 89, 29); + break; + case 105: + return jjMoveStringLiteralDfa4_0(active1, 0x200080800000L, active2, 0L); + case 108: + return jjMoveStringLiteralDfa4_0(active1, 0x2000020000000L, active2, 0L); + case 109: + if ((active1 & 0x10000L) != 0L) + return jjStartNfaWithStates_0(3, 80, 29); + break; + case 110: + return jjMoveStringLiteralDfa4_0(active1, 0x400000000L, active2, 0L); + case 111: + if ((active1 & 0x10L) != 0L) + return jjStartNfaWithStates_0(3, 68, 29); + else if ((active1 & 0x200000L) != 0L) + return jjStartNfaWithStates_0(3, 85, 29); + return jjMoveStringLiteralDfa4_0(active1, 0x20100000000000L, active2, 0L); + case 112: + return jjMoveStringLiteralDfa4_0(active1, 0x10000000000L, active2, 0L); + case 114: + if ((active1 & 0x100L) != 0L) + return jjStartNfaWithStates_0(3, 72, 29); + return jjMoveStringLiteralDfa4_0(active1, 0x4000200000000L, active2, 0L); + case 115: + if ((active1 & 0x20000000000L) != 0L) + return jjStartNfaWithStates_0(3, 105, 29); + return jjMoveStringLiteralDfa4_0(active1, 0x10004000000200L, active2, 0L); + case 116: + return jjMoveStringLiteralDfa4_0(active1, 0x409010000400L, active2, 0L); + case 117: + return jjMoveStringLiteralDfa4_0(active1, 0x2100000000L, active2, 0L); + case 118: + return jjMoveStringLiteralDfa4_0(active1, 0x8000000L, active2, 0L); + default : + break; + } + return jjStartNfa_0(2, 0L, active1, active2); +} +static private int jjMoveStringLiteralDfa4_0(long old1, long active1, long old2, long active2) +{ + if (((active1 &= old1) | (active2 &= old2)) == 0L) + return jjStartNfa_0(2, 0L, old1, old2); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(3, 0L, active1, active2); + return 4; + } + switch(curChar) + { + case 97: + return jjMoveStringLiteralDfa5_0(active1, 0x4000008000000L, active2, 0L); + case 99: + return jjMoveStringLiteralDfa5_0(active1, 0xa040000000L, active2, 0L); + case 100: + return jjMoveStringLiteralDfa5_0(active1, 0x80000000000L, active2, 0L); + case 101: + if ((active1 & 0x2000000000000L) != 0L) + return jjStartNfaWithStates_0(4, 113, 29); + else if ((active1 & 0x10000000000000L) != 0L) + return jjStartNfaWithStates_0(4, 116, 29); + return jjMoveStringLiteralDfa5_0(active1, 0x410000000L, active2, 0L); + case 103: + return jjMoveStringLiteralDfa5_0(active1, 0x200000000000L, active2, 0L); + case 104: + if ((active1 & 0x80L) != 0L) + return jjStartNfaWithStates_0(4, 71, 29); + break; + case 105: + return jjMoveStringLiteralDfa5_0(active1, 0x1020000400L, active2, 0L); + case 107: + if ((active1 & 0x20L) != 0L) + return jjStartNfaWithStates_0(4, 69, 29); + break; + case 108: + return jjMoveStringLiteralDfa5_0(active1, 0x10000004000L, active2, 0x40L); + case 110: + if ((active1 & 0x100000000000L) != 0L) + return jjStartNfaWithStates_0(4, 108, 29); + return jjMoveStringLiteralDfa5_0(active1, 0x900000L, active2, 0L); + case 111: + return jjMoveStringLiteralDfa5_0(active1, 0x800000000L, active2, 0L); + case 114: + return jjMoveStringLiteralDfa5_0(active1, 0x100020000L, active2, 0L); + case 115: + if ((active1 & 0x4000000000L) != 0L) + return jjStartNfaWithStates_0(4, 102, 29); + return jjMoveStringLiteralDfa5_0(active1, 0x80000000L, active2, 0L); + case 116: + if ((active1 & 0x200L) != 0L) + return jjStartNfaWithStates_0(4, 73, 29); + else if ((active1 & 0x40000L) != 0L) + return jjStartNfaWithStates_0(4, 82, 29); + else if ((active1 & 0x200000000L) != 0L) + return jjStartNfaWithStates_0(4, 97, 29); + return jjMoveStringLiteralDfa5_0(active1, 0x1000000001000L, active2, 0L); + case 117: + return jjMoveStringLiteralDfa5_0(active1, 0x400000000800L, active2, 0L); + case 119: + if ((active1 & 0x20000000000000L) != 0L) + return jjStartNfaWithStates_0(4, 117, 29); + break; + default : + break; + } + return jjStartNfa_0(3, 0L, active1, active2); +} +static private int jjMoveStringLiteralDfa5_0(long old1, long active1, long old2, long active2) +{ + if (((active1 &= old1) | (active2 &= old2)) == 0L) + return jjStartNfa_0(3, 0L, old1, old2); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(4, 0L, active1, active2); + return 5; + } + switch(curChar) + { + case 97: + return jjMoveStringLiteralDfa6_0(active1, 0x410000000000L, active2, 0L); + case 99: + if ((active1 & 0x20000000L) != 0L) + return jjStartNfaWithStates_0(5, 93, 29); + else if ((active1 & 0x1000000000L) != 0L) + return jjStartNfaWithStates_0(5, 100, 29); + return jjMoveStringLiteralDfa6_0(active1, 0x10000000L, active2, 0L); + case 100: + if ((active1 & 0x100000L) != 0L) + return jjStartNfaWithStates_0(5, 84, 29); + else if ((active1 & 0x400000000L) != 0L) + return jjStartNfaWithStates_0(5, 98, 29); + break; + case 101: + if ((active1 & 0x1000L) != 0L) + return jjStartNfaWithStates_0(5, 76, 29); + else if ((active1 & 0x4000L) != 0L) + return jjStartNfaWithStates_0(5, 78, 29); + else if ((active1 & 0x800000L) != 0L) + return jjStartNfaWithStates_0(5, 87, 29); + return jjMoveStringLiteralDfa6_0(active1, 0x80000000000L, active2, 0L); + case 102: + if ((active1 & 0x800000000L) != 0L) + return jjStartNfaWithStates_0(5, 99, 29); + break; + case 104: + if ((active1 & 0x8000000000L) != 0L) + return jjStartNfaWithStates_0(5, 103, 29); + break; + case 105: + return jjMoveStringLiteralDfa6_0(active1, 0x1000000000000L, active2, 0L); + case 108: + return jjMoveStringLiteralDfa6_0(active1, 0x40000800L, active2, 0x40L); + case 110: + if ((active1 & 0x20000L) != 0L) + return jjStartNfaWithStates_0(5, 81, 29); + else if ((active1 & 0x100000000L) != 0L) + return jjStartNfaWithStates_0(5, 96, 29); + return jjMoveStringLiteralDfa6_0(active1, 0x200000000400L, active2, 0L); + case 116: + if ((active1 & 0x2000000000L) != 0L) + return jjStartNfaWithStates_0(5, 101, 29); + return jjMoveStringLiteralDfa6_0(active1, 0x4000088000000L, active2, 0L); + default : + break; + } + return jjStartNfa_0(4, 0L, active1, active2); +} +static private int jjMoveStringLiteralDfa6_0(long old1, long active1, long old2, long active2) +{ + if (((active1 &= old1) | (active2 &= old2)) == 0L) + return jjStartNfa_0(4, 0L, old1, old2); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(5, 0L, active1, active2); + return 6; + } + switch(curChar) + { + case 97: + return jjMoveStringLiteralDfa7_0(active1, 0x40000000L, active2, 0L); + case 101: + if ((active1 & 0x8000000L) != 0L) + return jjStartNfaWithStates_0(6, 91, 29); + return jjMoveStringLiteralDfa7_0(active1, 0x200080000000L, active2, 0L); + case 102: + if ((active1 & 0x80000000000L) != 0L) + return jjStartNfaWithStates_0(6, 107, 29); + break; + case 108: + if ((active1 & 0x400000000000L) != 0L) + return jjStartNfaWithStates_0(6, 110, 29); + return jjMoveStringLiteralDfa7_0(active1, 0x1000000000000L, active2, 0L); + case 111: + return jjMoveStringLiteralDfa7_0(active1, 0x4000000000000L, active2, 0L); + case 116: + if ((active1 & 0x800L) != 0L) + return jjStartNfaWithStates_0(6, 75, 29); + return jjMoveStringLiteralDfa7_0(active1, 0x10010000000L, active2, 0L); + case 117: + return jjMoveStringLiteralDfa7_0(active1, 0x400L, active2, 0L); + case 121: + if ((active2 & 0x40L) != 0L) + return jjStartNfaWithStates_0(6, 134, 29); + break; + default : + break; + } + return jjStartNfa_0(5, 0L, active1, active2); +} +static private int jjMoveStringLiteralDfa7_0(long old1, long active1, long old2, long active2) +{ + if (((active1 &= old1) | (active2 &= old2)) == 0L) + return jjStartNfa_0(5, 0L, old1, old2); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(6, 0L, active1, 0L); + return 7; + } + switch(curChar) + { + case 100: + if ((active1 & 0x200000000000L) != 0L) + return jjStartNfaWithStates_0(7, 109, 29); + break; + case 101: + if ((active1 & 0x400L) != 0L) + return jjStartNfaWithStates_0(7, 74, 29); + else if ((active1 & 0x10000000000L) != 0L) + return jjStartNfaWithStates_0(7, 104, 29); + else if ((active1 & 0x1000000000000L) != 0L) + return jjStartNfaWithStates_0(7, 112, 29); + return jjMoveStringLiteralDfa8_0(active1, 0x10000000L); + case 114: + if ((active1 & 0x80000000L) != 0L) + return jjStartNfaWithStates_0(7, 95, 29); + else if ((active1 & 0x4000000000000L) != 0L) + return jjStartNfaWithStates_0(7, 114, 29); + return jjMoveStringLiteralDfa8_0(active1, 0x40000000L); + default : + break; + } + return jjStartNfa_0(6, 0L, active1, 0L); +} +static private int jjMoveStringLiteralDfa8_0(long old1, long active1) +{ + if (((active1 &= old1)) == 0L) + return jjStartNfa_0(6, 0L, old1, 0L); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(7, 0L, active1, 0L); + return 8; + } + switch(curChar) + { + case 100: + if ((active1 & 0x10000000L) != 0L) + return jjStartNfaWithStates_0(8, 92, 29); + break; + case 101: + return jjMoveStringLiteralDfa9_0(active1, 0x40000000L); + default : + break; + } + return jjStartNfa_0(7, 0L, active1, 0L); +} +static private int jjMoveStringLiteralDfa9_0(long old1, long active1) +{ + if (((active1 &= old1)) == 0L) + return jjStartNfa_0(7, 0L, old1, 0L); + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + jjStopStringLiteralDfa_0(8, 0L, active1, 0L); + return 9; + } + switch(curChar) + { + case 100: + if ((active1 & 0x40000000L) != 0L) + return jjStartNfaWithStates_0(9, 94, 29); + break; + default : + break; + } + return jjStartNfa_0(8, 0L, active1, 0L); +} +static private int jjStartNfaWithStates_0(int pos, int kind, int state) +{ + jjmatchedKind = kind; + jjmatchedPos = pos; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { return pos + 1; } + return jjMoveNfa_0(state, pos + 1); +} +static final long[] jjbitVec0 = { + 0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL +}; +static private int jjMoveNfa_0(int startState, int curPos) +{ + int startsAt = 0; + jjnewStateCnt = 78; + int i = 1; + jjstateSet[0] = startState; + int kind = 0x7fffffff; + for (;;) + { + if (++jjround == 0x7fffffff) + ReInitRounds(); + if (curChar < 64) + { + long l = 1L << curChar; + do + { + switch(jjstateSet[--i]) + { + case 28: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(0, 5); + else if (curChar == 36) + { + if (kind > 135) + kind = 135; + jjCheckNAdd(29); + } + else if (curChar == 34) + jjCheckNAddStates(6, 8); + else if (curChar == 39) + jjCheckNAddTwoStates(7, 9); + else if (curChar == 46) + jjCheckNAdd(1); + if ((0x3fe000000000000L & l) != 0L) + { + if (kind > 122) + kind = 122; + jjCheckNAddStates(9, 16); + } + else if (curChar == 48) + jjAddStates(17, 20); + if (curChar == 48) + { + if (kind > 118) + kind = 118; + jjCheckNAddStates(21, 28); + } + break; + case 0: + if (curChar == 46) + jjCheckNAdd(1); + break; + case 1: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 130) + kind = 130; + jjCheckNAddStates(29, 31); + break; + case 3: + if ((0x280000000000L & l) != 0L) + jjCheckNAdd(4); + break; + case 4: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 130) + kind = 130; + jjCheckNAddTwoStates(4, 5); + break; + case 6: + if (curChar == 39) + jjCheckNAddTwoStates(7, 9); + break; + case 7: + if ((0xffffff7fffffdbffL & l) != 0L) + jjCheckNAddTwoStates(7, 8); + break; + case 8: + if (curChar == 39 && kind > 132) + kind = 132; + break; + case 10: + if ((0x8000008400000000L & l) != 0L) + jjCheckNAdd(8); + break; + case 11: + if (curChar == 48) + jjCheckNAddTwoStates(12, 8); + break; + case 12: + if ((0xff000000000000L & l) != 0L) + jjCheckNAddTwoStates(12, 8); + break; + case 13: + if ((0x3fe000000000000L & l) != 0L) + jjCheckNAddTwoStates(14, 8); + break; + case 14: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(14, 8); + break; + case 16: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(16, 8); + break; + case 17: + if (curChar == 34) + jjCheckNAddStates(6, 8); + break; + case 18: + if ((0xfffffffbffffdbffL & l) != 0L) + jjCheckNAddStates(6, 8); + break; + case 20: + if ((0x8000008400000400L & l) != 0L) + jjCheckNAddStates(6, 8); + break; + case 21: + if (curChar == 34 && kind > 133) + kind = 133; + break; + case 22: + if (curChar == 48) + jjCheckNAddStates(32, 35); + break; + case 23: + if ((0xff000000000000L & l) != 0L) + jjCheckNAddStates(32, 35); + break; + case 24: + if ((0x3fe000000000000L & l) != 0L) + jjCheckNAddStates(36, 39); + break; + case 25: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(36, 39); + break; + case 27: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(40, 43); + break; + case 29: + if ((0x3ff001000000000L & l) == 0L) + break; + if (kind > 135) + kind = 135; + jjCheckNAdd(29); + break; + case 30: + if (curChar != 48) + break; + if (kind > 118) + kind = 118; + jjCheckNAddStates(21, 28); + break; + case 31: + if ((0xff000000000000L & l) == 0L) + break; + if (kind > 118) + kind = 118; + jjCheckNAdd(31); + break; + case 32: + if ((0xff000000000000L & l) != 0L) + jjCheckNAddTwoStates(32, 33); + break; + case 34: + if ((0xff000000000000L & l) != 0L) + jjCheckNAddTwoStates(34, 35); + break; + case 36: + if ((0xff000000000000L & l) != 0L) + jjCheckNAddStates(44, 46); + break; + case 41: + if ((0x3fe000000000000L & l) == 0L) + break; + if (kind > 122) + kind = 122; + jjCheckNAddStates(9, 16); + break; + case 42: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 122) + kind = 122; + jjCheckNAdd(42); + break; + case 43: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(43, 44); + break; + case 45: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(45, 46); + break; + case 47: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(47, 49); + break; + case 52: + if (curChar == 48) + jjAddStates(17, 20); + break; + case 54: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 126) + kind = 126; + jjstateSet[jjnewStateCnt++] = 54; + break; + case 56: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 127) + kind = 127; + jjAddStates(50, 51); + break; + case 59: + if ((0x3ff000000000000L & l) != 0L) + jjAddStates(52, 53); + break; + case 62: + if ((0x3ff000000000000L & l) != 0L) + jjAddStates(54, 56); + break; + case 67: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddStates(0, 5); + break; + case 68: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(68, 69); + break; + case 69: + if (curChar != 46) + break; + if (kind > 130) + kind = 130; + jjCheckNAddStates(57, 59); + break; + case 70: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 130) + kind = 130; + jjCheckNAddStates(57, 59); + break; + case 71: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(71, 0); + break; + case 72: + if ((0x3ff000000000000L & l) != 0L) + jjCheckNAddTwoStates(72, 73); + break; + case 74: + if ((0x280000000000L & l) != 0L) + jjCheckNAdd(75); + break; + case 75: + if ((0x3ff000000000000L & l) == 0L) + break; + if (kind > 131) + kind = 131; + jjCheckNAddTwoStates(75, 76); + break; + default : break; + } + } while(i != startsAt); + } + else if (curChar < 128) + { + long l = 1L << (curChar & 077); + do + { + switch(jjstateSet[--i]) + { + case 28: + if ((0x7fffffe87fffffeL & l) != 0L) + { + if (kind > 135) + kind = 135; + jjCheckNAdd(29); + } + if (curChar == 76) + jjAddStates(60, 61); + break; + case 2: + if ((0x2000000020L & l) != 0L) + jjAddStates(62, 63); + break; + case 5: + if ((0x104000001040L & l) != 0L && kind > 130) + kind = 130; + break; + case 7: + if ((0xffffffffefffffffL & l) != 0L) + jjCheckNAddTwoStates(7, 8); + break; + case 9: + if (curChar == 92) + jjAddStates(64, 67); + break; + case 10: + if ((0x54404610000000L & l) != 0L) + jjCheckNAdd(8); + break; + case 15: + if ((0x100000001000000L & l) != 0L) + jjCheckNAdd(16); + break; + case 16: + if ((0x7e0000007eL & l) != 0L) + jjCheckNAddTwoStates(16, 8); + break; + case 18: + if ((0xffffffffefffffffL & l) != 0L) + jjCheckNAddStates(6, 8); + break; + case 19: + if (curChar == 92) + jjAddStates(68, 71); + break; + case 20: + if ((0x54404610000000L & l) != 0L) + jjCheckNAddStates(6, 8); + break; + case 26: + if ((0x100000001000000L & l) != 0L) + jjCheckNAdd(27); + break; + case 27: + if ((0x7e0000007eL & l) != 0L) + jjCheckNAddStates(40, 43); + break; + case 29: + if ((0x7fffffe87fffffeL & l) == 0L) + break; + if (kind > 135) + kind = 135; + jjCheckNAdd(29); + break; + case 33: + if ((0x100000001000L & l) != 0L && kind > 119) + kind = 119; + break; + case 35: + if ((0x20000000200000L & l) != 0L && kind > 120) + kind = 120; + break; + case 37: + if ((0x100000001000L & l) != 0L && kind > 121) + kind = 121; + break; + case 38: + if ((0x20000000200000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 37; + break; + case 39: + if ((0x20000000200000L & l) != 0L && kind > 121) + kind = 121; + break; + case 40: + if ((0x100000001000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 39; + break; + case 44: + if ((0x20100000201000L & l) != 0L && kind > 123) + kind = 123; + break; + case 46: + if ((0x20000000200000L & l) != 0L && kind > 124) + kind = 124; + break; + case 48: + if ((0x100000001000L & l) != 0L && kind > 125) + kind = 125; + break; + case 49: + if ((0x20000000200000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 48; + break; + case 50: + if ((0x20000000200000L & l) != 0L && kind > 125) + kind = 125; + break; + case 51: + if ((0x100000001000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 50; + break; + case 53: + if ((0x100000001000000L & l) != 0L) + jjCheckNAdd(54); + break; + case 54: + if ((0x7e0000007eL & l) == 0L) + break; + if (kind > 126) + kind = 126; + jjCheckNAdd(54); + break; + case 55: + if ((0x100000001000000L & l) != 0L) + jjCheckNAdd(56); + break; + case 56: + if ((0x7e0000007eL & l) == 0L) + break; + if (kind > 127) + kind = 127; + jjCheckNAddTwoStates(56, 57); + break; + case 57: + if ((0x20100000201000L & l) != 0L && kind > 127) + kind = 127; + break; + case 58: + if ((0x100000001000000L & l) != 0L) + jjCheckNAdd(59); + break; + case 59: + if ((0x7e0000007eL & l) != 0L) + jjCheckNAddTwoStates(59, 60); + break; + case 60: + if ((0x20000000200000L & l) != 0L && kind > 128) + kind = 128; + break; + case 61: + if ((0x100000001000000L & l) != 0L) + jjCheckNAdd(62); + break; + case 62: + if ((0x7e0000007eL & l) != 0L) + jjCheckNAddStates(54, 56); + break; + case 63: + if ((0x100000001000L & l) != 0L && kind > 129) + kind = 129; + break; + case 64: + if ((0x20000000200000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 63; + break; + case 65: + if ((0x20000000200000L & l) != 0L && kind > 129) + kind = 129; + break; + case 66: + if ((0x100000001000L & l) != 0L) + jjstateSet[jjnewStateCnt++] = 65; + break; + case 73: + if ((0x2000000020L & l) != 0L) + jjAddStates(72, 73); + break; + case 76: + if ((0x104000001040L & l) != 0L && kind > 131) + kind = 131; + break; + case 77: + if (curChar == 76) + jjAddStates(60, 61); + break; + default : break; + } + } while(i != startsAt); + } + else + { + int i2 = (curChar & 0xff) >> 6; + long l2 = 1L << (curChar & 077); + do + { + switch(jjstateSet[--i]) + { + case 7: + if ((jjbitVec0[i2] & l2) != 0L) + jjAddStates(74, 75); + break; + case 18: + if ((jjbitVec0[i2] & l2) != 0L) + jjAddStates(6, 8); + break; + default : break; + } + } while(i != startsAt); + } + if (kind != 0x7fffffff) + { + jjmatchedKind = kind; + jjmatchedPos = curPos; + kind = 0x7fffffff; + } + ++curPos; + if ((i = jjnewStateCnt) == (startsAt = 78 - (jjnewStateCnt = startsAt))) + return curPos; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { return curPos; } + } +} +static private int jjMoveStringLiteralDfa0_1() +{ + switch(curChar) + { + case 10: + return jjStopAtPos(0, 9); + default : + return 1; + } +} +static private int jjMoveStringLiteralDfa0_4() +{ + switch(curChar) + { + case 10: + return jjStopAtPos(0, 14); + case 47: + return jjMoveStringLiteralDfa1_4(0x8000L); + case 92: + return jjMoveStringLiteralDfa1_4(0x30000L); + default : + return 1; + } +} +static private int jjMoveStringLiteralDfa1_4(long active0) +{ + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + return 1; + } + switch(curChar) + { + case 10: + if ((active0 & 0x10000L) != 0L) + return jjStopAtPos(1, 16); + break; + case 13: + return jjMoveStringLiteralDfa2_4(active0, 0x20000L); + case 42: + if ((active0 & 0x8000L) != 0L) + return jjStopAtPos(1, 15); + break; + default : + return 2; + } + return 2; +} +static private int jjMoveStringLiteralDfa2_4(long old0, long active0) +{ + if (((active0 &= old0)) == 0L) + return 2; + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + return 2; + } + switch(curChar) + { + case 10: + if ((active0 & 0x20000L) != 0L) + return jjStopAtPos(2, 17); + break; + default : + return 3; + } + return 3; +} +static private int jjMoveStringLiteralDfa0_3() +{ + switch(curChar) + { + case 42: + return jjMoveStringLiteralDfa1_3(0x2000L); + default : + return 1; + } +} +static private int jjMoveStringLiteralDfa1_3(long active0) +{ + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + return 1; + } + switch(curChar) + { + case 47: + if ((active0 & 0x2000L) != 0L) + return jjStopAtPos(1, 13); + break; + default : + return 2; + } + return 2; +} +static private int jjMoveStringLiteralDfa0_2() +{ + switch(curChar) + { + case 42: + return jjMoveStringLiteralDfa1_2(0x800L); + default : + return 1; + } +} +static private int jjMoveStringLiteralDfa1_2(long active0) +{ + try { curChar = input_stream.readChar(); } + catch(java.io.IOException e) { + return 1; + } + switch(curChar) + { + case 47: + if ((active0 & 0x800L) != 0L) + return jjStopAtPos(1, 11); + break; + default : + return 2; + } + return 2; +} +static final int[] jjnextStates = { + 68, 69, 71, 0, 72, 73, 18, 19, 21, 42, 43, 44, 45, 46, 47, 49, + 51, 53, 55, 58, 61, 31, 32, 33, 34, 35, 36, 38, 40, 1, 2, 5, + 18, 19, 23, 21, 18, 19, 25, 21, 18, 19, 27, 21, 36, 38, 40, 47, + 49, 51, 56, 57, 59, 60, 62, 64, 66, 70, 2, 5, 6, 17, 3, 4, + 10, 11, 13, 15, 20, 22, 24, 26, 74, 75, 7, 8, +}; + +/** Token literal values. */ +public static final String[] jjstrLiteralImages = { +"", null, null, null, null, null, null, null, null, null, null, null, null, +null, null, null, null, null, null, "\173", "\175", "\133", "\135", "\50", "\51", +"\72\72", "\72", "\73", "\54", "\77", "\56\56\56", "\75", "\52\75", "\57\75", "\45\75", +"\53\75", "\55\75", "\74\74\75", "\76\76\75", "\46\75", "\136\75", "\174\75", +"\174\174", "\46\46", "\174", "\136", "\46", "\75\75", "\41\75", "\74", "\76", "\74\75", +"\76\75", "\74\74", "\76\76", "\53", "\55", "\52", "\57", "\45", "\53\53", "\55\55", +"\176", "\41", "\56", "\55\76", "\56\52", "\55\76\52", "\141\165\164\157", +"\142\162\145\141\153", "\143\141\163\145", "\143\141\164\143\150", "\143\150\141\162", +"\143\157\156\163\164", "\143\157\156\164\151\156\165\145", "\144\145\146\141\165\154\164", +"\144\145\154\145\164\145", "\144\157", "\144\157\165\142\154\145", "\145\154\163\145", +"\145\156\165\155", "\145\170\164\145\162\156", "\146\154\157\141\164", "\146\157\162", +"\146\162\151\145\156\144", "\147\157\164\157", "\151\146", "\151\156\154\151\156\145", "\151\156\164", +"\154\157\156\147", "\156\145\167", "\160\162\151\166\141\164\145", +"\160\162\157\164\145\143\164\145\144", "\160\165\142\154\151\143", "\162\145\144\145\143\154\141\162\145\144", +"\162\145\147\151\163\164\145\162", "\162\145\164\165\162\156", "\163\150\157\162\164", +"\163\151\147\156\145\144", "\163\151\172\145\157\146", "\163\164\141\164\151\143", +"\163\164\162\165\143\164", "\143\154\141\163\163", "\163\167\151\164\143\150", +"\164\145\155\160\154\141\164\145", "\164\150\151\163", "\164\162\171", "\164\171\160\145\144\145\146", +"\165\156\151\157\156", "\165\156\163\151\147\156\145\144", "\166\151\162\164\165\141\154", +"\166\157\151\144", "\166\157\154\141\164\151\154\145", "\167\150\151\154\145", +"\157\160\145\162\141\164\157\162", "\164\162\165\145", "\146\141\154\163\145", "\164\150\162\157\167", null, null, +null, null, null, null, null, null, null, null, null, null, null, null, null, null, +"\146\151\156\141\154\154\171", null, }; + +/** Lexer state names. */ +public static final String[] lexStateNames = { + "DEFAULT", + "IN_LINE_COMMENT", + "IN_COMMENT", + "IN_PREPROCESSOR_OUTPUT_COMMENT", + "PREPROCESSOR_OUTPUT", +}; + +/** Lex State array. */ +public static final int[] jjnewLexState = { + -1, -1, -1, -1, -1, -1, 1, 2, 4, 0, -1, 0, -1, 4, 0, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, +}; +static final long[] jjtoToken = { + 0xfffffffffff80001L, 0xffffffffffffffffL, 0xffL, +}; +static final long[] jjtoSkip = { + 0xebfeL, 0x0L, 0x0L, +}; +static final long[] jjtoMore = { + 0x71400L, 0x0L, 0x0L, +}; +static protected SimpleCharStream input_stream; +static private final int[] jjrounds = new int[78]; +static private final int[] jjstateSet = new int[156]; +static protected char curChar; +/** Constructor. */ +public CPPParserTokenManager(SimpleCharStream stream){ + if (input_stream != null) + throw new TokenMgrError("ERROR: Second call to constructor of static lexer. You must use ReInit() to initialize the static variables.", TokenMgrError.STATIC_LEXER_ERROR); + input_stream = stream; +} + +/** Constructor. */ +public CPPParserTokenManager(SimpleCharStream stream, int lexState){ + this(stream); + SwitchTo(lexState); +} + +/** Reinitialise parser. */ +static public void ReInit(SimpleCharStream stream) +{ + jjmatchedPos = jjnewStateCnt = 0; + curLexState = defaultLexState; + input_stream = stream; + ReInitRounds(); +} +static private void ReInitRounds() +{ + int i; + jjround = 0x80000001; + for (i = 78; i-- > 0;) + jjrounds[i] = 0x80000000; +} + +/** Reinitialise parser. */ +static public void ReInit(SimpleCharStream stream, int lexState) +{ + ReInit(stream); + SwitchTo(lexState); +} + +/** Switch to specified lex state. */ +static public void SwitchTo(int lexState) +{ + if (lexState >= 5 || lexState < 0) + throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE); + else + curLexState = lexState; +} + +static protected Token jjFillToken() +{ + final Token t; + final String curTokenImage; + final int beginLine; + final int endLine; + final int beginColumn; + final int endColumn; + String im = jjstrLiteralImages[jjmatchedKind]; + curTokenImage = (im == null) ? input_stream.GetImage() : im; + beginLine = input_stream.getBeginLine(); + beginColumn = input_stream.getBeginColumn(); + endLine = input_stream.getEndLine(); + endColumn = input_stream.getEndColumn(); + t = Token.newToken(jjmatchedKind, curTokenImage); + + t.beginLine = beginLine; + t.endLine = endLine; + t.beginColumn = beginColumn; + t.endColumn = endColumn; + + return t; +} + +static int curLexState = 0; +static int defaultLexState = 0; +static int jjnewStateCnt; +static int jjround; +static int jjmatchedPos; +static int jjmatchedKind; + +/** Get the next Token. */ +public static Token getNextToken() +{ + Token matchedToken; + int curPos = 0; + + EOFLoop : + for (;;) + { + try + { + curChar = input_stream.BeginToken(); + } + catch(java.io.IOException e) + { + jjmatchedKind = 0; + matchedToken = jjFillToken(); + return matchedToken; + } + + for (;;) + { + switch(curLexState) + { + case 0: + try { input_stream.backup(0); + while (curChar <= 32 && (0x100001600L & (1L << curChar)) != 0L) + curChar = input_stream.BeginToken(); + } + catch (java.io.IOException e1) { continue EOFLoop; } + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_0(); + break; + case 1: + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_1(); + if (jjmatchedPos == 0 && jjmatchedKind > 10) + { + jjmatchedKind = 10; + } + break; + case 2: + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_2(); + if (jjmatchedPos == 0 && jjmatchedKind > 12) + { + jjmatchedKind = 12; + } + break; + case 3: + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_3(); + if (jjmatchedPos == 0 && jjmatchedKind > 12) + { + jjmatchedKind = 12; + } + break; + case 4: + jjmatchedKind = 0x7fffffff; + jjmatchedPos = 0; + curPos = jjMoveStringLiteralDfa0_4(); + if (jjmatchedPos == 0 && jjmatchedKind > 18) + { + jjmatchedKind = 18; + } + break; + } + if (jjmatchedKind != 0x7fffffff) + { + if (jjmatchedPos + 1 < curPos) + input_stream.backup(curPos - jjmatchedPos - 1); + if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) + { + matchedToken = jjFillToken(); + if (jjnewLexState[jjmatchedKind] != -1) + curLexState = jjnewLexState[jjmatchedKind]; + return matchedToken; + } + else if ((jjtoSkip[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L) + { + if (jjnewLexState[jjmatchedKind] != -1) + curLexState = jjnewLexState[jjmatchedKind]; + continue EOFLoop; + } + if (jjnewLexState[jjmatchedKind] != -1) + curLexState = jjnewLexState[jjmatchedKind]; + curPos = 0; + jjmatchedKind = 0x7fffffff; + try { + curChar = input_stream.readChar(); + continue; + } + catch (java.io.IOException e1) { } + } + int error_line = input_stream.getEndLine(); + int error_column = input_stream.getEndColumn(); + String error_after = null; + boolean EOFSeen = false; + try { input_stream.readChar(); input_stream.backup(1); } + catch (java.io.IOException e1) { + EOFSeen = true; + error_after = curPos <= 1 ? "" : input_stream.GetImage(); + if (curChar == '\n' || curChar == '\r') { + error_line++; + error_column = 0; + } + else + error_column++; + } + if (!EOFSeen) { + input_stream.backup(1); + error_after = curPos <= 1 ? "" : input_stream.GetImage(); + } + throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR); + } + } +} + +static private void jjCheckNAdd(int state) +{ + if (jjrounds[state] != jjround) + { + jjstateSet[jjnewStateCnt++] = state; + jjrounds[state] = jjround; + } +} +static private void jjAddStates(int start, int end) +{ + do { + jjstateSet[jjnewStateCnt++] = jjnextStates[start]; + } while (start++ != end); +} +static private void jjCheckNAddTwoStates(int state1, int state2) +{ + jjCheckNAdd(state1); + jjCheckNAdd(state2); +} + +static private void jjCheckNAddStates(int start, int end) +{ + do { + jjCheckNAdd(jjnextStates[start]); + } while (start++ != end); +} + +} diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/ParseException.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/ParseException.java new file mode 100644 index 00000000000..cc7d6e24f28 --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/ParseException.java @@ -0,0 +1,198 @@ +/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 4.1 */ +/* JavaCCOptions:KEEP_LINE_COL=null */ +package net.sourceforge.pmd.cpd.cppast; + +/** + * This exception is thrown when parse errors are encountered. + * You can explicitly create objects of this exception type by + * calling the method generateParseException in the generated + * parser. + * + * You can modify this class to customize your error reporting + * mechanisms so long as you retain the public fields. + */ +public class ParseException extends RuntimeException { + + /** + * This constructor is used by the method "generateParseException" + * in the generated parser. Calling this constructor generates + * a new object of this type with the fields "currentToken", + * "expectedTokenSequences", and "tokenImage" set. The boolean + * flag "specialConstructor" is also set to true to indicate that + * this constructor was used to create this object. + * This constructor calls its super class with the empty string + * to force the "toString" method of parent class "Throwable" to + * print the error message in the form: + * ParseException: <result of getMessage> + */ + public ParseException(Token currentTokenVal, + int[][] expectedTokenSequencesVal, + String[] tokenImageVal + ) + { + super(""); + specialConstructor = true; + currentToken = currentTokenVal; + expectedTokenSequences = expectedTokenSequencesVal; + tokenImage = tokenImageVal; + } + + /** + * The following constructors are for use by you for whatever + * purpose you can think of. Constructing the exception in this + * manner makes the exception behave in the normal way - i.e., as + * documented in the class "Throwable". The fields "errorToken", + * "expectedTokenSequences", and "tokenImage" do not contain + * relevant information. The JavaCC generated code does not use + * these constructors. + */ + + public ParseException() { + super(); + specialConstructor = false; + } + + /** Constructor with message. */ + public ParseException(String message) { + super(message); + specialConstructor = false; + } + + /** + * This variable determines which constructor was used to create + * this object and thereby affects the semantics of the + * "getMessage" method (see below). + */ + protected boolean specialConstructor; + + /** + * This is the last token that has been consumed successfully. If + * this object has been created due to a parse error, the token + * followng this token will (therefore) be the first error token. + */ + public Token currentToken; + + /** + * Each entry in this array is an array of integers. Each array + * of integers represents a sequence of tokens (by their ordinal + * values) that is expected at this point of the parse. + */ + public int[][] expectedTokenSequences; + + /** + * This is a reference to the "tokenImage" array of the generated + * parser within which the parse error occurred. This array is + * defined in the generated ...Constants interface. + */ + public String[] tokenImage; + + /** + * This method has the standard behavior when this object has been + * created using the standard constructors. Otherwise, it uses + * "currentToken" and "expectedTokenSequences" to generate a parse + * error message and returns it. If this object has been created + * due to a parse error, and you do not catch it (it gets thrown + * from the parser), then this method is called during the printing + * of the final stack trace, and hence the correct error message + * gets displayed. + */ + public String getMessage() { + if (!specialConstructor) { + return super.getMessage(); + } + StringBuffer expected = new StringBuffer(); + int maxSize = 0; + for (int i = 0; i < expectedTokenSequences.length; i++) { + if (maxSize < expectedTokenSequences[i].length) { + maxSize = expectedTokenSequences[i].length; + } + for (int j = 0; j < expectedTokenSequences[i].length; j++) { + expected.append(tokenImage[expectedTokenSequences[i][j]]).append(' '); + } + if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) { + expected.append("..."); + } + expected.append(eol).append(" "); + } + String retval = "Encountered \""; + Token tok = currentToken.next; + for (int i = 0; i < maxSize; i++) { + if (i != 0) retval += " "; + if (tok.kind == 0) { + retval += tokenImage[0]; + break; + } + retval += " " + tokenImage[tok.kind]; + retval += " \""; + retval += add_escapes(tok.image); + retval += " \""; + tok = tok.next; + } + retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn; + retval += "." + eol; + if (expectedTokenSequences.length == 1) { + retval += "Was expecting:" + eol + " "; + } else { + retval += "Was expecting one of:" + eol + " "; + } + retval += expected.toString(); + return retval; + } + + /** + * The end of line string for this machine. + */ + protected String eol = System.getProperty("line.separator", "\n"); + + /** + * Used to convert raw characters to their escaped version + * when these raw version cannot be used as part of an ASCII + * string literal. + */ + protected String add_escapes(String str) { + StringBuffer retval = new StringBuffer(); + char ch; + for (int i = 0; i < str.length(); i++) { + switch (str.charAt(i)) + { + case 0 : + continue; + case '\b': + retval.append("\\b"); + continue; + case '\t': + retval.append("\\t"); + continue; + case '\n': + retval.append("\\n"); + continue; + case '\f': + retval.append("\\f"); + continue; + case '\r': + retval.append("\\r"); + continue; + case '\"': + retval.append("\\\""); + continue; + case '\'': + retval.append("\\\'"); + continue; + case '\\': + retval.append("\\\\"); + continue; + default: + if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { + String s = "0000" + Integer.toString(ch, 16); + retval.append("\\u" + s.substring(s.length() - 4, s.length())); + } else { + retval.append(ch); + } + continue; + } + } + return retval.toString(); + } + +} +/* JavaCC - OriginalChecksum=8b42f597f21215eb130252440c369111 (do not edit this line) */ diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/SimpleCharStream.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/SimpleCharStream.java new file mode 100644 index 00000000000..92464e2280d --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/SimpleCharStream.java @@ -0,0 +1,476 @@ +/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 4.1 */ +/* JavaCCOptions:STATIC=true */ +package net.sourceforge.pmd.cpd.cppast; + +/** + * An implementation of interface CharStream, where the stream is assumed to + * contain only ASCII characters (without unicode processing). + */ + +public class SimpleCharStream +{ +/** Whether parser is static. */ + public static final boolean staticFlag = true; + static int bufsize; + static int available; + static int tokenBegin; +/** Position in buffer. */ + static public int bufpos = -1; + static protected int bufline[]; + static protected int bufcolumn[]; + + static protected int column = 0; + static protected int line = 1; + + static protected boolean prevCharIsCR = false; + static protected boolean prevCharIsLF = false; + + static protected java.io.Reader inputStream; + + static protected char[] buffer; + static protected int maxNextCharInd = 0; + static protected int inBuf = 0; + static protected int tabSize = 8; + + static protected void setTabSize(int i) { tabSize = i; } + static protected int getTabSize(int i) { return tabSize; } + + + static protected void ExpandBuff(boolean wrapAround) + { + char[] newbuffer = new char[bufsize + 2048]; + int newbufline[] = new int[bufsize + 2048]; + int newbufcolumn[] = new int[bufsize + 2048]; + + try + { + if (wrapAround) + { + System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); + System.arraycopy(buffer, 0, newbuffer, + bufsize - tokenBegin, bufpos); + buffer = newbuffer; + + System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); + System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos); + bufline = newbufline; + + System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); + System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos); + bufcolumn = newbufcolumn; + + maxNextCharInd = (bufpos += (bufsize - tokenBegin)); + } + else + { + System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin); + buffer = newbuffer; + + System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin); + bufline = newbufline; + + System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin); + bufcolumn = newbufcolumn; + + maxNextCharInd = (bufpos -= tokenBegin); + } + } + catch (Throwable t) + { + throw new Error(t.getMessage()); + } + + + bufsize += 2048; + available = bufsize; + tokenBegin = 0; + } + + static protected void FillBuff() throws java.io.IOException + { + if (maxNextCharInd == available) + { + if (available == bufsize) + { + if (tokenBegin > 2048) + { + bufpos = maxNextCharInd = 0; + available = tokenBegin; + } + else if (tokenBegin < 0) + bufpos = maxNextCharInd = 0; + else + ExpandBuff(false); + } + else if (available > tokenBegin) + available = bufsize; + else if ((tokenBegin - available) < 2048) + ExpandBuff(true); + else + available = tokenBegin; + } + + int i; + try { + if ((i = inputStream.read(buffer, maxNextCharInd, + available - maxNextCharInd)) == -1) + { + inputStream.close(); + throw new java.io.IOException(); + } + else + maxNextCharInd += i; + return; + } + catch(java.io.IOException e) { + --bufpos; + backup(0); + if (tokenBegin == -1) + tokenBegin = bufpos; + throw e; + } + } + +/** Start. */ + static public char BeginToken() throws java.io.IOException + { + tokenBegin = -1; + char c = readChar(); + tokenBegin = bufpos; + + return c; + } + + static protected void UpdateLineColumn(char c) + { + column++; + + if (prevCharIsLF) + { + prevCharIsLF = false; + line += (column = 1); + } + else if (prevCharIsCR) + { + prevCharIsCR = false; + if (c == '\n') + { + prevCharIsLF = true; + } + else + line += (column = 1); + } + + switch (c) + { + case '\r' : + prevCharIsCR = true; + break; + case '\n' : + prevCharIsLF = true; + break; + case '\t' : + column--; + column += (tabSize - (column % tabSize)); + break; + default : + break; + } + + bufline[bufpos] = line; + bufcolumn[bufpos] = column; + } + +/** Read a character. */ + static public char readChar() throws java.io.IOException + { + if (inBuf > 0) + { + --inBuf; + + if (++bufpos == bufsize) + bufpos = 0; + + return buffer[bufpos]; + } + + if (++bufpos >= maxNextCharInd) + FillBuff(); + + char c = buffer[bufpos]; + + UpdateLineColumn(c); + return c; + } + + /** + * @deprecated + * @see #getEndColumn + */ + + static public int getColumn() { + return bufcolumn[bufpos]; + } + + /** + * @deprecated + * @see #getEndLine + */ + + static public int getLine() { + return bufline[bufpos]; + } + + /** Get token end column number. */ + static public int getEndColumn() { + return bufcolumn[bufpos]; + } + + /** Get token end line number. */ + static public int getEndLine() { + return bufline[bufpos]; + } + + /** Get token beginning column number. */ + static public int getBeginColumn() { + return bufcolumn[tokenBegin]; + } + + /** Get token beginning line number. */ + static public int getBeginLine() { + return bufline[tokenBegin]; + } + +/** Backup a number of characters. */ + static public void backup(int amount) { + + inBuf += amount; + if ((bufpos -= amount) < 0) + bufpos += bufsize; + } + + /** Constructor. */ + public SimpleCharStream(java.io.Reader dstream, int startline, + int startcolumn, int buffersize) + { + if (inputStream != null) + throw new Error("\n ERROR: Second call to the constructor of a static SimpleCharStream.\n" + + " You must either use ReInit() or set the JavaCC option STATIC to false\n" + + " during the generation of this class."); + inputStream = dstream; + line = startline; + column = startcolumn - 1; + + available = bufsize = buffersize; + buffer = new char[buffersize]; + bufline = new int[buffersize]; + bufcolumn = new int[buffersize]; + } + + /** Constructor. */ + public SimpleCharStream(java.io.Reader dstream, int startline, + int startcolumn) + { + this(dstream, startline, startcolumn, 4096); + } + + /** Constructor. */ + public SimpleCharStream(java.io.Reader dstream) + { + this(dstream, 1, 1, 4096); + } + + /** Reinitialise. */ + public void ReInit(java.io.Reader dstream, int startline, + int startcolumn, int buffersize) + { + inputStream = dstream; + line = startline; + column = startcolumn - 1; + + if (buffer == null || buffersize != buffer.length) + { + available = bufsize = buffersize; + buffer = new char[buffersize]; + bufline = new int[buffersize]; + bufcolumn = new int[buffersize]; + } + prevCharIsLF = prevCharIsCR = false; + tokenBegin = inBuf = maxNextCharInd = 0; + bufpos = -1; + } + + /** Reinitialise. */ + public void ReInit(java.io.Reader dstream, int startline, + int startcolumn) + { + ReInit(dstream, startline, startcolumn, 4096); + } + + /** Reinitialise. */ + public void ReInit(java.io.Reader dstream) + { + ReInit(dstream, 1, 1, 4096); + } + /** Constructor. */ + public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline, + int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException + { + this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); + } + + /** Constructor. */ + public SimpleCharStream(java.io.InputStream dstream, int startline, + int startcolumn, int buffersize) + { + this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); + } + + /** Constructor. */ + public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline, + int startcolumn) throws java.io.UnsupportedEncodingException + { + this(dstream, encoding, startline, startcolumn, 4096); + } + + /** Constructor. */ + public SimpleCharStream(java.io.InputStream dstream, int startline, + int startcolumn) + { + this(dstream, startline, startcolumn, 4096); + } + + /** Constructor. */ + public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException + { + this(dstream, encoding, 1, 1, 4096); + } + + /** Constructor. */ + public SimpleCharStream(java.io.InputStream dstream) + { + this(dstream, 1, 1, 4096); + } + + /** Reinitialise. */ + public void ReInit(java.io.InputStream dstream, String encoding, int startline, + int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException + { + ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize); + } + + /** Reinitialise. */ + public void ReInit(java.io.InputStream dstream, int startline, + int startcolumn, int buffersize) + { + ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize); + } + + /** Reinitialise. */ + public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException + { + ReInit(dstream, encoding, 1, 1, 4096); + } + + /** Reinitialise. */ + public void ReInit(java.io.InputStream dstream) + { + ReInit(dstream, 1, 1, 4096); + } + /** Reinitialise. */ + public void ReInit(java.io.InputStream dstream, String encoding, int startline, + int startcolumn) throws java.io.UnsupportedEncodingException + { + ReInit(dstream, encoding, startline, startcolumn, 4096); + } + /** Reinitialise. */ + public void ReInit(java.io.InputStream dstream, int startline, + int startcolumn) + { + ReInit(dstream, startline, startcolumn, 4096); + } + /** Get token literal value. */ + static public String GetImage() + { + if (bufpos >= tokenBegin) + return new String(buffer, tokenBegin, bufpos - tokenBegin + 1); + else + return new String(buffer, tokenBegin, bufsize - tokenBegin) + + new String(buffer, 0, bufpos + 1); + } + + /** Get the suffix. */ + static public char[] GetSuffix(int len) + { + char[] ret = new char[len]; + + if ((bufpos + 1) >= len) + System.arraycopy(buffer, bufpos - len + 1, ret, 0, len); + else + { + System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0, + len - bufpos - 1); + System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1); + } + + return ret; + } + + /** Reset buffer when finished. */ + static public void Done() + { + buffer = null; + bufline = null; + bufcolumn = null; + } + + /** + * Method to adjust line and column numbers for the start of a token. + */ + static public void adjustBeginLineColumn(int newLine, int newCol) + { + int start = tokenBegin; + int len; + + if (bufpos >= tokenBegin) + { + len = bufpos - tokenBegin + inBuf + 1; + } + else + { + len = bufsize - tokenBegin + bufpos + 1 + inBuf; + } + + int i = 0, j = 0, k = 0; + int nextColDiff = 0, columnDiff = 0; + + while (i < len && + bufline[j = start % bufsize] == bufline[k = ++start % bufsize]) + { + bufline[j] = newLine; + nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j]; + bufcolumn[j] = newCol + columnDiff; + columnDiff = nextColDiff; + i++; + } + + if (i < len) + { + bufline[j] = newLine++; + bufcolumn[j] = newCol + columnDiff; + + while (i++ < len) + { + if (bufline[j = start % bufsize] != bufline[++start % bufsize]) + bufline[j] = newLine++; + else + bufline[j] = newLine; + } + } + + line = bufline[j]; + column = bufcolumn[j]; + } + +} +/* JavaCC - OriginalChecksum=9bbb8cb4295bb8f7d58e31ce57dc2e0f (do not edit this line) */ diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/Token.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/Token.java new file mode 100644 index 00000000000..59cf8faec5e --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/Token.java @@ -0,0 +1,124 @@ +/* Generated By:JavaCC: Do not edit this line. Token.java Version 4.1 */ +/* JavaCCOptions:TOKEN_EXTENDS=,KEEP_LINE_COL=null */ +package net.sourceforge.pmd.cpd.cppast; + +/** + * Describes the input token stream. + */ + +public class Token { + + /** + * An integer that describes the kind of this token. This numbering + * system is determined by JavaCCParser, and a table of these numbers is + * stored in the file ...Constants.java. + */ + public int kind; + + /** The line number of the first character of this Token. */ + public int beginLine; + /** The column number of the first character of this Token. */ + public int beginColumn; + /** The line number of the last character of this Token. */ + public int endLine; + /** The column number of the last character of this Token. */ + public int endColumn; + + /** + * The string image of the token. + */ + public String image; + + /** + * A reference to the next regular (non-special) token from the input + * stream. If this is the last token from the input stream, or if the + * token manager has not read tokens beyond this one, this field is + * set to null. This is true only if this token is also a regular + * token. Otherwise, see below for a description of the contents of + * this field. + */ + public Token next; + + /** + * This field is used to access special tokens that occur prior to this + * token, but after the immediately preceding regular (non-special) token. + * If there are no such special tokens, this field is set to null. + * When there are more than one such special token, this field refers + * to the last of these special tokens, which in turn refers to the next + * previous special token through its specialToken field, and so on + * until the first special token (whose specialToken field is null). + * The next fields of special tokens refer to other special tokens that + * immediately follow it (without an intervening regular token). If there + * is no such token, this field is null. + */ + public Token specialToken; + + /** + * An optional attribute value of the Token. + * Tokens which are not used as syntactic sugar will often contain + * meaningful values that will be used later on by the compiler or + * interpreter. This attribute value is often different from the image. + * Any subclass of Token that actually wants to return a non-null value can + * override this method as appropriate. + */ + public Object getValue() { + return null; + } + + /** + * No-argument constructor + */ + public Token() {} + + /** + * Constructs a new token for the specified Image. + */ + public Token(int kind) + { + this(kind, null); + } + + /** + * Constructs a new token for the specified Image and Kind. + */ + public Token(int kind, String image) + { + this.kind = kind; + this.image = image; + } + + /** + * Returns the image. + */ + public String toString() + { + return image; + } + + /** + * Returns a new Token object, by default. However, if you want, you + * can create and return subclass objects based on the value of ofKind. + * Simply add the cases to the switch for all those special cases. + * For example, if you have a subclass of Token called IDToken that + * you want to create if ofKind is ID, simply add something like : + * + * case MyParserConstants.ID : return new IDToken(ofKind, image); + * + * to the following switch statement. Then you can cast matchedToken + * variable to the appropriate type and use sit in your lexical actions. + */ + public static Token newToken(int ofKind, String image) + { + switch(ofKind) + { + default : return new Token(ofKind, image); + } + } + + public static Token newToken(int ofKind) + { + return newToken(ofKind, null); + } + +} +/* JavaCC - OriginalChecksum=1917659c640ac2c65feaa32a37580421 (do not edit this line) */ diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/TokenMgrError.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/TokenMgrError.java new file mode 100644 index 00000000000..8a705c407ec --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/cpd/cppast/TokenMgrError.java @@ -0,0 +1,140 @@ +/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 4.1 */ +/* JavaCCOptions: */ +package net.sourceforge.pmd.cpd.cppast; + +/** Token Manager Error. */ +public class TokenMgrError extends Error +{ + + /* + * Ordinals for various reasons why an Error of this type can be thrown. + */ + + /** + * Lexical error occurred. + */ + static final int LEXICAL_ERROR = 0; + + /** + * An attempt was made to create a second instance of a static token manager. + */ + static final int STATIC_LEXER_ERROR = 1; + + /** + * Tried to change to an invalid lexical state. + */ + static final int INVALID_LEXICAL_STATE = 2; + + /** + * Detected (and bailed out of) an infinite loop in the token manager. + */ + static final int LOOP_DETECTED = 3; + + /** + * Indicates the reason why the exception is thrown. It will have + * one of the above 4 values. + */ + int errorCode; + + /** + * Replaces unprintable characters by their escaped (or unicode escaped) + * equivalents in the given string + */ + protected static final String addEscapes(String str) { + StringBuffer retval = new StringBuffer(); + char ch; + for (int i = 0; i < str.length(); i++) { + switch (str.charAt(i)) + { + case 0 : + continue; + case '\b': + retval.append("\\b"); + continue; + case '\t': + retval.append("\\t"); + continue; + case '\n': + retval.append("\\n"); + continue; + case '\f': + retval.append("\\f"); + continue; + case '\r': + retval.append("\\r"); + continue; + case '\"': + retval.append("\\\""); + continue; + case '\'': + retval.append("\\\'"); + continue; + case '\\': + retval.append("\\\\"); + continue; + default: + if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) { + String s = "0000" + Integer.toString(ch, 16); + retval.append("\\u" + s.substring(s.length() - 4, s.length())); + } else { + retval.append(ch); + } + continue; + } + } + return retval.toString(); + } + + /** + * Returns a detailed message for the Error when it is thrown by the + * token manager to indicate a lexical error. + * Parameters : + * EOFSeen : indicates if EOF caused the lexical error + * curLexState : lexical state in which this error occurred + * errorLine : line number when the error occurred + * errorColumn : column number when the error occurred + * errorAfter : prefix that was seen before this error occurred + * curchar : the offending character + * Note: You can customize the lexical error message by modifying this method. + */ + protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) { + return("Lexical error in file " + CPPParserTokenManager.getFileName() + " at line " + + errorLine + ", column " + + errorColumn + ". Encountered: " + + (EOFSeen ? "<EOF> " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") + + "after : \"" + addEscapes(errorAfter) + "\""); + } + + /** + * You can also modify the body of this method to customize your error messages. + * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not + * of end-users concern, so you can return something like : + * + * "Internal Error : Please file a bug report .... " + * + * from this method for such cases in the release version of your parser. + */ + public String getMessage() { + return super.getMessage(); + } + + /* + * Constructors of various flavors follow. + */ + + /** No arg constructor. */ + public TokenMgrError() { + } + + /** Constructor with message and reason. */ + public TokenMgrError(String message, int reason) { + super(message); + errorCode = reason; + } + + /** Full Constructor. */ + public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) { + this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason); + } +} +/* JavaCC - OriginalChecksum=7925b33c412b4bfa3a7147ae3e790276 (do not edit this line) */ diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/util/FileFinder.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/FileFinder.java new file mode 100644 index 00000000000..d07b32112a9 --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/FileFinder.java @@ -0,0 +1,42 @@ +package net.sourceforge.pmd.util;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A utility class for finding files within a directory.
+ */
+public class FileFinder {
+
+ private FilenameFilter filter;
+ private static final String FILE_SEP = System.getProperty("file.separator");
+
+ public List<File> findFilesFrom(String dir, FilenameFilter filter, boolean recurse) {
+ this.filter = filter;
+ List<File> files = new ArrayList<File>();
+ scanDirectory(new File(dir), files, recurse);
+ return files;
+ }
+
+ /**
+ * Implements a tail recursive file scanner
+ */
+ private void scanDirectory(File dir, List<File> list, boolean recurse) {
+ String[] candidates = dir.list(filter);
+ if (candidates == null) {
+ return;
+ }
+ for (int i = 0; i < candidates.length; i++) {
+ File tmp = new File(dir + FILE_SEP + candidates[i]);
+ if (tmp.isDirectory()) {
+ if (recurse) {
+ scanDirectory(tmp, list, true);
+ }
+ } else {
+ list.add(new File(dir + FILE_SEP + candidates[i]));
+ }
+ }
+ }
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/util/StringUtil.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/StringUtil.java new file mode 100644 index 00000000000..bfb2f65855a --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/StringUtil.java @@ -0,0 +1,310 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ +package net.sourceforge.pmd.util; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class StringUtil { + + public static final String[] EMPTY_STRINGS = new String[0]; + private static final boolean supportsUTF8 = System.getProperty("net.sourceforge.pmd.supportUTF8", "no").equals("yes"); + private static final String[] ENTITIES; + + static { + ENTITIES = new String[256 - 126]; + for (int i = 126; i <= 255; i++) { + ENTITIES[i - 126] = "&#" + i + ';'; + } + } + + public static String replaceString(String original, char oldChar, String newString) { + + String fixedNew = newString == null ? "" : newString; + + StringBuffer desc = new StringBuffer(); + int index = original.indexOf(oldChar); + int last = 0; + while (index != -1) { + desc.append(original.substring(last, index)); + desc.append(fixedNew); + last = index + 1; + index = original.indexOf(oldChar, last); + } + desc.append(original.substring(last)); + return desc.toString(); + } + + public static String replaceString(String original, String oldString, String newString) { + + String fixedNew = newString == null ? "" : newString; + + StringBuffer desc = new StringBuffer(); + int index = original.indexOf(oldString); + int last = 0; + while (index != -1) { + desc.append(original.substring(last, index)); + desc.append(fixedNew); + last = index + oldString.length(); + index = original.indexOf(oldString, last); + } + desc.append(original.substring(last)); + return desc.toString(); + } + + /** + * Appends to a StringBuffer the String src where non-ASCII and + * XML special chars are escaped. + * + * @param buf The destination XML stream + * @param src The String to append to the stream + */ + public static void appendXmlEscaped(StringBuffer buf, String src) { + appendXmlEscaped(buf, src, supportsUTF8); + } + + public static String htmlEncode(String string) { + String encoded = StringUtil.replaceString(string, '&', "&"); + encoded = StringUtil.replaceString(encoded, '<', "<"); + return StringUtil.replaceString(encoded, '>', ">"); + } + + // TODO - unify the method above with the one below + + private static void appendXmlEscaped(StringBuffer buf, String src, boolean supportUTF8) { + char c; + for (int i = 0; i < src.length(); i++) { + c = src.charAt(i); + if (c > '~') {// 126 + if (!supportUTF8) { + if (c <= 255) { + buf.append(ENTITIES[c - 126]); + } else { + buf.append("&u").append(Integer.toHexString(c)).append(';'); + } + } else { + buf.append(c); + } + } else if (c == '&') + buf.append("&"); + else if (c == '"') + buf.append("""); + else if (c == '<') + buf.append("<"); + else if (c == '>') + buf.append(">"); + else + buf.append(c); + } + } + + /** + * Parses the input source using the delimiter specified. This method is much + * faster than using the StringTokenizer or String.split(char) approach and + * serves as a replacement for String.split() for JDK1.3 that doesn't have it. + * + * FIXME - we're on JDK 1.4 now, can we replace this with String.split? + * + * @param source String + * @param delimiter char + * @return String[] + */ + public static String[] substringsOf(String source, char delimiter) { + + if (source == null || source.length() == 0) { + return EMPTY_STRINGS; + } + + int delimiterCount = 0; + int length = source.length(); + char[] chars = source.toCharArray(); + + for (int i=0; i<length; i++) { + if (chars[i] == delimiter) delimiterCount++; + } + + if (delimiterCount == 0) return new String[] { source }; + + String results[] = new String[delimiterCount+1]; + + int i = 0; + int offset = 0; + + while (offset <= length) { + int pos = source.indexOf(delimiter, offset); + if (pos < 0) pos = length; + results[i++] = pos == offset ? "" : source.substring(offset, pos); + offset = pos + 1; + } + + return results; + } + + /** + * Much more efficient than StringTokenizer. + * + * @param str String + * @param separator char + * @return String[] + */ + public static String[] substringsOf(String str, String separator) { + + if (str == null || str.length() == 0) { + return EMPTY_STRINGS; + } + + int index = str.indexOf(separator); + if (index == -1) { + return new String[]{str}; + } + + List<String> list = new ArrayList<String>(); + int currPos = 0; + int len = separator.length(); + while (index != -1) { + list.add(str.substring(currPos, index)); + currPos = index + len; + index = str.indexOf(separator, currPos); + } + list.add(str.substring(currPos)); + return list.toArray(new String[list.size()]); + } + + + /** + * Copies the elements returned by the iterator onto the string buffer + * each delimited by the separator. + * + * @param sb StringBuffer + * @param iter Iterator + * @param separator String + */ + public static void asStringOn(StringBuffer sb, Iterator iter, String separator) { + + if (!iter.hasNext()) return; + + sb.append(iter.next()); + + while (iter.hasNext()) { + sb.append(separator); + sb.append(iter.next()); + } + } + /** + * Return the length of the shortest string in the array. + * If any one of them is null then it returns 0. + * + * @param strings String[] + * @return int + */ + public static int lengthOfShortestIn(String[] strings) { + + int minLength = Integer.MAX_VALUE; + + for (int i=0; i<strings.length; i++) { + if (strings[i] == null) return 0; + minLength = Math.min(minLength, strings[i].length()); + } + + return minLength; + } + + /** + * Determine the maximum number of common leading whitespace characters + * the strings share in the same sequence. Useful for determining how + * many leading characters can be removed to shift all the text in the + * strings to the left without misaligning them. + * + * @param strings String[] + * @return int + */ + public static int maxCommonLeadingWhitespaceForAll(String[] strings) { + + int shortest = lengthOfShortestIn(strings); + if (shortest == 0) return 0; + + char[] matches = new char[shortest]; + + String str; + for (int m=0; m<matches.length; m++) { + matches[m] = strings[0].charAt(m); + if (!Character.isWhitespace(matches[m])) return m; + for (int i=0; i<strings.length; i++) { + str = strings[i]; + if (str.charAt(m) != matches[m]) return m; + } + } + + return shortest; + } + + /** + * Trims off the leading characters off the strings up to the trimDepth + * specified. Returns the same strings if trimDepth = 0 + * + * @param strings + * @param trimDepth + * @return String[] + */ + public static String[] trimStartOn(String[] strings, int trimDepth) { + + if (trimDepth == 0) return strings; + + String[] results = new String[strings.length]; + for (int i=0; i<strings.length; i++) { + results[i] = strings[i].substring(trimDepth); + } + return results; + } + + /** + * Left pads a string. + * @param s The String to pad + * @param length The desired minimum length of the resulting padded String + * @return The resulting left padded String + */ + public static String lpad(String s, int length) { + String res = s; + if (length - s.length() > 0) { + char [] arr = new char[length - s.length()]; + java.util.Arrays.fill(arr, ' '); + res = new StringBuffer(length).append(arr).append(s).toString(); + } + return res; + } + + /** + * Are the two String values the same. + * The Strings can be optionally trimmed before checking. + * The Strings can be optionally compared ignoring case. + * The Strings can be have embedded whitespace standardized before comparing. + * Two null values are treated as equal. + * + * @param s1 The first String. + * @param s2 The second String. + * @param trim Indicates if the Strings should be trimmed before comparison. + * @param ignoreCase Indicates if the case of the Strings should ignored during comparison. + * @param standardizeWhitespace Indicates if the embedded whitespace should be standardized before comparison. + * @return <code>true</code> if the Strings are the same, <code>false</code> otherwise. + */ + public static boolean isSame(String s1, String s2, boolean trim, boolean ignoreCase, boolean standardizeWhitespace) { + if (s1 == s2) { + return true; + } else if (s1 == null || s2 == null) { + return false; + } else { + if (trim) { + s1 = s1.trim(); + s2 = s2.trim(); + } + if (standardizeWhitespace) { + // Replace all whitespace with a standard single space character. + s1 = s1.replaceAll("\\s+", " "); + s2 = s2.replaceAll("\\s+", " "); + } + return ignoreCase ? s1.equalsIgnoreCase(s2) : s1.equals(s2); + } + } +} diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/AbstractCompoundFilter.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/AbstractCompoundFilter.java new file mode 100644 index 00000000000..01d6e66573b --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/AbstractCompoundFilter.java @@ -0,0 +1,56 @@ +package net.sourceforge.pmd.util.filter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A base class for Filters which implements behavior using a List of other
+ * Filters.
+ *
+ * @param <T>
+ * The underlying type on which the filter applies.
+ */
+public abstract class AbstractCompoundFilter<T> implements Filter<T> {
+
+ protected List<Filter<T>> filters;
+
+ public AbstractCompoundFilter() {
+ filters = new ArrayList<Filter<T>>(2);
+ }
+
+ public AbstractCompoundFilter(Filter<T>... filters) {
+ this.filters = new ArrayList<Filter<T>>(filters.length);
+ for (Filter<T> filter : filters) {
+ this.filters.add(filter);
+ }
+ }
+
+ public List<Filter<T>> getFilters() {
+ return filters;
+ }
+
+ public void setFilters(List<Filter<T>> filters) {
+ this.filters = filters;
+ }
+
+ public void addFilter(Filter<T> filter) {
+ filters.add(filter);
+ }
+
+ protected abstract String getOperator();
+
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("(");
+ for (int i = 0; i < filters.size(); i++) {
+ if (i > 0) {
+ builder.append(" ");
+ builder.append(getOperator());
+ builder.append(" ");
+ }
+ builder.append(filters.get(i));
+ }
+ builder.append(")");
+ return builder.toString();
+ }
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/AbstractDelegateFilter.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/AbstractDelegateFilter.java new file mode 100644 index 00000000000..f55c9c68d6f --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/AbstractDelegateFilter.java @@ -0,0 +1,37 @@ +package net.sourceforge.pmd.util.filter;
+
+/**
+ * A base class for Filters which implements behavior using delegation
+ * to an underlying filter.
+ *
+ * @param <T>
+ * The underlying type on which the filter applies.
+ */
+public abstract class AbstractDelegateFilter<T> implements Filter<T> {
+ protected Filter<T> filter;
+
+ public AbstractDelegateFilter() {
+ }
+
+ public AbstractDelegateFilter(Filter<T> filter) {
+ this.filter = filter;
+ }
+
+ public Filter<T> getFilter() {
+ return filter;
+ }
+
+ public void setFilter(Filter<T> filter) {
+ this.filter = filter;
+ }
+
+ // Subclass should override to do something other the simply delegate.
+ public boolean filter(T obj) {
+ return filter.filter(obj);
+ }
+
+ // Subclass should override to do something other the simply delegate.
+ public String toString() {
+ return filter.toString();
+ }
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/AndFilter.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/AndFilter.java new file mode 100644 index 00000000000..d2e29b9e8a8 --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/AndFilter.java @@ -0,0 +1,34 @@ +package net.sourceforge.pmd.util.filter;
+
+/**
+ * A logical AND of a list of Filters. This implementation is short circuiting.
+ *
+ * @param <T>
+ * The underlying type on which the filter applies.
+ */
+public class AndFilter<T> extends AbstractCompoundFilter<T> {
+
+ public AndFilter() {
+ super();
+ }
+
+ public AndFilter(Filter<T>... filters) {
+ super(filters);
+ }
+
+ public boolean filter(T obj) {
+ boolean match = true;
+ for (Filter<T> filter : filters) {
+ if (!filter.filter(obj)) {
+ match = false;
+ break;
+ }
+ }
+ return match;
+ }
+
+ @Override
+ protected String getOperator() {
+ return "and";
+ }
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/DirectoryFilter.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/DirectoryFilter.java new file mode 100644 index 00000000000..acd3f8c3c37 --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/DirectoryFilter.java @@ -0,0 +1,17 @@ +package net.sourceforge.pmd.util.filter;
+
+import java.io.File;
+
+/**
+ * Directory filter.
+ */
+public class DirectoryFilter implements Filter<File> {
+ public static final DirectoryFilter INSTANCE = new DirectoryFilter();
+
+ private DirectoryFilter() {
+ }
+
+ public boolean filter(File file) {
+ return file.isDirectory();
+ }
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/FileExtensionFilter.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/FileExtensionFilter.java new file mode 100644 index 00000000000..5d7aa4ce0ed --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/FileExtensionFilter.java @@ -0,0 +1,42 @@ +package net.sourceforge.pmd.util.filter;
+
+import java.io.File;
+
+public class FileExtensionFilter implements Filter<File> {
+ protected final String[] extensions;
+ protected final boolean ignoreCase;
+
+ /**
+ * Matches any files with the given extensions, ignoring case
+ */
+ public FileExtensionFilter(String... extensions) {
+ this(true, extensions);
+ }
+
+ /**
+ * Matches any files with the given extensions, optionally ignoring case.
+ */
+ public FileExtensionFilter(boolean ignoreCase, String... extensions) {
+ this.extensions = extensions;
+ this.ignoreCase = ignoreCase;
+ if (ignoreCase) {
+ for (int i = 0; i < this.extensions.length; i++) {
+ this.extensions[i] = this.extensions[i].toUpperCase();
+ }
+ }
+ }
+
+ public boolean filter(File file) {
+ boolean accept = extensions == null;
+ if (!accept) {
+ for (String extension : extensions) {
+ String name = file.getName();
+ if (ignoreCase ? name.toUpperCase().endsWith(extension) : name.endsWith(extension)) {
+ accept = true;
+ break;
+ }
+ }
+ }
+ return accept;
+ }
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/Filter.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/Filter.java new file mode 100644 index 00000000000..9cb249d6dc7 --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/Filter.java @@ -0,0 +1,11 @@ +package net.sourceforge.pmd.util.filter;
+
+/**
+ * A Filter interface, used for filtering arbitrary objects.
+ *
+ * @param <T>
+ * The underlying type on which the filter applies.
+ */
+public interface Filter<T> {
+ boolean filter(T obj);
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/Filters.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/Filters.java new file mode 100644 index 00000000000..948bb5a1dc4 --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/Filters.java @@ -0,0 +1,200 @@ +package net.sourceforge.pmd.util.filter;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Utility class for working with Filters. Contains builder style methods,
+ * apply methods, as well as mechanisms for adapting Filters and FilenameFilters.
+ */
+public class Filters {
+
+ /**
+ * Filter a given Collection.
+ * @param <T> Type of the Collection.
+ * @param filter A Filter upon the Type of objects in the Collection.
+ * @param collection The Collection to filter.
+ * @return A List containing only those objects for which the Filter returned <code>true</code>.
+ */
+ public static <T> List<T> filter(Filter<T> filter, Collection<T> collection) {
+ List<T> list = new ArrayList<T>();
+ for (T obj : collection) {
+ if (filter.filter(obj)) {
+ list.add(obj);
+ }
+ }
+ return list;
+ }
+
+ /**
+ * Get a File Filter for files with the given extensions, ignoring case.
+ * @param extensions The extensions to filter.
+ * @return A File Filter.
+ */
+ public static Filter<File> getFileExtensionFilter(String... extensions) {
+ return new FileExtensionFilter(extensions);
+ }
+
+ /**
+ * Get a File Filter for directories.
+ * @return A File Filter.
+ */
+ public static Filter<File> getDirectoryFilter() {
+ return DirectoryFilter.INSTANCE;
+ }
+
+ /**
+ * Get a File Filter for directories or for files with the given extensions, ignoring case.
+ * @param extensions The extensions to filter.
+ * @return A File Filter.
+ */
+ public static Filter<File> getFileExtensionOrDirectoryFilter(String... extensions) {
+ return new OrFilter<File>(getFileExtensionFilter(extensions), getDirectoryFilter());
+ }
+
+ /**
+ * Given a String Filter, expose as a File Filter. The File paths are
+ * normalized to a standard pattern using <code>/</code> as a path separator
+ * which can be used cross platform easily in a regular expression based
+ * String Filter.
+ *
+ * @param filter A String Filter.
+ * @return A File Filter.
+ */
+ public static Filter<File> toNormalizedFileFilter(final Filter<String> filter) {
+ return new Filter<File>() {
+ public boolean filter(File file) {
+ String path = file.getPath();
+ path = path.replace('\\', '/');
+ return filter.filter(path);
+ }
+
+ public String toString() {
+ return filter.toString();
+ }
+ };
+ }
+
+ /**
+ * Given a String Filter, expose as a Filter on another type. The
+ * <code>toString()</code> method is called on the objects of the other
+ * type and delegated to the String Filter.
+ * @param <T> The desired type.
+ * @param filter The existing String Filter.
+ * @return A Filter on the desired type.
+ */
+ public static <T> Filter<T> fromStringFilter(final Filter<String> filter) {
+ return new Filter<T>() {
+ public boolean filter(T obj) {
+ return filter.filter(obj.toString());
+ }
+
+ public String toString() {
+ return filter.toString();
+ }
+ };
+ }
+
+ /**
+ * Given a File Filter, expose as a FilenameFilter.
+ * @param filter The File Filter.
+ * @return A FilenameFilter.
+ */
+ public static FilenameFilter toFilenameFilter(final Filter<File> filter) {
+ return new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ return filter.filter(new File(dir, name));
+ }
+
+ public String toString() {
+ return filter.toString();
+ }
+ };
+ }
+
+ /**
+ * Given a FilenameFilter, expose as a File Filter.
+ * @param filter The FilenameFilter.
+ * @return A File Filter.
+ */
+ public static Filter<File> toFileFilter(final FilenameFilter filter) {
+ return new Filter<File>() {
+ public boolean filter(File file) {
+ return filter.accept(file.getParentFile(), file.getName());
+ }
+
+ public String toString() {
+ return filter.toString();
+ }
+ };
+ }
+
+ /**
+ * Construct a String Filter using set of include and exclude regular
+ * expressions. If there are no include regular expressions provide, then
+ * a regular expression is added which matches every String by default.
+ * A String is included as long as it matches an include regular expression
+ * and does not match an exclude regular expression.
+ * <p>
+ * In other words, exclude patterns override include patterns.
+ *
+ * @param includeRegexes The include regular expressions. May be <code>null</code>.
+ * @param excludeRegexes The exclude regular expressions. May be <code>null</code>.
+ * @return A String Filter.
+ */
+ public static Filter<String> buildRegexFilterExcludeOverInclude(List<String> includeRegexes,
+ List<String> excludeRegexes) {
+ OrFilter<String> includeFilter = new OrFilter<String>();
+ if (includeRegexes == null || includeRegexes.size() == 0) {
+ includeFilter.addFilter(new RegexStringFilter(".*"));
+ } else {
+ for (String includeRegex : includeRegexes) {
+ includeFilter.addFilter(new RegexStringFilter(includeRegex));
+ }
+ }
+
+ OrFilter<String> excludeFilter = new OrFilter<String>();
+ if (excludeRegexes != null) {
+ for (String excludeRegex : excludeRegexes) {
+ excludeFilter.addFilter(new RegexStringFilter(excludeRegex));
+ }
+ }
+
+ return new AndFilter<String>(includeFilter, new NotFilter<String>(excludeFilter));
+ }
+
+ /**
+ * Construct a String Filter using set of include and exclude regular
+ * expressions. If there are no include regular expressions provide, then
+ * a regular expression is added which matches every String by default.
+ * A String is included as long as the case that there is an include which
+ * matches or there is not an exclude which matches.
+ * <p>
+ * In other words, include patterns override exclude patterns.
+ *
+ * @param includeRegexes The include regular expressions. May be <code>null</code>.
+ * @param excludeRegexes The exclude regular expressions. May be <code>null</code>.
+ * @return A String Filter.
+ */
+ public static Filter<String> buildRegexFilterIncludeOverExclude(List<String> includeRegexes,
+ List<String> excludeRegexes) {
+ OrFilter<String> includeFilter = new OrFilter<String>();
+ if (includeRegexes != null) {
+ for (String includeRegex : includeRegexes) {
+ includeFilter.addFilter(new RegexStringFilter(includeRegex));
+ }
+ }
+
+ OrFilter<String> excludeFilter = new OrFilter<String>();
+ if (excludeRegexes != null) {
+ for (String excludeRegex : excludeRegexes) {
+ excludeFilter.addFilter(new RegexStringFilter(excludeRegex));
+ }
+ }
+
+ return new OrFilter<String>(includeFilter, new NotFilter<String>(excludeFilter));
+ }
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/NotFilter.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/NotFilter.java new file mode 100644 index 00000000000..437e3524805 --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/NotFilter.java @@ -0,0 +1,25 @@ +package net.sourceforge.pmd.util.filter;
+
+/**
+ * A logical NEGATION of a Filter.
+ *
+ * @param <T>
+ * The underlying type on which the filter applies.
+ */
+public class NotFilter<T> extends AbstractDelegateFilter<T> {
+ public NotFilter() {
+ super();
+ }
+
+ public NotFilter(Filter<T> filter) {
+ super(filter);
+ }
+
+ public boolean filter(T obj) {
+ return !filter.filter(obj);
+ }
+
+ public String toString() {
+ return "not (" + filter + ")";
+ }
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/OrFilter.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/OrFilter.java new file mode 100644 index 00000000000..2647e2d98ab --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/OrFilter.java @@ -0,0 +1,34 @@ +package net.sourceforge.pmd.util.filter;
+
+/**
+ * A logical OR of a list of Filters. This implementation is short circuiting.
+ *
+ * @param <T>
+ * The underlying type on which the filter applies.
+ */
+public class OrFilter<T> extends AbstractCompoundFilter<T> {
+
+ public OrFilter() {
+ super();
+ }
+
+ public OrFilter(Filter<T>... filters) {
+ super(filters);
+ }
+
+ public boolean filter(T obj) {
+ boolean match = false;
+ for (Filter<T> filter : filters) {
+ if (filter.filter(obj)) {
+ match = true;
+ break;
+ }
+ }
+ return match;
+ }
+
+ @Override
+ protected String getOperator() {
+ return "or";
+ }
+}
diff --git a/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/RegexStringFilter.java b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/RegexStringFilter.java new file mode 100644 index 00000000000..7f883212589 --- /dev/null +++ b/sonar-duplications/src/main/java/net/sourceforge/pmd/util/filter/RegexStringFilter.java @@ -0,0 +1,40 @@ +package net.sourceforge.pmd.util.filter;
+
+import java.util.regex.Pattern;
+
+/**
+ * A filter to which uses a regular expression to match upon Strings.
+ */
+public class RegexStringFilter implements Filter<String> {
+
+ protected String regex;
+
+ protected Pattern pattern;
+
+ public RegexStringFilter() {
+ }
+
+ public RegexStringFilter(String regex) {
+ this.regex = regex;
+ }
+
+ public String getRegex() {
+ return regex;
+ }
+
+ public void setRegex(String regex) {
+ this.regex = regex;
+ this.pattern = null;
+ }
+
+ public boolean filter(String obj) {
+ if (pattern == null) {
+ pattern = Pattern.compile(regex);
+ }
+ return pattern.matcher(obj).matches();
+ }
+
+ public String toString() {
+ return "matches " + regex;
+ }
+}
diff --git a/sonar-duplications/src/main/java/org/sonar/duplications/cpd/CPD.java b/sonar-duplications/src/main/java/org/sonar/duplications/cpd/CPD.java new file mode 100644 index 00000000000..f8b88745233 --- /dev/null +++ b/sonar-duplications/src/main/java/org/sonar/duplications/cpd/CPD.java @@ -0,0 +1,114 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ +package org.sonar.duplications.cpd; + +import net.sourceforge.pmd.cpd.*; +import net.sourceforge.pmd.util.FileFinder; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.*; + +public class CPD { + + private Map<String, SourceCode> source = new HashMap<String, SourceCode>(); + private CPDListener listener = new CPDNullListener(); + private Tokens tokens = new Tokens(); + private int minimumTileSize; + private MatchAlgorithm matchAlgorithm; + private Language language; + private boolean skipDuplicates; + public static boolean debugEnable = false; + private boolean loadSourceCodeSlices = true; + private String encoding = System.getProperty("file.encoding"); + + public CPD(int minimumTileSize, Language language) { + TokenEntry.clearImages(); // workaround for bug 1947823 + this.minimumTileSize = minimumTileSize; + this.language = language; + } + + public void skipDuplicates() { + this.skipDuplicates = true; + } + + public void setCpdListener(CPDListener cpdListener) { + this.listener = cpdListener; + } + + public void setEncoding(String encoding) { + this.encoding = encoding; + } + + public void setLoadSourceCodeSlices(boolean loadSourceCodeSlices) { + this.loadSourceCodeSlices = loadSourceCodeSlices; + } + + public void go() { + TokenEntry.clearImages(); + matchAlgorithm = new MatchAlgorithm(source, tokens, minimumTileSize, listener); + matchAlgorithm.setLoadSourceCodeSlices(loadSourceCodeSlices); + matchAlgorithm.findMatches(); + } + + public Iterator<Match> getMatches() { + return matchAlgorithm.matches(); + } + + public void add(File file) throws IOException { + add(1, file); + } + + public void addAllInDirectory(String dir) throws IOException { + addDirectory(dir, false); + } + + public void addRecursively(String dir) throws IOException { + addDirectory(dir, true); + } + + public void add(List<File> files) throws IOException { + for (File f : files) { + add(files.size(), f); + } + } + + private void addDirectory(String dir, boolean recurse) throws IOException { + if ( !(new File(dir)).exists()) { + throw new FileNotFoundException("Couldn't find directory " + dir); + } + FileFinder finder = new FileFinder(); + // TODO - could use SourceFileSelector here + add(finder.findFilesFrom(dir, language.getFileFilter(), recurse)); + } + + private Set<String> current = new HashSet<String>(); + + private void add(int fileCount, File file) throws IOException { + + if (skipDuplicates) { + // TODO refactor this thing into a separate class + String signature = file.getName() + '_' + file.length(); + if (current.contains(signature)) { + System.err.println("Skipping " + file.getAbsolutePath() + + " since it appears to be a duplicate file and --skip-duplicate-files is set"); + return; + } + current.add(signature); + } + + if ( !file.getCanonicalPath().equals(new File(file.getAbsolutePath()).getCanonicalPath())) { + System.err.println("Skipping " + file + " since it appears to be a symlink"); + return; + } + + listener.addedFile(fileCount, file); + SourceCode sourceCode = new SourceCode(new FileCodeLoaderWithoutCache(file, encoding)); + language.getTokenizer().tokenize(sourceCode, tokens); + source.put(sourceCode.getFileName(), sourceCode); + } + + +} diff --git a/sonar-duplications/src/main/java/org/sonar/duplications/cpd/CodeLoaderWithoutCache.java b/sonar-duplications/src/main/java/org/sonar/duplications/cpd/CodeLoaderWithoutCache.java new file mode 100644 index 00000000000..f436768c929 --- /dev/null +++ b/sonar-duplications/src/main/java/org/sonar/duplications/cpd/CodeLoaderWithoutCache.java @@ -0,0 +1,31 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.duplications.cpd; + +import java.util.List; + +import net.sourceforge.pmd.cpd.SourceCode.CodeLoader; + +public abstract class CodeLoaderWithoutCache extends CodeLoader { + + public final List<String> getCode() { + return load(); + } +} diff --git a/sonar-duplications/src/main/java/org/sonar/duplications/cpd/FileCodeLoaderWithoutCache.java b/sonar-duplications/src/main/java/org/sonar/duplications/cpd/FileCodeLoaderWithoutCache.java new file mode 100644 index 00000000000..fe63482d46b --- /dev/null +++ b/sonar-duplications/src/main/java/org/sonar/duplications/cpd/FileCodeLoaderWithoutCache.java @@ -0,0 +1,44 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.duplications.cpd; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.io.Reader; + +public class FileCodeLoaderWithoutCache extends CodeLoaderWithoutCache { + + private File file; + private String encoding; + + public FileCodeLoaderWithoutCache(File file, String encoding) { + this.file = file; + this.encoding = encoding; + } + + public Reader getReader() throws Exception { + return new InputStreamReader(new FileInputStream(file), encoding); + } + + public String getFileName() { + return this.file.getAbsolutePath(); + } +} diff --git a/sonar-duplications/src/main/java/org/sonar/duplications/cpd/Match.java b/sonar-duplications/src/main/java/org/sonar/duplications/cpd/Match.java new file mode 100644 index 00000000000..777f8617b2a --- /dev/null +++ b/sonar-duplications/src/main/java/org/sonar/duplications/cpd/Match.java @@ -0,0 +1,171 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ +package org.sonar.duplications.cpd; + +import java.util.Comparator; +import java.util.Iterator; +import java.util.Set; +import java.util.TreeSet; + +import net.sourceforge.pmd.cpd.TokenEntry; + +public class Match implements Comparable<Match> { + + public static final String EOL = System.getProperty("line.separator", "\n"); + + private int tokenCount; + private int lineCount; + private Set<TokenEntry> markSet = new TreeSet<TokenEntry>(); + private TokenEntry[] marks = new TokenEntry[2]; + private String code; + private MatchCode mc; + private String label; + + public static final Comparator<Match> MatchesComparator = new Comparator<Match>() { + + public int compare(Match ma, Match mb) { + return mb.getMarkCount() - ma.getMarkCount(); + } + }; + + public static final Comparator<Match> LinesComparator = new Comparator<Match>() { + + public int compare(Match ma, Match mb) { + return mb.getLineCount() - ma.getLineCount(); + } + }; + + public static final Comparator<Match> LabelComparator = new Comparator<Match>() { + + public int compare(Match ma, Match mb) { + if (ma.getLabel() == null) + return 1; + if (mb.getLabel() == null) + return -1; + return mb.getLabel().compareTo(ma.getLabel()); + } + }; + + public static final Comparator<Match> LengthComparator = new Comparator<Match>() { + + public int compare(Match ma, Match mb) { + return mb.getLineCount() - ma.getLineCount(); + } + }; + + public static class MatchCode { + + private int first; + private int second; + + public MatchCode() { + } + + public MatchCode(TokenEntry m1, TokenEntry m2) { + first = m1.getIndex(); + second = m2.getIndex(); + } + + public int hashCode() { + return first + 37 * second; + } + + public boolean equals(Object other) { + MatchCode mc = (MatchCode) other; + return mc.first == first && mc.second == second; + } + + public void setFirst(int first) { + this.first = first; + } + + public void setSecond(int second) { + this.second = second; + } + + } + + public Match(int tokenCount, TokenEntry first, TokenEntry second) { + markSet.add(first); + markSet.add(second); + marks[0] = first; + marks[1] = second; + this.tokenCount = tokenCount; + } + + public int getMarkCount() { + return markSet.size(); + } + + public void setLineCount(int lineCount) { + this.lineCount = lineCount; + } + + public int getLineCount() { + return this.lineCount; + } + + public int getTokenCount() { + return this.tokenCount; + } + + public String getSourceCodeSlice() { + return this.code; + } + + public void setSourceCodeSlice(String code) { + this.code = code; + } + + public Iterator<TokenEntry> iterator() { + return markSet.iterator(); + } + + public int compareTo(Match other) { + int diff = other.getTokenCount() - getTokenCount(); + if (diff != 0) { + return diff; + } + return other.getFirstMark().getIndex() - getFirstMark().getIndex(); + } + + public TokenEntry getFirstMark() { + return marks[0]; + } + + public TokenEntry getSecondMark() { + return marks[1]; + } + + public String toString() { + return "Match: " + EOL + "tokenCount = " + tokenCount + EOL + "marks = " + markSet.size(); + } + + public Set<TokenEntry> getMarkSet() { + return markSet; + } + + public MatchCode getMatchCode() { + if (mc == null) { + mc = new MatchCode(marks[0], marks[1]); + } + return mc; + } + + public int getEndIndex() { + return marks[1].getIndex() + getTokenCount() - 1; + } + + public void setMarkSet(Set<TokenEntry> markSet) { + this.markSet = markSet; + } + + public void setLabel(String aLabel) { + label = aLabel; + } + + public String getLabel() { + return label; + } +}
\ No newline at end of file diff --git a/sonar-duplications/src/main/java/org/sonar/duplications/cpd/MatchAlgorithm.java b/sonar-duplications/src/main/java/org/sonar/duplications/cpd/MatchAlgorithm.java new file mode 100644 index 00000000000..fce761146dc --- /dev/null +++ b/sonar-duplications/src/main/java/org/sonar/duplications/cpd/MatchAlgorithm.java @@ -0,0 +1,131 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ +package org.sonar.duplications.cpd; + +import net.sourceforge.pmd.cpd.*; + +import java.util.*; + +public class MatchAlgorithm { + + private final static int MOD = 37; + private int lastHash; + private int lastMod = 1; + + private List<Match> matches; + private Map<String, SourceCode> source; + private Tokens tokens; + private List<TokenEntry> code; + private CPDListener cpdListener; + private int min; + private boolean loadSourceCodeSlices = true; + + public MatchAlgorithm(Map<String, SourceCode> sourceCode, Tokens tokens, int min) { + this(sourceCode, tokens, min, new CPDNullListener()); + } + + public MatchAlgorithm(Map<String, SourceCode> sourceCode, Tokens tokens, int min, CPDListener listener) { + this.source = sourceCode; + this.tokens = tokens; + this.code = tokens.getTokens(); + this.min = min; + this.cpdListener = listener; + for (int i = 0; i < min; i++) { + lastMod *= MOD; + } + } + + public void setLoadSourceCodeSlices(boolean loadSourceCodeSlices) { + this.loadSourceCodeSlices = loadSourceCodeSlices; + } + + public void setListener(CPDListener listener) { + this.cpdListener = listener; + } + + public Iterator<Match> matches() { + return matches.iterator(); + } + + public TokenEntry tokenAt(int offset, TokenEntry m) { + return code.get(offset + m.getIndex()); + } + + public int getMinimumTileSize() { + return this.min; + } + + public void findMatches() { + cpdListener.phaseUpdate(CPDListener.HASH); + Map<TokenEntry, Object> markGroups = hash(); + + cpdListener.phaseUpdate(CPDListener.MATCH); + MatchCollector matchCollector = new MatchCollector(this); + for (Iterator<Object> i = markGroups.values().iterator(); i.hasNext();) { + Object o = i.next(); + if (o instanceof List) { + List<TokenEntry> l = (List<TokenEntry>) o; + + Collections.reverse(l); + matchCollector.collect(l); + } + i.remove(); + } + cpdListener.phaseUpdate(CPDListener.GROUPING); + matches = matchCollector.getMatches(); + matchCollector = null; + for (Match match : matches) { + for (Iterator<TokenEntry> occurrences = match.iterator(); occurrences.hasNext();) { + TokenEntry mark = occurrences.next(); + match.setLineCount(tokens.getLineCount(mark, match)); + if (loadSourceCodeSlices && !occurrences.hasNext()) { + int start = mark.getBeginLine(); + int end = start + match.getLineCount() - 1; + SourceCode sourceCode = source.get(mark.getTokenSrcID()); + match.setSourceCodeSlice(sourceCode.getSlice(start, end)); + } + } + } + cpdListener.phaseUpdate(CPDListener.DONE); + } + + @SuppressWarnings("PMD.JumbledIncrementer") + private Map<TokenEntry, Object> hash() { + Map<TokenEntry, Object> markGroups = new HashMap<TokenEntry, Object>(tokens.size()); + for (int i = code.size() - 1; i >= 0; i--) { + TokenEntry token = code.get(i); + if (token != TokenEntry.EOF) { + int last = tokenAt(min, token).getIdentifier(); + lastHash = MOD * lastHash + token.getIdentifier() - lastMod * last; + token.setHashCode(lastHash); + Object o = markGroups.get(token); + + // Note that this insertion method is worthwhile since the vast majority + // markGroup keys will have only one value. + if (o == null) { + markGroups.put(token, token); + } else if (o instanceof TokenEntry) { + List<TokenEntry> l = new ArrayList<TokenEntry>(); + l.add((TokenEntry) o); + l.add(token); + markGroups.put(token, l); + } else { + List<TokenEntry> l = (List<TokenEntry>) o; + l.add(token); + } + } else { + lastHash = 0; + for (int end = Math.max(0, i - min + 1); i > end; i--) { + token = code.get(i - 1); + lastHash = MOD * lastHash + token.getIdentifier(); + if (token == TokenEntry.EOF) { + break; + } + } + } + } + return markGroups; + } + +} diff --git a/sonar-duplications/src/main/java/org/sonar/duplications/cpd/MatchCollector.java b/sonar-duplications/src/main/java/org/sonar/duplications/cpd/MatchCollector.java new file mode 100644 index 00000000000..6bbb825b025 --- /dev/null +++ b/sonar-duplications/src/main/java/org/sonar/duplications/cpd/MatchCollector.java @@ -0,0 +1,167 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ +package org.sonar.duplications.cpd; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import net.sourceforge.pmd.cpd.TokenEntry; + +public class MatchCollector { + + private MatchAlgorithm ma; + private Map<Match.MatchCode, Match> startMap = new HashMap<Match.MatchCode, Match>(); + private Map<String, List<Match>> fileMap = new HashMap<String, List<Match>>(); + + public MatchCollector(MatchAlgorithm ma) { + this.ma = ma; + } + + public void collect(List<TokenEntry> marks) { + // first get a pairwise collection of all maximal matches + for (int i = 0; i < marks.size() - 1; i++) { + TokenEntry mark1 = marks.get(i); + for (int j = i + 1; j < marks.size(); j++) { + TokenEntry mark2 = marks.get(j); + int diff = mark1.getIndex() - mark2.getIndex(); + if ( -diff < ma.getMinimumTileSize()) { + continue; + } + if (hasPreviousDupe(mark1, mark2)) { + continue; + } + + // "match too small" check + int dupes = countDuplicateTokens(mark1, mark2); + if (dupes < ma.getMinimumTileSize()) { + continue; + } + // is it still too close together + if (diff + dupes >= 1) { + continue; + } + determineMatch(mark1, mark2, dupes); + } + } + } + + @SuppressWarnings("PMD.CompareObjectsWithEquals") + public List<Match> getMatches() { + List<Match> matchList = new ArrayList<Match>(startMap.values()); + Collections.sort(matchList); + Set<Match.MatchCode> matchSet = new HashSet<Match.MatchCode>(); + Match.MatchCode matchCode = new Match.MatchCode(); + for (int i = matchList.size(); i > 1; i--) { + Match match1 = matchList.get(i - 1); + TokenEntry mark1 = match1.getMarkSet().iterator().next(); + matchSet.clear(); + matchSet.add(match1.getMatchCode()); + for (int j = i - 1; j > 0; j--) { + Match match2 = matchList.get(j - 1); + if (match1.getTokenCount() != match2.getTokenCount()) { + break; + } + TokenEntry mark2 = null; + for (Iterator<TokenEntry> iter = match2.getMarkSet().iterator(); iter.hasNext();) { + mark2 = iter.next(); + if (mark2 != mark1) { + break; + } + } + int dupes = countDuplicateTokens(mark1, mark2); + if (dupes < match1.getTokenCount()) { + break; + } + matchSet.add(match2.getMatchCode()); + match1.getMarkSet().addAll(match2.getMarkSet()); + matchList.remove(i - 2); + i--; + } + if (matchSet.size() == 1) { + continue; + } + // prune the mark set + Set<TokenEntry> pruned = match1.getMarkSet(); + boolean done = false; + ArrayList<TokenEntry> a1 = new ArrayList<TokenEntry>(match1.getMarkSet()); + Collections.sort(a1); + for (int outer = 0; outer < a1.size() - 1 && !done; outer++) { + TokenEntry cmark1 = a1.get(outer); + for (int inner = outer + 1; inner < a1.size() && !done; inner++) { + TokenEntry cmark2 = a1.get(inner); + matchCode.setFirst(cmark1.getIndex()); + matchCode.setSecond(cmark2.getIndex()); + if ( !matchSet.contains(matchCode)) { + if (pruned.size() > 2) { + pruned.remove(cmark2); + } + if (pruned.size() == 2) { + done = true; + } + } + } + } + } + return matchList; + } + + /** + * A greedy algorithm for determining non-overlapping matches + */ + private void determineMatch(TokenEntry mark1, TokenEntry mark2, int dupes) { + Match match = new Match(dupes, mark1, mark2); + String fileKey = mark1.getTokenSrcID() + mark2.getTokenSrcID(); + List<Match> pairMatches = fileMap.get(fileKey); + if (pairMatches == null) { + pairMatches = new ArrayList<Match>(); + fileMap.put(fileKey, pairMatches); + } + boolean add = true; + for (int i = 0; i < pairMatches.size(); i++) { + Match other = pairMatches.get(i); + if (other.getFirstMark().getIndex() + other.getTokenCount() - mark1.getIndex() > 0) { + boolean ordered = other.getSecondMark().getIndex() - mark2.getIndex() < 0; + if ((ordered && (other.getEndIndex() - mark2.getIndex() > 0)) + || ( !ordered && (match.getEndIndex() - other.getSecondMark().getIndex()) > 0)) { + if (other.getTokenCount() >= match.getTokenCount()) { + add = false; + break; + } else { + pairMatches.remove(i); + startMap.remove(other.getMatchCode()); + } + } + } + } + if (add) { + pairMatches.add(match); + startMap.put(match.getMatchCode(), match); + } + } + + private boolean hasPreviousDupe(TokenEntry mark1, TokenEntry mark2) { + if (mark1.getIndex() == 0) { + return false; + } + return !matchEnded(ma.tokenAt( -1, mark1), ma.tokenAt( -1, mark2)); + } + + private int countDuplicateTokens(TokenEntry mark1, TokenEntry mark2) { + int index = 0; + while ( !matchEnded(ma.tokenAt(index, mark1), ma.tokenAt(index, mark2))) { + index++; + } + return index; + } + + private boolean matchEnded(TokenEntry token1, TokenEntry token2) { + return token1.getIdentifier() != token2.getIdentifier() || token1 == TokenEntry.EOF || token2 == TokenEntry.EOF; + } +}
\ No newline at end of file diff --git a/sonar-duplications/src/test/java/org/sonar/duplications/cpd/CPDTest.java b/sonar-duplications/src/test/java/org/sonar/duplications/cpd/CPDTest.java new file mode 100644 index 00000000000..f0f561091b2 --- /dev/null +++ b/sonar-duplications/src/test/java/org/sonar/duplications/cpd/CPDTest.java @@ -0,0 +1,90 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2009 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.duplications.cpd; + +import net.sourceforge.pmd.cpd.AbstractLanguage; +import net.sourceforge.pmd.cpd.JavaTokenizer; +import net.sourceforge.pmd.cpd.TokenEntry; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertThat; + +public class CPDTest { + + @Test + public void testSetLoadSourceCodeSlicesToFalse() throws IOException { + TokenEntry.clearImages(); + AbstractLanguage cpdLanguage = new AbstractLanguage(new JavaTokenizer()) { + }; + CPD cpd = new CPD(20, cpdLanguage); + cpd.setEncoding(Charset.defaultCharset().name()); + cpd.setLoadSourceCodeSlices(false); + cpd.add(new File("test-resources/org/sonar/duplications/cpd/CPDTest/CPDFile1.java")); + cpd.add(new File("test-resources/org/sonar/duplications/cpd/CPDTest/CPDFile2.java")); + cpd.go(); + + List<Match> matches = getMatches(cpd); + assertThat(matches.size(), is(1)); + + org.sonar.duplications.cpd.Match match = matches.get(0); + assertThat(match.getLineCount(), is(26)); + assertThat(match.getFirstMark().getBeginLine(), is(16)); + assertThat(match.getSourceCodeSlice(), is(nullValue())); + } + + @Test + public void testDuplicationOnSameFile() throws IOException { + TokenEntry.clearImages(); + AbstractLanguage cpdLanguage = new AbstractLanguage(new JavaTokenizer()) { + }; + CPD cpd = new CPD(20, cpdLanguage); + cpd.setEncoding(Charset.defaultCharset().name()); + cpd.setLoadSourceCodeSlices(false); + cpd.add(new File("test-resources/org/sonar/duplications/cpd/CPDTest/CPDFile3.java")); + cpd.go(); + + List<Match> matches = getMatches(cpd); + assertThat(matches.size(), is(1)); + + org.sonar.duplications.cpd.Match match = matches.get(0); + assertThat(match.getLineCount(), is(16)); + assertThat(match.getFirstMark().getBeginLine(), is(29)); + assertThat(match.getSourceCodeSlice(), is(nullValue())); + } + + private List<Match> getMatches(CPD cpd) { + List<Match> matches = new ArrayList<org.sonar.duplications.cpd.Match>(); + Iterator<Match> matchesIter = cpd.getMatches(); + while (matchesIter.hasNext()) { + matches.add(matchesIter.next()); + } + return matches; + } + +} diff --git a/sonar-duplications/test-resources/README.txt b/sonar-duplications/test-resources/README.txt new file mode 100644 index 00000000000..3f09e6215df --- /dev/null +++ b/sonar-duplications/test-resources/README.txt @@ -0,0 +1,2 @@ +This directory is a workaround for opening the project into Intellij Idea. +Indeed it tries to compile Java sources found in src/test/resources, and fail because of syntax errors or specific encoding.
\ No newline at end of file diff --git a/sonar-duplications/test-resources/org/sonar/duplications/cpd/CPDTest/CPDFile1.java b/sonar-duplications/test-resources/org/sonar/duplications/cpd/CPDTest/CPDFile1.java new file mode 100644 index 00000000000..75e2b77b0dc --- /dev/null +++ b/sonar-duplications/test-resources/org/sonar/duplications/cpd/CPDTest/CPDFile1.java @@ -0,0 +1,41 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ +package net.sourceforge.pmd.cpd.fork; + +import java.util.HashMap; +import java.util.Map; + +import net.sourceforge.pmd.cpd.CPDListener; +import net.sourceforge.pmd.cpd.CPDNullListener; +import net.sourceforge.pmd.cpd.Language; +import net.sourceforge.pmd.cpd.SourceCode; +import net.sourceforge.pmd.cpd.Tokens; +import org.sonar.duplications.cpd.MatchAlgorithm; + +public class CPDFile1 { + + private Map<String, SourceCode> source = new HashMap<String, SourceCode>(); + private CPDListener listener = new CPDNullListener(); + private Tokens tokens = new Tokens(); + private int minimumTileSize; + private MatchAlgorithm matchAlgorithm; + private Language language; + private boolean skipDuplicates; + public static boolean debugEnable = false; + private boolean loadSourceCodeSlices = true; + private String encoding = System.getProperty("file.encoding"); + + public CPD(int minimumTileSize, Language language) { + this.minimumTileSize = minimumTileSize; + this.language = language; + } + + public void skipDuplicates() { + this.skipDuplicates = true; + } + + public void setCpdListener(CPDListener cpdListener) { + this.listener = cpdListener; + } +} diff --git a/sonar-duplications/test-resources/org/sonar/duplications/cpd/CPDTest/CPDFile2.java b/sonar-duplications/test-resources/org/sonar/duplications/cpd/CPDTest/CPDFile2.java new file mode 100644 index 00000000000..cdd67488f6a --- /dev/null +++ b/sonar-duplications/test-resources/org/sonar/duplications/cpd/CPDTest/CPDFile2.java @@ -0,0 +1,41 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ +package net.sourceforge.pmd.cpd.fork; + +import java.util.HashMap; +import java.util.Map; + +import net.sourceforge.pmd.cpd.CPDListener; +import net.sourceforge.pmd.cpd.CPDNullListener; +import net.sourceforge.pmd.cpd.Language; +import net.sourceforge.pmd.cpd.SourceCode; +import net.sourceforge.pmd.cpd.Tokens; +import org.sonar.duplications.cpd.MatchAlgorithm; + +public class CPDFile2 { + + private Map<String, SourceCode> source = new HashMap<String, SourceCode>(); + private CPDListener listener = new CPDNullListener(); + private Tokens tokens = new Tokens(); + private int minimumTileSize; + private MatchAlgorithm matchAlgorithm; + private Language language; + private boolean skipDuplicates; + public static boolean debugEnable = false; + private boolean loadSourceCodeSlices = true; + private String encoding = System.getProperty("file.encoding"); + + public CPD(int minimumTileSize, Language language) { + this.minimumTileSize = minimumTileSize; + this.language = language; + } + + public void skipDuplicates() { + this.skipDuplicates = true; + } + + public void setCpdListener(CPDListener cpdListener) { + this.listener = cpdListener; + } +} diff --git a/sonar-duplications/test-resources/org/sonar/duplications/cpd/CPDTest/CPDFile3.java b/sonar-duplications/test-resources/org/sonar/duplications/cpd/CPDTest/CPDFile3.java new file mode 100644 index 00000000000..8ba22b82a07 --- /dev/null +++ b/sonar-duplications/test-resources/org/sonar/duplications/cpd/CPDTest/CPDFile3.java @@ -0,0 +1,63 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ +package net.sourceforge.pmd.cpd.fork; + +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertThat; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import net.sourceforge.pmd.cpd.CPDListener; +import net.sourceforge.pmd.cpd.CPDNullListener; +import net.sourceforge.pmd.cpd.Language; +import net.sourceforge.pmd.cpd.SourceCode; +import net.sourceforge.pmd.cpd.Tokens; + +import org.apache.commons.io.FileUtils; +import org.sonar.duplications.cpd.CPD; +import org.sonar.duplications.cpd.Match; +import org.sonar.duplications.cpd.MatchAlgorithm; + +public class CPDFile2 { + + + public void method1(){ + CPD cpd = new CPD(20, cpdLanguage); + cpd.setEncoding(Charset.defaultCharset().name()); + cpd.setLoadSourceCodeSlices(false); + cpd.add(FileUtils.toFile(CPD.class.getResource("/org/sonar/duplications/cpd/CPDTest/CPDFile1.java"))); + cpd.add(FileUtils.toFile(CPD.class.getResource("/org/sonar/duplications/cpd/CPDTest/CPDFile2.java"))); + cpd.go(); + + List<Match> matches = getMatches(cpd); + assertThat(matches.size(), is(1)); + + org.sonar.duplications.cpd.Match match = matches.get(0); + assertThat(match.getLineCount(), is(26)); + assertThat(match.getFirstMark().getBeginLine(), is(16)); + assertThat(match.getSourceCodeSlice(), is(nullValue())); + } + + public void method1Duplicated(){ + CPD cpd = new CPD(20, cpdLanguage); + cpd.setEncoding(Charset.defaultCharset().name()); + cpd.setLoadSourceCodeSlices(false); + cpd.add(FileUtils.toFile(CPD.class.getResource("/org/sonar/duplications/cpd/CPDTest/CPDFile1.java"))); + cpd.add(FileUtils.toFile(CPD.class.getResource("/org/sonar/duplications/cpd/CPDTest/CPDFile2.java"))); + cpd.go(); + + List<Match> matches = getMatches(cpd); + assertThat(matches.size(), is(1)); + + org.sonar.duplications.cpd.Match match = matches.get(0); + assertThat(match.getLineCount(), is(26)); + assertThat(match.getFirstMark().getBeginLine(), is(16)); + assertThat(match.getSourceCodeSlice(), is(nullValue())); + } + +} |