/* * Sonar PHP Plugin * Copyright (C) 2010 Sonar PHP Plugin * dev@sonar.codehaus.org * * 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 02 */ package org.sonar.plugins.php.core; import static org.sonar.plugins.php.api.Php.PHP; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.util.HashSet; import java.util.List; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.batch.Phase; import org.sonar.api.batch.Sensor; import org.sonar.api.batch.SensorContext; import org.sonar.api.checks.NoSonarFilter; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.resources.Project; import org.sonar.api.resources.ProjectFileSystem; import org.sonar.api.utils.SonarException; import org.sonar.plugins.php.api.Php; import org.sonar.plugins.php.api.PhpFile; import org.sonar.squid.measures.Metric; import org.sonar.squid.recognizer.CamelCaseDetector; import org.sonar.squid.recognizer.CodeRecognizer; import org.sonar.squid.recognizer.ContainsDetector; import org.sonar.squid.recognizer.Detector; import org.sonar.squid.recognizer.EndWithDetector; import org.sonar.squid.recognizer.KeywordsDetector; import org.sonar.squid.recognizer.LanguageFootprint; import org.sonar.squid.text.Source; @Phase(name = Phase.Name.PRE) // The NoSonarFilter must be fed before launching the violation engines public class NoSonarAndCommentedOutLocSensor implements Sensor { private static final double CODE_RECOGNIZER_SENSITIVITY = 0.9; private static final Logger LOG = LoggerFactory.getLogger(NoSonarAndCommentedOutLocSensor.class); /** * */ private final NoSonarFilter filter; /** * @param noSonarFilter */ public NoSonarAndCommentedOutLocSensor(NoSonarFilter noSonarFilter) { this.filter = noSonarFilter; } /** * @see org.sonar.api.batch.Sensor#analyse(org.sonar.api.resources.Project, org.sonar.api.batch.SensorContext) */ public void analyse(Project project, SensorContext context) { ProjectFileSystem fileSystem = project.getFileSystem(); List<File> sourceFiles = fileSystem.getSourceFiles(PHP); List<File> directories = fileSystem.getSourceDirs(); for (File file : sourceFiles) { PhpFile phpFile = PhpFile.getInstance(project).fromIOFile(file, directories, false); if (phpFile != null) { Source source = analyseSourceCode(file); if (source != null) { filter.addResource(phpFile, source.getNoSonarTagLines()); double measure = source.getMeasure(Metric.COMMENTED_OUT_CODE_LINES); context.saveMeasure(phpFile, CoreMetrics.COMMENTED_OUT_CODE_LINES, measure); } } } } protected static Source analyseSourceCode(File file) { Source result = null; try { result = new Source(new FileReader(file), new CodeRecognizer(CODE_RECOGNIZER_SENSITIVITY, new PhpLanguageFootprint())); } catch (FileNotFoundException e) { throw new SonarException("Unable to open file '" + file.getAbsolutePath() + "'", e); } catch (RuntimeException rEx) { LOG.error("error while parsing file '" + file.getAbsolutePath() + "'", rEx); } return result; } /** * @see org.sonar.api.batch.CheckProject#shouldExecuteOnProject(org.sonar.api.resources.Project) */ public boolean shouldExecuteOnProject(Project project) { return PHP.equals(project.getLanguage()); } private static class PhpLanguageFootprint implements LanguageFootprint { private static final double CAMEL_CASE_PROBABILITY = 0.5; private static final double CONDITIONAL_PROBABILITY = 0.95; private static final double PHP_KEYWORDS_PROBABILITY = 0.3; private static final double BOOLEAN_OPERATOR_PROBABILITY = 0.7; private static final double END_WITH_DETECTOR_PROBABILITY = 0.95; private final Set<Detector> detectors = new HashSet<Detector>(); public PhpLanguageFootprint() { detectors.add(new EndWithDetector(END_WITH_DETECTOR_PROBABILITY, '}', ';', '{')); detectors.add(new KeywordsDetector(BOOLEAN_OPERATOR_PROBABILITY, "||", "&&")); detectors.add(new KeywordsDetector(PHP_KEYWORDS_PROBABILITY, Php.PHP_KEYWORDS_ARRAY)); detectors.add(new ContainsDetector(CONDITIONAL_PROBABILITY, "++", "for(", "if(", "while(", "catch(", "switch(", "try{", "else{")); detectors.add(new CamelCaseDetector(CAMEL_CASE_PROBABILITY)); } /** * @see org.sonar.squid.recognizer.LanguageFootprint#getDetectors() */ public Set<Detector> getDetectors() { return detectors; } } }