org.sonar.java.ast.JavaAstScanner Maven / Gradle / Ivy
/*
* SonarQube Java
* Copyright (C) 2012-2016 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.java.ast;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import com.sonar.sslr.api.RecognitionException;
import com.sonar.sslr.api.typed.ActionParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.java.JavaConfiguration;
import org.sonar.java.ast.parser.JavaParser;
import org.sonar.java.model.VisitorsBridge;
import org.sonar.plugins.java.api.tree.Tree;
import org.sonar.squidbridge.ProgressReport;
import org.sonar.squidbridge.api.AnalysisException;
import javax.annotation.Nullable;
import java.io.File;
import java.io.InterruptedIOException;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
public class JavaAstScanner {
private static final Logger LOG = LoggerFactory.getLogger(JavaAstScanner.class);
private final ActionParser parser;
private VisitorsBridge visitor;
public JavaAstScanner(ActionParser parser) {
this.parser = parser;
}
/**
* Takes parser and index from another instance of {@link JavaAstScanner}
*/
public JavaAstScanner(JavaAstScanner astScanner) {
this.parser = astScanner.parser;
}
public void scan(Iterable files) {
ProgressReport progressReport = new ProgressReport("Report about progress of Java AST analyzer", TimeUnit.SECONDS.toMillis(10));
progressReport.start(Lists.newArrayList(files));
boolean successfullyCompleted = false;
try {
for (File file : files) {
simpleScan(file);
progressReport.nextFile();
}
successfullyCompleted = true;
} finally {
if (successfullyCompleted) {
progressReport.stop();
} else {
progressReport.cancel();
}
}
}
private void simpleScan(File file) {
visitor.setCurrentFile(file);
try {
Tree ast = parser.parse(file);
visitor.visitFile(ast);
} catch (RecognitionException e) {
checkInterrrupted(e);
LOG.error("Unable to parse source file : " + file.getAbsolutePath());
LOG.error(e.getMessage());
parseErrorWalkAndVisit(e, file);
} catch (Exception e) {
checkInterrrupted(e);
throw new AnalysisException(getAnalyisExceptionMessage(file), e);
} catch (StackOverflowError error) {
LOG.error("A stack overflow error occured while analyzing file: " + file.getAbsolutePath());
throw error;
}
}
private static void checkInterrrupted(Exception e) {
Throwable cause = Throwables.getRootCause(e);
if (cause instanceof InterruptedException || cause instanceof InterruptedIOException) {
throw new AnalysisException("Analysis cancelled", e);
}
}
private void parseErrorWalkAndVisit(RecognitionException e, File file) {
try {
// Process the exception
visitor.visitFile(null);
visitor.processRecognitionException(e);
} catch (Exception e2) {
throw new AnalysisException(getAnalyisExceptionMessage(file), e2);
}
}
private static String getAnalyisExceptionMessage(File file) {
return "SonarQube is unable to analyze file : '" + file.getAbsolutePath() + "'";
}
public void setVisitorBridge(VisitorsBridge visitor) {
this.visitor = visitor;
}
@VisibleForTesting
public static void scanSingleFileForTests(File file, VisitorsBridge visitorsBridge) {
scanSingleFileForTests(file, visitorsBridge, new JavaConfiguration(Charset.forName("UTF-8")));
}
@VisibleForTesting
public static void scanSingleFileForTests(File file, VisitorsBridge visitorsBridge, JavaConfiguration conf) {
if (!file.isFile()) {
throw new IllegalArgumentException("File '" + file + "' not found.");
}
JavaAstScanner scanner = create(conf, visitorsBridge);
scanner.scan(Collections.singleton(file));
}
private static JavaAstScanner create(JavaConfiguration conf, @Nullable VisitorsBridge visitorsBridge) {
JavaAstScanner astScanner = new JavaAstScanner(JavaParser.createParser(conf.getCharset()));
if (visitorsBridge != null) {
visitorsBridge.setCharset(conf.getCharset());
visitorsBridge.setJavaVersion(conf.javaVersion());
astScanner.setVisitorBridge(visitorsBridge);
}
return astScanner;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy