*/
package org.sonar.java.ast;
-import com.google.common.collect.Maps;
import com.puppycrawl.tools.checkstyle.api.Check;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.resources.InputFile;
import org.sonar.java.ast.visitor.JavaAstVisitor;
-import org.sonar.java.recognizer.JavaFootprint;
-import org.sonar.java.squid.JavaSquidConfiguration;
-import org.sonar.squid.recognizer.CodeRecognizer;
import org.sonar.squid.text.Source;
-import java.io.File;
-import java.util.*;
-
/**
* Delegate from Checkstyle {@link Check} to {@link JavaAstVisitor}s.
*/
public class CheckstyleSquidBridge extends Check {
private static Logger logger = LoggerFactory.getLogger(CheckstyleSquidBridge.class);
- private static JavaAstVisitor[] visitors;
- private static int[] allTokens;
- private static CodeRecognizer codeRecognizer;
- private static Map<java.io.File,InputFile> inputFilesByPath = Maps.newHashMap();
- static void setASTVisitors(List<JavaAstVisitor> visitors) {
- CheckstyleSquidBridge.visitors = visitors.toArray(new JavaAstVisitor[visitors.size()]);
- SortedSet<Integer> sorter = new TreeSet<Integer>();
- for (JavaAstVisitor visitor : visitors) {
- sorter.addAll(visitor.getWantedTokens());
- allTokens = new int[sorter.size()];
- int i = 0;
- for (Integer itSorted : sorter) {
- allTokens[i++] = itSorted;
- }
- }
- }
+ private static CheckstyleSquidBridgeContext bridgeContext;
- static void setSquidConfiguration(JavaSquidConfiguration conf) {
- codeRecognizer = new CodeRecognizer(conf.getCommentedCodeThreshold(), new JavaFootprint());
+ /**
+ * @see CheckstyleSquidBridgeContext
+ */
+ static void setContext(CheckstyleSquidBridgeContext context) {
+ bridgeContext = context;
}
@Override
public int[] getDefaultTokens() {
- return allTokens; //NOSONAR returning directly the array is not a security flaw here
- }
-
- public static InputFile getInputFile(File path) {
- return inputFilesByPath.get(path);
- }
-
- public static void setInputFiles(Collection<InputFile> inputFiles) {
- inputFilesByPath.clear();
- for (InputFile inputFile : inputFiles) {
- inputFilesByPath.put(inputFile.getFile().getAbsoluteFile(), inputFile);
- }
+ return bridgeContext.getAllTokens();
}
@Override
try {
String filename = getFileContents().getFilename();
Source source = createSource();
- InputFile inputFile = getInputFile(new java.io.File(filename));
- for (JavaAstVisitor visitor : visitors) {
+ InputFile inputFile = bridgeContext.getInputFile(new java.io.File(filename));
+ for (JavaAstVisitor visitor : bridgeContext.getVisitors()) {
visitor.setFileContents(getFileContents());
visitor.setSource(source);
visitor.setInputFile(inputFile);
}
private Source createSource() {
- return new Source(getFileContents().getLines(), codeRecognizer);
+ return new Source(getFileContents().getLines(), bridgeContext.getCodeRecognizer());
}
@Override
public void visitToken(DetailAST ast) {
try {
- for (JavaAstVisitor visitor : visitors) {
+ for (JavaAstVisitor visitor : bridgeContext.getVisitors()) {
if (visitor.getWantedTokens().contains(ast.getType())) {
visitor.visitToken(ast);
}
@Override
public void leaveToken(DetailAST ast) {
+ JavaAstVisitor[] visitors = bridgeContext.getVisitors();
try {
for (int i = visitors.length - 1; i >= 0; i--) {
JavaAstVisitor visitor = visitors[i];
@Override
public void finishTree(DetailAST ast) {
+ JavaAstVisitor[] visitors = bridgeContext.getVisitors();
try {
for (int i = visitors.length - 1; i >= 0; i--) {
JavaAstVisitor visitor = visitors[i];
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * 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.java.ast;
+
+import com.google.common.collect.Maps;
+import org.sonar.api.resources.InputFile;
+import org.sonar.java.ast.visitor.JavaAstVisitor;
+import org.sonar.java.recognizer.JavaFootprint;
+import org.sonar.java.squid.JavaSquidConfiguration;
+import org.sonar.squid.recognizer.CodeRecognizer;
+
+import java.io.File;
+import java.util.*;
+
+/**
+ * This class helps to transfer additional information into {@link CheckstyleSquidBridge}.
+ * We forced to use static fields in {@link CheckstyleSquidBridge},
+ * because it will be instantiated by Checkstyle, so there is no other way of communication.
+ */
+class CheckstyleSquidBridgeContext {
+
+ private int[] allTokens;
+ private JavaAstVisitor[] visitors;
+ private CodeRecognizer codeRecognizer;
+ private Map<java.io.File, InputFile> inputFilesByPath = Maps.newHashMap();
+
+ public CheckstyleSquidBridgeContext setASTVisitors(List<JavaAstVisitor> visitors) {
+ this.visitors = visitors.toArray(new JavaAstVisitor[visitors.size()]);
+ SortedSet<Integer> sorter = new TreeSet<Integer>();
+ for (JavaAstVisitor visitor : visitors) {
+ sorter.addAll(visitor.getWantedTokens());
+ allTokens = new int[sorter.size()];
+ int i = 0;
+ for (Integer itSorted : sorter) {
+ allTokens[i++] = itSorted;
+ }
+ }
+ return this;
+ }
+
+ public CheckstyleSquidBridgeContext setSquidConfiguration(JavaSquidConfiguration conf) {
+ codeRecognizer = new CodeRecognizer(conf.getCommentedCodeThreshold(), new JavaFootprint());
+ return this;
+ }
+
+ public CheckstyleSquidBridgeContext setInputFiles(Collection<InputFile> inputFiles) {
+ inputFilesByPath.clear();
+ for (InputFile inputFile : inputFiles) {
+ inputFilesByPath.put(inputFile.getFile().getAbsoluteFile(), inputFile);
+ }
+ return this;
+ }
+
+ public int[] getAllTokens() {
+ return allTokens;
+ }
+
+ public InputFile getInputFile(File path) {
+ return inputFilesByPath.get(path);
+ }
+
+ public CodeRecognizer getCodeRecognizer() {
+ return codeRecognizer;
+ }
+
+ public JavaAstVisitor[] getVisitors() {
+ return visitors;
+ }
+
+}
for (JavaAstVisitor visitor : getVisitors()) {
visitor.setSourceCodeStack(resourcesStack);
}
- CheckstyleSquidBridge.setASTVisitors(getVisitors());
- CheckstyleSquidBridge.setSquidConfiguration(conf);
- CheckstyleSquidBridge.setInputFiles(inputFiles);
- launchCheckstyle(InputFileUtils.toFiles(inputFiles), conf.getCharset());
+
+ CheckstyleSquidBridgeContext bridgeContext = new CheckstyleSquidBridgeContext()
+ .setASTVisitors(getVisitors())
+ .setSquidConfiguration(conf)
+ .setInputFiles(inputFiles);
+
+ CheckstyleSquidBridge.setContext(bridgeContext);
+ try {
+ launchCheckstyle(InputFileUtils.toFiles(inputFiles), conf.getCharset());
+ } finally {
+ // Garbage collector should be able to do his job, so we must clean context after execution
+ CheckstyleSquidBridge.setContext(null);
+ }
return this;
}
try {
c.setClassloader(getClass().getClassLoader());
c.setModuleClassLoader(getClass().getClassLoader());
- c.process(Lists.<File>newArrayList(files));
+ c.process(Lists.<File> newArrayList(files));
c.destroy();
} finally {
Thread.currentThread().setContextClassLoader(initialClassLoader);