diff --git a/cxx-checks/pom.xml b/cxx-checks/pom.xml index 40a6f298b0..c76821c5a8 100644 --- a/cxx-checks/pom.xml +++ b/cxx-checks/pom.xml @@ -51,4 +51,84 @@ test + + + + + + + com.googlecode.maven-download-plugin + download-maven-plugin + 1.4.0 + + + download-eclipse-cdt-core + generate-sources + + wget + + + https://ftp.halifax.rwth-aachen.de/eclipse/tools/cdt/releases/9.5/cdt-9.5.2/plugins/org.eclipse.cdt.core_6.5.0.201807181141.jar + org.eclipse.cdt.core_6.5.0.201807181141.jar + ${java.io.tmpdir} + 9fc8edd950a527149ae33e79bc858c91 + + + + + + com.googlecode.maven-download-plugin + download-maven-plugin + 1.4.0 + + + download-eclipse-cdt-core-sources + generate-sources + + wget + + + https://ftp.halifax.rwth-aachen.de/eclipse/tools/cdt/releases/9.5/cdt-9.5.2/plugins/org.eclipse.cdt.core.source_6.5.0.201807181141.jar + org.eclipse.cdt.core.source_6.5.0.201807181141.jar + ${java.io.tmpdir} + 9ac89ce26712bf0b078aa178315daa15 + + + + + + org.apache.maven.plugins + maven-install-plugin + 2.5.1 + + org.eclipse.cdt + org.eclipse.cdt.core + 6.5.0 + jar + ${java.io.tmpdir}/org.eclipse.cdt.core_6.5.0.201807181141.jar + ${java.io.tmpdir}/org.eclipse.cdt.core.source_6.5.0.201807181141.jar + true + ${java.io.tmpdir}/sonar-cxx-local-maven/ + true + + + + install-eclipse-cdt-core + + install-file + + generate-sources + + + + + + diff --git a/cxx-sensors/pom.xml b/cxx-sensors/pom.xml index beca8adc80..450af06397 100644 --- a/cxx-sensors/pom.xml +++ b/cxx-sensors/pom.xml @@ -15,6 +15,14 @@ target/${project.artifactId}-${project.version}.jar + + + + sonar-cxx-local-maven + file://${java.io.tmpdir}/sonar-cxx-local-maven/ + + + org.sonarsource.sonarqube @@ -100,5 +108,21 @@ assertj-core test + + + org.eclipse.cdt + org.eclipse.cdt.core + 6.5.0 + + + org.eclipse.platform + org.eclipse.core.runtime + 3.14.0 + + + com.ibm.icu + icu4j + 3.4.4 + diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/eclipsecdt/EclipseCDTException.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/eclipsecdt/EclipseCDTException.java new file mode 100644 index 0000000000..defed6395d --- /dev/null +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/eclipsecdt/EclipseCDTException.java @@ -0,0 +1,33 @@ +/* + * Sonar C++ Plugin (Community) + * Copyright (C) 2010-2018 SonarOpenCommunity + * http://github.com/SonarOpenCommunity/sonar-cxx + * + * 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.cxx.sensors.eclipsecdt; + +public class EclipseCDTException extends Exception { + + private static final long serialVersionUID = 4069232895507964456L; + + EclipseCDTException(String message) { + super(message); + } + + public EclipseCDTException(String message, Throwable e) { + super(message, e); + } +} diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/eclipsecdt/EclipseCDTParser.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/eclipsecdt/EclipseCDTParser.java new file mode 100644 index 0000000000..4f78f8818f --- /dev/null +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/eclipsecdt/EclipseCDTParser.java @@ -0,0 +1,233 @@ +/* + * Sonar C++ Plugin (Community) + * Copyright (C) 2010-2018 SonarOpenCommunity + * http://github.com/SonarOpenCommunity/sonar-cxx + * + * 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.cxx.sensors.eclipsecdt; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.io.FileUtils; +import org.eclipse.cdt.core.dom.ast.ASTGenericVisitor; +import org.eclipse.cdt.core.dom.ast.IASTDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTFileLocation; +import org.eclipse.cdt.core.dom.ast.IASTImageLocation; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTProblem; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.gnu.cpp.GPPLanguage; +import org.eclipse.cdt.core.index.IIndex; +import org.eclipse.cdt.core.index.IIndexFileLocation; +import org.eclipse.cdt.core.parser.FileContent; +import org.eclipse.cdt.core.parser.IParserLogService; +import org.eclipse.cdt.core.parser.IScannerInfo; +import org.eclipse.cdt.core.parser.IncludeFileContentProvider; +import org.eclipse.cdt.core.parser.ScannerInfo; +import org.eclipse.cdt.core.parser.util.CharArrayUtils; +import org.eclipse.cdt.internal.core.parser.IMacroDictionary; +import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent; +import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContentProvider; +import org.eclipse.core.runtime.CoreException; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; + +public class EclipseCDTParser { + + private static final Logger LOG = Loggers.get(EclipseCDTParser.class); + + /** + * Naive implementation for IncludeFileContentProvider, see + * {@link org.eclipse.cdt.internal.core.parser.EmptyFilesProvider} + * + * InernalFile is a source file from the eclipse workspace. Usage of + * FileContent.createForExternalFileLocation() seems to be inappropropriate. + */ + private static final IncludeFileContentProvider INCLUDE_FILE_PROVIDER = new InternalFileContentProvider() { + private InternalFileContent getContentUncached(String path) { + if (!getInclusionExists(path)) { + return null; + } + + char[] contents = CharArrayUtils.EMPTY; + try { + contents = FileUtils.readFileToString(new File(path), Charset.defaultCharset()).toCharArray(); + } catch (IOException e) { + LOG.debug("EclipseCDTParser: Unable to read the content of {}", path); + } + return (InternalFileContent) FileContent.create(path, contents); + } + + @Override + public InternalFileContent getContentForInclusion(String path, IMacroDictionary macroDictionary) { + return getContentUncached(path); + } + + @Override + public InternalFileContent getContentForInclusion(IIndexFileLocation ifl, String astPath) { + return getContentUncached(astPath); + } + }; + + private static final IParserLogService LOG_ADAPTER = new IParserLogService() { + @Override + public boolean isTracing() { + return LOG.isDebugEnabled(); + } + + @Override + public void traceLog(String msg) { + LOG.debug(msg); + } + }; + + private final String sourcePath; + private final IASTTranslationUnit translationUnit; + private final LinebasedOffsetTranslator offsetTranslator; + + public EclipseCDTParser(String path, String[] includePaths) throws EclipseCDTException { + sourcePath = path; + try { + offsetTranslator = new LinebasedOffsetTranslator(path); + } catch (IOException e) { + throw new EclipseCDTException("Unable to read file " + path, e); + } + + final IIndex ignoreIndex = null; + final Map ignoreDefinedMacros = null; + final int noSpecialParseOptions = 0; + IScannerInfo scannerInfo = new ScannerInfo(ignoreDefinedMacros, includePaths); + FileContent fileContent = FileContent.createForExternalFileLocation(path); + + try { + translationUnit = GPPLanguage.getDefault().getASTTranslationUnit(fileContent, scannerInfo, INCLUDE_FILE_PROVIDER, + ignoreIndex, noSpecialParseOptions, LOG_ADAPTER); + } catch (CoreException e) { + throw new EclipseCDTException("Unable to parse file " + path, e); + } + + logPreprocessorProblems(); + } + + private void logPreprocessorProblems() { + if (LOG.isDebugEnabled()) { + for (IASTProblem problem : translationUnit.getPreprocessorProblems()) { + LOG.debug(problem.getMessageWithLocation()); + } + } + } + + /** + * Traverse the given top-level declaration and find all IASTName nodes, which + * describe this or arbitrary nested declaration + */ + private Set getDeclarationNameNodes(IASTDeclaration declaration) { + final Set declarationNameNodes = new HashSet<>(); + declaration.accept(new ASTGenericVisitor(true) { + { + includeInactiveNodes = true; + } + + @Override + public int visit(IASTName name) { + if (name.isDeclaration()) { + declarationNameNodes.add(name); + } + return PROCESS_CONTINUE; + } + + }); + + return declarationNameNodes; + } + + private LinebasedTextRange newRange(IASTFileLocation location) throws EclipseCDTException { + int globalOffset = location.getNodeOffset(); + int length = location.getNodeLength(); + LinebasedTextPointer start = offsetTranslator.newPointer(globalOffset); + LinebasedTextPointer end = offsetTranslator.newPointer(globalOffset + length); + return new LinebasedTextRange(start, end); + } + + private LinebasedTextRange newRange(IASTName astName) throws EclipseCDTException { + try { + return newRange(astName.getFileLocation()); + } catch (EclipseCDTException e) { + throw new EclipseCDTException("Unable to create LinebasedTextRange for symbol [name=" + astName + ", location=" + + astName.getFileLocation() + ", file=" + sourcePath + ", error=" + e.getMessage() + "]", e); + } + } + + private Boolean isLocatedInFile(IASTName name) { + if (name == null || !name.isPartOfTranslationUnitFile()) { + return false; + } + IASTFileLocation fileLocation = name.getFileLocation(); + return fileLocation != null && sourcePath.equals(fileLocation.getFileName()) && fileLocation.getNodeLength() > 0; + } + + private Boolean isPartOfSymbolTable(IASTName name) { + if (!isLocatedInFile(name)) { + return false; + } + IASTImageLocation imageLocation = name.getImageLocation(); + return (imageLocation != null) && (imageLocation.getLocationKind() == IASTImageLocation.REGULAR_CODE); + } + + public Map> generateSymbolTable() throws EclipseCDTException { + // collect all declarations from the translation unit + IASTDeclaration[] declarations = translationUnit.getDeclarations(true); + final Set declarationNames = new HashSet<>(); + for (IASTDeclaration declaration : declarations) { + declarationNames.addAll(getDeclarationNameNodes(declaration)); + } + + // collect all references to the declarations + Map> table = new HashMap<>(); + for (IASTName declarationName : declarationNames) { + IBinding binding = declarationName.resolveBinding(); + if (binding == null) { + continue; + } + + Set references = new HashSet<>(); + for (IASTName referenceName : translationUnit.getReferences(binding)) { + if (referenceName != null && isPartOfSymbolTable(referenceName)) { + references.add(newRange(referenceName)); + } + } + + if (isPartOfSymbolTable(declarationName)) { + table.put(newRange(declarationName), references); + } else if (!references.isEmpty()) { + LinebasedTextRange randomReference = references.iterator().next(); + references.remove(randomReference); + table.put(randomReference, references); + } else { + continue; + } + + } + return table; + } +} diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/eclipsecdt/LinebasedOffsetTranslator.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/eclipsecdt/LinebasedOffsetTranslator.java new file mode 100644 index 0000000000..9e8cabafb5 --- /dev/null +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/eclipsecdt/LinebasedOffsetTranslator.java @@ -0,0 +1,77 @@ +/* + * Sonar C++ Plugin (Community) + * Copyright (C) 2010-2018 SonarOpenCommunity + * http://github.com/SonarOpenCommunity/sonar-cxx + * + * 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.cxx.sensors.eclipsecdt; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Eclipse CDT operates with absolute offsets in order to address tokens in the + * source file. We use binary search over the line offsets for the conversion to + * the SonarQube format (see {@link TextPointer} ) + * + * Inspired by {@link DefaultInputFile} + */ +public class LinebasedOffsetTranslator { + private final Integer lineOffsets[]; + private final Integer maxOffset; + + LinebasedOffsetTranslator(String path) throws IOException { + lineOffsets = readLineOffsets(path); + maxOffset = lineOffsets[lineOffsets.length - 1]; + } + + private static Integer[] readLineOffsets(String path) throws IOException { + List lineOffsetsList = new ArrayList<>(); + + lineOffsetsList.add(0); + int currentOffset = 0; + + try (BufferedReader br = new BufferedReader(new FileReader(new File(path)))) { + for (String line; (line = br.readLine()) != null;) { + // 1 stands for the length of '\n' + currentOffset = currentOffset + line.length() + 1; + lineOffsetsList.add(currentOffset); + } + } + + return lineOffsetsList.toArray(new Integer[lineOffsetsList.size()]); + } + + private Integer findLine(Integer globalOffset) { + return Math.abs(Arrays.binarySearch(lineOffsets, globalOffset) + 1); + } + + public LinebasedTextPointer newPointer(int globalOffset) throws EclipseCDTException { + if (globalOffset < 0 || globalOffset > maxOffset) { + throw new EclipseCDTException(Integer.valueOf(globalOffset).toString() + " must be in range [0, " + + Integer.valueOf(maxOffset).toString() + "]"); + } + + int line = findLine(globalOffset); + int startLineOffset = lineOffsets[line - 1]; + return new LinebasedTextPointer(line, globalOffset - startLineOffset); + } +} diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/eclipsecdt/LinebasedTextPointer.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/eclipsecdt/LinebasedTextPointer.java new file mode 100644 index 0000000000..9d7d06bcb8 --- /dev/null +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/eclipsecdt/LinebasedTextPointer.java @@ -0,0 +1,76 @@ +/* + * Sonar C++ Plugin (Community) + * Copyright (C) 2010-2018 SonarOpenCommunity + * http://github.com/SonarOpenCommunity/sonar-cxx + * + * 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.cxx.sensors.eclipsecdt; + +public class LinebasedTextPointer implements Comparable { + private final int line; + private final int lineOffset; + + public LinebasedTextPointer(int line, int lineOffset) { + this.line = line; + this.lineOffset = lineOffset; + } + + public int line() { + return line; + } + + public int lineOffset() { + return lineOffset; + } + + @Override + public String toString() { + return "LinebasedTextPointer [line=" + line + ", lineOffset=" + lineOffset + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + line; + result = prime * result + lineOffset; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + LinebasedTextPointer other = (LinebasedTextPointer) obj; + if (line != other.line) + return false; + if (lineOffset != other.lineOffset) + return false; + return true; + } + + @Override + public int compareTo(LinebasedTextPointer o) { + if (this.line == o.line()) { + return Integer.compare(this.lineOffset, o.lineOffset()); + } + return Integer.compare(this.line, o.line()); + } +} diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/eclipsecdt/LinebasedTextRange.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/eclipsecdt/LinebasedTextRange.java new file mode 100644 index 0000000000..3fd1c3d52d --- /dev/null +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/eclipsecdt/LinebasedTextRange.java @@ -0,0 +1,84 @@ +/* + * Sonar C++ Plugin (Community) + * Copyright (C) 2010-2018 SonarOpenCommunity + * http://github.com/SonarOpenCommunity/sonar-cxx + * + * 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.cxx.sensors.eclipsecdt; + +public class LinebasedTextRange implements Comparable { + private final LinebasedTextPointer start; + private final LinebasedTextPointer end; + + public LinebasedTextRange(LinebasedTextPointer start, LinebasedTextPointer end) { + this.start = start; + this.end = end; + } + + public LinebasedTextPointer start() { + return start; + } + + public LinebasedTextPointer end() { + return end; + } + + @Override + public String toString() { + return "LinebasedTextRange [start=" + start + ", end=" + end + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((end == null) ? 0 : end.hashCode()); + result = prime * result + ((start == null) ? 0 : start.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + LinebasedTextRange other = (LinebasedTextRange) obj; + if (end == null) { + if (other.end != null) + return false; + } else if (!end.equals(other.end)) + return false; + if (start == null) { + if (other.start != null) + return false; + } else if (!start.equals(other.start)) + return false; + return true; + } + + @Override + public int compareTo(LinebasedTextRange o) { + int i = start().compareTo(o.start()); + if (i == 0) { + return end().compareTo(o.end()); + } + return i; + } + +} \ No newline at end of file diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/squid/CxxSquidSensor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/squid/CxxSquidSensor.java index f59c6bb93e..c900dc4109 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/squid/CxxSquidSensor.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/squid/CxxSquidSensor.java @@ -51,6 +51,7 @@ import org.sonar.cxx.sensors.utils.CxxReportSensor; import org.sonar.cxx.sensors.utils.JsonCompilationDatabase; import org.sonar.cxx.sensors.visitors.CxxCpdVisitor; +import org.sonar.cxx.sensors.visitors.CxxEclipseCDTVisitor; import org.sonar.cxx.sensors.visitors.CxxFileLinesVisitor; import org.sonar.cxx.sensors.visitors.CxxHighlighterVisitor; import org.sonar.cxx.utils.CxxReportIssue; @@ -126,9 +127,11 @@ public void describe(SensorDescriptor descriptor) { @Override public void execute(SensorContext context) { + CxxConfiguration cxxConf = createConfiguration(context.fileSystem(), context); List> visitors = new ArrayList<>((Collection) checks.all()); visitors.add(new CxxHighlighterVisitor(context)); visitors.add(new CxxFileLinesVisitor(language, fileLinesContextFactory, context)); + visitors.add(new CxxEclipseCDTVisitor(context, cxxConf)); visitors.add( new CxxCpdVisitor( @@ -136,7 +139,6 @@ public void execute(SensorContext context) { this.language.getBooleanOption(CPD_IGNORE_LITERALS_KEY).orElse(Boolean.FALSE), this.language.getBooleanOption(CPD_IGNORE_IDENTIFIERS_KEY).orElse(Boolean.FALSE))); - CxxConfiguration cxxConf = createConfiguration(context.fileSystem(), context); AstScanner scanner = CxxAstScanner.create(this.language, cxxConf, visitors.toArray(new SquidAstVisitor[visitors.size()])); diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/visitors/CxxEclipseCDTVisitor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/visitors/CxxEclipseCDTVisitor.java new file mode 100644 index 0000000000..12f7826e58 --- /dev/null +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/visitors/CxxEclipseCDTVisitor.java @@ -0,0 +1,110 @@ +/* + * Sonar C++ Plugin (Community) + * Copyright (C) 2010-2018 SonarOpenCommunity + * http://github.com/SonarOpenCommunity/sonar-cxx + * + * 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.cxx.sensors.visitors; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.annotation.Nullable; + +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.sensor.SensorContext; +import org.sonar.api.batch.sensor.symbol.NewSymbol; +import org.sonar.api.batch.sensor.symbol.NewSymbolTable; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; +import org.sonar.cxx.CxxCompilationUnitSettings; +import org.sonar.cxx.CxxConfiguration; +import org.sonar.cxx.sensors.eclipsecdt.EclipseCDTException; +import org.sonar.cxx.sensors.eclipsecdt.EclipseCDTParser; +import org.sonar.cxx.sensors.eclipsecdt.LinebasedTextRange; +import org.sonar.cxx.sensors.utils.CxxUtils; +import org.sonar.squidbridge.SquidAstVisitor; + +import com.sonar.sslr.api.AstNode; +import com.sonar.sslr.api.AstVisitor; +import com.sonar.sslr.api.Grammar; + +public class CxxEclipseCDTVisitor extends SquidAstVisitor implements AstVisitor { + + private static final Logger LOG = Loggers.get(CxxEclipseCDTVisitor.class); + + private final SensorContext context; + private final CxxConfiguration configuration; + + public CxxEclipseCDTVisitor(SensorContext context, CxxConfiguration cxxConfiguration) { + this.configuration = cxxConfiguration; + this.context = context; + } + + private String[] getIncludePaths(String compilationUnit) { + CxxCompilationUnitSettings cus = configuration.getCompilationUnitSettings(compilationUnit); + if (cus != null) { + List includes = cus.getIncludes(); + return cus.getIncludes().toArray(new String[includes.size()]); + } else { + return new String[0]; + } + } + + @Override + public void visitFile(@Nullable AstNode astNode) { + InputFile inputFile = context.fileSystem() + .inputFile(context.fileSystem().predicates().is(getContext().getFile().getAbsoluteFile())); + + if (inputFile == null) { + LOG.warn("Unable to locate the source file " + getContext().getFile().getAbsoluteFile().getAbsolutePath()); + } + + try { + String path = inputFile.uri().getPath(); + EclipseCDTParser parser = new EclipseCDTParser(path, getIncludePaths(path)); + + Map> table = parser.generateSymbolTable(); + + NewSymbolTable newSymbolTable = context.newSymbolTable(); + newSymbolTable.onFile(inputFile); + for (Map.Entry> entry : table.entrySet()) { + LinebasedTextRange declaration = entry.getKey(); + Set references = entry.getValue(); + + NewSymbol declarationSymbol = newSymbolTable.newSymbol(declaration.start().line(), + declaration.start().lineOffset(), declaration.end().line(), declaration.end().lineOffset()); + for (LinebasedTextRange reference : references) { + try { + declarationSymbol.newReference(reference.start().line(), reference.start().lineOffset(), + reference.end().line(), reference.end().lineOffset()); + } catch (Exception e) { + LOG.debug("Couldn't add a symbol reference because of {}", CxxUtils.getStackTrace(e)); + } + } + } + + newSymbolTable.save(); + + } catch (EclipseCDTException e) { + LOG.warn("EclipseCDT failure: " + CxxUtils.getStackTrace(e)); + } catch (Exception e) { + LOG.warn("Generic exception: " + CxxUtils.getStackTrace(e)); + } + } + +} diff --git a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/eclipsecdt/EclipseCDTParserTest.java b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/eclipsecdt/EclipseCDTParserTest.java new file mode 100644 index 0000000000..740e019237 --- /dev/null +++ b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/eclipsecdt/EclipseCDTParserTest.java @@ -0,0 +1,182 @@ +/* + * Sonar C++ Plugin (Community) + * Copyright (C) 2010-2018 SonarOpenCommunity + * http://github.com/SonarOpenCommunity/sonar-cxx + * + * 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.cxx.sensors.eclipsecdt; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.junit.Test; +import org.sonar.cxx.sensors.utils.TestUtils; + +public class EclipseCDTParserTest { + + String markToken(List lines, LinebasedTextRange range, boolean asDeclaration) { + // declarations/references from our test are placed in a single line + assertThat(range.start().line()).isEqualTo(range.end().line()); + + int line = range.start().line(); + int offsetFrom = range.start().lineOffset(); + int offsetTo = range.end().lineOffset(); + assertThat(offsetFrom).isLessThan(offsetTo); + + StringBuilder sb = new StringBuilder(); + sb.append(line).append(": "); + + int prefixLength = sb.length(); + + sb.append(lines.get(line - 1)).append("\n"); + for (int i = 0; i < offsetFrom + prefixLength; i++) { + sb.append(' '); + } + for (int i = 0; i < (offsetTo - offsetFrom); i++) { + if (asDeclaration) { + sb.append('!'); + } else { + sb.append('^'); + } + } + sb.append("\n"); + return sb.toString(); + } + + private String dumpSymbolTable(File target, Map> table) + throws IOException { + StringBuilder actualFullDump = new StringBuilder(); + List content = Files.readAllLines(target.toPath()); + List keys = sort(table.keySet()); + for (LinebasedTextRange key : keys) { + actualFullDump.append("DECLARATION:").append("\n"); + actualFullDump.append(markToken(content, key, true)); + actualFullDump.append("REFERENCES:").append("\n"); + List values = sort(table.get(key)); + for (LinebasedTextRange value : values) { + actualFullDump.append(markToken(content, value, false)); + } + actualFullDump.append("\n\n"); + } + return actualFullDump.toString(); + } + + /** + * sort for reproducable comparison + */ + static List sort(Set s) { + List l = new ArrayList(s); + Collections.sort(l); + return l; + } + + @Test + public void testInlineDeclarations() throws IOException, EclipseCDTException { + File baseDir = TestUtils.loadResource("/org/sonar/cxx/eclipsecdt"); + File target = new File(baseDir, "symbols_inline.cc"); + + File expectedDeclartaions = new File(baseDir, "symbols_inline_declarations.txt"); + + List content = Files.readAllLines(target.toPath()); + + EclipseCDTParser parser = new EclipseCDTParser(target.getAbsolutePath(), new String[0]); + Map> table = parser.generateSymbolTable(); + + StringBuilder actualDeclarationsDump = new StringBuilder(); + List keys = sort(table.keySet()); + for (LinebasedTextRange key : keys) { + actualDeclarationsDump.append(markToken(content, key, true)); + } + + assertThat(actualDeclarationsDump.toString()) + .isEqualTo(new String(Files.readAllBytes(expectedDeclartaions.toPath()), "UTF-8")); + + } + + @Test + public void testInlineReferences() throws IOException, EclipseCDTException { + File baseDir = TestUtils.loadResource("/org/sonar/cxx/eclipsecdt"); + File target = new File(baseDir, "symbols_inline.cc"); + + File expectedReferences = new File(baseDir, "symbols_inline_references.txt"); + + EclipseCDTParser parser = new EclipseCDTParser(target.getAbsolutePath(), new String[0]); + Map> table = parser.generateSymbolTable(); + + String actualFullDump = dumpSymbolTable(target, table); + + assertThat(actualFullDump).isEqualTo(new String(Files.readAllBytes(expectedReferences.toPath()), "UTF-8")); + } + + @Test + public void testMissingInclude() throws IOException, EclipseCDTException { + File baseDir = TestUtils.loadResource("/org/sonar/cxx/eclipsecdt"); + File target = new File(baseDir, "symbols.cc"); + + File expectedReferences = new File(baseDir, "symbols_noinclude_references.txt"); + // symbols_noinclude_references.cc contains a non-trivial include, but the + // list of include directories is empty + String[] includePaths = new String[0]; + EclipseCDTParser parser = new EclipseCDTParser(target.getAbsolutePath(), includePaths); + Map> table = parser.generateSymbolTable(); + + String actualFullDump = dumpSymbolTable(target, table); + + assertThat(actualFullDump).isEqualTo(new String(Files.readAllBytes(expectedReferences.toPath()), "UTF-8")); + } + + @Test + public void testCorrectInclude() throws IOException, EclipseCDTException { + File baseDir = TestUtils.loadResource("/org/sonar/cxx/eclipsecdt"); + File target = new File(baseDir, "symbols.cc"); + + File expectedReferences = new File(baseDir, "symbols_include_references.txt"); + // symbols_noinclude_references.cc contains a non-trivial include, but the + // pass a correct (relative) include path + // now all symbols declared in the header are recognized in the *.cc file + // too + String[] includePaths = { "includ3path/" }; + EclipseCDTParser parser = new EclipseCDTParser(target.getAbsolutePath(), includePaths); + Map> table = parser.generateSymbolTable(); + + String actualFullDump = dumpSymbolTable(target, table); + + assertThat(actualFullDump).isEqualTo(new String(Files.readAllBytes(expectedReferences.toPath()), "UTF-8")); + } + + @Test + public void testErrorRecovery() throws EclipseCDTException, IOException { + File baseDir = TestUtils.loadResource("/org/sonar/cxx/eclipsecdt"); + File target = new File(baseDir, "syntaxerror.cc"); + + File expectedReferences = new File(baseDir, "syntaxerror_references.txt"); + EclipseCDTParser parser = new EclipseCDTParser(target.getAbsolutePath(), new String[0]); + Map> table = parser.generateSymbolTable(); + + String actualFullDump = dumpSymbolTable(target, table); + + assertThat(actualFullDump).isEqualTo(new String(Files.readAllBytes(expectedReferences.toPath()), "UTF-8")); + } + +} diff --git a/cxx-sensors/src/test/resources/org/sonar/cxx/eclipsecdt/includ3path/symbols.hh b/cxx-sensors/src/test/resources/org/sonar/cxx/eclipsecdt/includ3path/symbols.hh new file mode 100644 index 0000000000..aaeb4a5876 --- /dev/null +++ b/cxx-sensors/src/test/resources/org/sonar/cxx/eclipsecdt/includ3path/symbols.hh @@ -0,0 +1,35 @@ +// MotorController.h + +enum Direction +{ + Forward, Reverse +}; + +enum Velocity +{ + Accelerate, Decelerate +}; + +extern int global1 = 0; + +// This class is exported from the MotorController.dll +class CMotorController +{ +private: + int speed; + Direction direction; + bool limiter; + Velocity velocity; + +public: + CMotorController( void ); + + void setSpeed( int speed ); + int getSpeed(); + void checkSpeed(); + bool getLimiter(); + Velocity getVelocity(); + + void setDirection( Direction direction ); + Direction getDirection(); +}; diff --git a/cxx-sensors/src/test/resources/org/sonar/cxx/eclipsecdt/symbols.cc b/cxx-sensors/src/test/resources/org/sonar/cxx/eclipsecdt/symbols.cc new file mode 100644 index 0000000000..4e5127412c --- /dev/null +++ b/cxx-sensors/src/test/resources/org/sonar/cxx/eclipsecdt/symbols.cc @@ -0,0 +1,87 @@ +#include "symbols.hh" +// this include must be resolved in one of specified include directories + +// MotorController.cpp : Defines the exported functions for the DLL application. + +int global1 = 0; + +constexpr int factorial( int n ) +{ + return n <= 1 ? 1 : ( n * factorial( n - 1 ) ); +} + +CMotorController::CMotorController() : + speed( 0 ), direction( Forward ), limiter( false ), velocity( Decelerate ) +{ +} + +void CMotorController::setSpeed( int speed ) +{ + this->speed = speed; +} + +int CMotorController::getSpeed() +{ + return speed; +} + +void CMotorController::setDirection( Direction direction ) +{ + this->direction = direction; +} + +void CMotorController::setDirectionAndSpeed( Direction direction, int speed ) +{ + this->direction = direction; + this->speed = speed; +} + +Direction CMotorController::getDirection() +{ + return direction; +} + +bool CMotorController::getLimiter() +{ + return limiter; +} + +Velocity CMotorController::getVelocity() +{ + return Velocity(); +} + +void CMotorController::checkSpeed() +{ + global1 = 1; + int test1 = global1; + + switch ( speed ) + { + case 10: + limiter = false; + velocity = Accelerate; + break; + case 50: + { + limiter = true; + velocity = Decelerate; + } + break; + default: + factorial( 4 ); + + } +} + +template< typename T > +T* factoryFunction() +{ + return new T(); +} + +void main() +{ + factoryFunction< CMotorController >()->setDirection( Direction::Forward ); +} + diff --git a/cxx-sensors/src/test/resources/org/sonar/cxx/eclipsecdt/symbols_include_references.txt b/cxx-sensors/src/test/resources/org/sonar/cxx/eclipsecdt/symbols_include_references.txt new file mode 100644 index 0000000000..8844ec5414 --- /dev/null +++ b/cxx-sensors/src/test/resources/org/sonar/cxx/eclipsecdt/symbols_include_references.txt @@ -0,0 +1,342 @@ +DECLARATION: +6: int global1 = 0; + !!!!!!! +REFERENCES: +56: global1 = 1; + ^^^^^^^ +57: int test1 = global1; + ^^^^^^^ + + +DECLARATION: +8: constexpr int factorial( int n ) + !!!!!!!!! +REFERENCES: +10: return n <= 1 ? 1 : ( n * factorial( n - 1 ) ); + ^^^^^^^^^ +72: factorial( 4 ); + ^^^^^^^^^ + + +DECLARATION: +8: constexpr int factorial( int n ) + ! +REFERENCES: +10: return n <= 1 ? 1 : ( n * factorial( n - 1 ) ); + ^ +10: return n <= 1 ? 1 : ( n * factorial( n - 1 ) ); + ^ +10: return n <= 1 ? 1 : ( n * factorial( n - 1 ) ); + ^ + + +DECLARATION: +13: CMotorController::CMotorController() : + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +13: CMotorController::CMotorController() : + !!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +14: speed( 0 ), direction( Forward ), limiter( false ), velocity( Decelerate ) + !!!!! +REFERENCES: +20: this->speed = speed; + ^^^^^ +25: return speed; + ^^^^^ +36: this->speed = speed; + ^^^^^ +59: switch ( speed ) + ^^^^^ + + +DECLARATION: +14: speed( 0 ), direction( Forward ), limiter( false ), velocity( Decelerate ) + !!!!!!!!! +REFERENCES: +30: this->direction = direction; + ^^^^^^^^^ +35: this->direction = direction; + ^^^^^^^^^ +41: return direction; + ^^^^^^^^^ + + +DECLARATION: +14: speed( 0 ), direction( Forward ), limiter( false ), velocity( Decelerate ) + !!!!!!! +REFERENCES: +85: factoryFunction< CMotorController >()->setDirection( Direction::Forward ); + ^^^^^^^ + + +DECLARATION: +14: speed( 0 ), direction( Forward ), limiter( false ), velocity( Decelerate ) + !!!!!!! +REFERENCES: +46: return limiter; + ^^^^^^^ +62: limiter = false; + ^^^^^^^ +67: limiter = true; + ^^^^^^^ + + +DECLARATION: +18: void CMotorController::setSpeed( int speed ) + !!!!!!!!!!!!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +18: void CMotorController::setSpeed( int speed ) + !!!!!!!! +REFERENCES: + + +DECLARATION: +18: void CMotorController::setSpeed( int speed ) + !!!!! +REFERENCES: +20: this->speed = speed; + ^^^^^ + + +DECLARATION: +20: this->speed = speed; + !!!!! +REFERENCES: + + +DECLARATION: +23: int CMotorController::getSpeed() + !!!!!!!!!!!!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +23: int CMotorController::getSpeed() + !!!!!!!! +REFERENCES: + + +DECLARATION: +28: void CMotorController::setDirection( Direction direction ) + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +REFERENCES: +85: factoryFunction< CMotorController >()->setDirection( Direction::Forward ); + ^^^^^^^^^^^^ + + +DECLARATION: +28: void CMotorController::setDirection( Direction direction ) + !!!!!!!!!!!! +REFERENCES: +85: factoryFunction< CMotorController >()->setDirection( Direction::Forward ); + ^^^^^^^^^^^^ + + +DECLARATION: +28: void CMotorController::setDirection( Direction direction ) + !!!!!!!!! +REFERENCES: +33: void CMotorController::setDirectionAndSpeed( Direction direction, int speed ) + ^^^^^^^^^ +39: Direction CMotorController::getDirection() + ^^^^^^^^^ +85: factoryFunction< CMotorController >()->setDirection( Direction::Forward ); + ^^^^^^^^^ + + +DECLARATION: +28: void CMotorController::setDirection( Direction direction ) + !!!!!!!!! +REFERENCES: +30: this->direction = direction; + ^^^^^^^^^ + + +DECLARATION: +30: this->direction = direction; + !!!!!!!!! +REFERENCES: + + +DECLARATION: +33: void CMotorController::setDirectionAndSpeed( Direction direction, int speed ) + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +33: void CMotorController::setDirectionAndSpeed( Direction direction, int speed ) + !!!!!!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +33: void CMotorController::setDirectionAndSpeed( Direction direction, int speed ) + !!!!!!!!! +REFERENCES: +35: this->direction = direction; + ^^^^^^^^^ + + +DECLARATION: +33: void CMotorController::setDirectionAndSpeed( Direction direction, int speed ) + !!!!! +REFERENCES: +36: this->speed = speed; + ^^^^^ + + +DECLARATION: +39: Direction CMotorController::getDirection() + !!!!!!!!!!!!!!!! +REFERENCES: +13: CMotorController::CMotorController() : + ^^^^^^^^^^^^^^^^ +18: void CMotorController::setSpeed( int speed ) + ^^^^^^^^^^^^^^^^ +23: int CMotorController::getSpeed() + ^^^^^^^^^^^^^^^^ +28: void CMotorController::setDirection( Direction direction ) + ^^^^^^^^^^^^^^^^ +33: void CMotorController::setDirectionAndSpeed( Direction direction, int speed ) + ^^^^^^^^^^^^^^^^ +44: bool CMotorController::getLimiter() + ^^^^^^^^^^^^^^^^ +49: Velocity CMotorController::getVelocity() + ^^^^^^^^^^^^^^^^ +54: void CMotorController::checkSpeed() + ^^^^^^^^^^^^^^^^ +85: factoryFunction< CMotorController >()->setDirection( Direction::Forward ); + ^^^^^^^^^^^^^^^^ + + +DECLARATION: +39: Direction CMotorController::getDirection() + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +39: Direction CMotorController::getDirection() + !!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +44: bool CMotorController::getLimiter() + !!!!!!!!!!!!!!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +44: bool CMotorController::getLimiter() + !!!!!!!!!! +REFERENCES: + + +DECLARATION: +49: Velocity CMotorController::getVelocity() + !!!!!!!! +REFERENCES: + + +DECLARATION: +49: Velocity CMotorController::getVelocity() + !!!!!!!!!!!!!!!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +49: Velocity CMotorController::getVelocity() + !!!!!!!!!!! +REFERENCES: + + +DECLARATION: +54: void CMotorController::checkSpeed() + !!!!!!!!!!!!!!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +54: void CMotorController::checkSpeed() + !!!!!!!!!! +REFERENCES: + + +DECLARATION: +56: global1 = 1; + !!!!!!! +REFERENCES: +57: int test1 = global1; + ^^^^^^^ + + +DECLARATION: +57: int test1 = global1; + !!!!! +REFERENCES: + + +DECLARATION: +63: velocity = Accelerate; + !!!!!!!! +REFERENCES: +14: speed( 0 ), direction( Forward ), limiter( false ), velocity( Decelerate ) + ^^^^^^^^ +68: velocity = Decelerate; + ^^^^^^^^ + + +DECLARATION: +63: velocity = Accelerate; + !!!!!!!!!! +REFERENCES: + + +DECLARATION: +68: velocity = Decelerate; + !!!!!!!!!! +REFERENCES: +14: speed( 0 ), direction( Forward ), limiter( false ), velocity( Decelerate ) + ^^^^^^^^^^ + + +DECLARATION: +77: template< typename T > + ! +REFERENCES: +78: T* factoryFunction() + ^ +80: return new T(); + ^ + + +DECLARATION: +78: T* factoryFunction() + !!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +83: void main() + !!!! +REFERENCES: + + +DECLARATION: +85: factoryFunction< CMotorController >()->setDirection( Direction::Forward ); + !!!!!!!!!!!! +REFERENCES: + + diff --git a/cxx-sensors/src/test/resources/org/sonar/cxx/eclipsecdt/symbols_inline.cc b/cxx-sensors/src/test/resources/org/sonar/cxx/eclipsecdt/symbols_inline.cc new file mode 100644 index 0000000000..17a8406b9f --- /dev/null +++ b/cxx-sensors/src/test/resources/org/sonar/cxx/eclipsecdt/symbols_inline.cc @@ -0,0 +1,118 @@ +// MotorController.h + +enum Direction +{ + Forward, Reverse +}; + +enum Velocity +{ + Accelerate, Decelerate +}; + +static int global1 = 0; + +// This class is exported from the MotorController.dll +class CMotorController +{ +private: + int speed; + Direction direction; + bool limiter; + Velocity velocity; + +public: + CMotorController( void ); + + void setSpeed( int speed ); + int getSpeed(); + void checkSpeed(); + bool getLimiter(); + Velocity getVelocity(); + + void setDirection( Direction direction ); + Direction getDirection(); +}; + +// MotorController.cpp : Defines the exported functions for the DLL application. + +constexpr int factorial( int n ) +{ + return n <= 1 ? 1 : ( n * factorial( n - 1 ) ); +} + +CMotorController::CMotorController() : + speed( 0 ), direction( Forward ), limiter( false ), velocity( Decelerate ) +{ +} + +void CMotorController::setSpeed( int speed ) +{ + this->speed = speed; +} + +int CMotorController::getSpeed() +{ + return speed; +} + +void CMotorController::setDirection( Direction direction ) +{ + this->direction = direction; +} + +void CMotorController::setDirectionAndSpeed( Direction direction, int speed ) +{ + this->direction = direction; + this->speed = speed; +} + +Direction CMotorController::getDirection() +{ + return direction; +} + +bool CMotorController::getLimiter() +{ + return limiter; +} + +Velocity CMotorController::getVelocity() +{ + return Velocity(); +} + +void CMotorController::checkSpeed() +{ + global1 = 1; + int test1 = global1; + + switch ( speed ) + { + case 10: + limiter = false; + velocity = Accelerate; + break; + case 50: + { + limiter = true; + velocity = Decelerate; + } + break; + default: + factorial( 4 ); + + } +} + +template< typename T > +T* factoryFunction() +{ + return new T(); +} + +void main() +{ + factoryFunction< CMotorController >()->setDirection( Direction::Forward ); +} + diff --git a/cxx-sensors/src/test/resources/org/sonar/cxx/eclipsecdt/symbols_inline_declarations.txt b/cxx-sensors/src/test/resources/org/sonar/cxx/eclipsecdt/symbols_inline_declarations.txt new file mode 100644 index 0000000000..cac5108084 --- /dev/null +++ b/cxx-sensors/src/test/resources/org/sonar/cxx/eclipsecdt/symbols_inline_declarations.txt @@ -0,0 +1,100 @@ +3: enum Direction + !!!!!!!!! +5: Forward, Reverse + !!!!!!! +5: Forward, Reverse + !!!!!!! +8: enum Velocity + !!!!!!!! +10: Accelerate, Decelerate + !!!!!!!!!! +10: Accelerate, Decelerate + !!!!!!!!!! +13: static int global1 = 0; + !!!!!!! +16: class CMotorController + !!!!!!!!!!!!!!!! +19: int speed; + !!!!! +20: Direction direction; + !!!!!!!!! +21: bool limiter; + !!!!!!! +22: Velocity velocity; + !!!!!!!! +25: CMotorController( void ); + !!!!!!!!!!!!!!!! +27: void setSpeed( int speed ); + !!!!!!!! +27: void setSpeed( int speed ); + !!!!! +28: int getSpeed(); + !!!!!!!! +29: void checkSpeed(); + !!!!!!!!!! +30: bool getLimiter(); + !!!!!!!!!! +31: Velocity getVelocity(); + !!!!!!!!!!! +33: void setDirection( Direction direction ); + !!!!!!!!!!!! +33: void setDirection( Direction direction ); + !!!!!!!!! +34: Direction getDirection(); + !!!!!!!!!!!! +39: constexpr int factorial( int n ) + !!!!!!!!! +39: constexpr int factorial( int n ) + ! +44: CMotorController::CMotorController() : + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +44: CMotorController::CMotorController() : + !!!!!!!!!!!!!!!! +49: void CMotorController::setSpeed( int speed ) + !!!!!!!!!!!!!!!!!!!!!!!!!! +49: void CMotorController::setSpeed( int speed ) + !!!!!!!! +49: void CMotorController::setSpeed( int speed ) + !!!!! +54: int CMotorController::getSpeed() + !!!!!!!!!!!!!!!!!!!!!!!!!! +54: int CMotorController::getSpeed() + !!!!!!!! +59: void CMotorController::setDirection( Direction direction ) + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +59: void CMotorController::setDirection( Direction direction ) + !!!!!!!!!!!! +59: void CMotorController::setDirection( Direction direction ) + !!!!!!!!! +64: void CMotorController::setDirectionAndSpeed( Direction direction, int speed ) + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +64: void CMotorController::setDirectionAndSpeed( Direction direction, int speed ) + !!!!!!!!!!!!!!!!!!!! +64: void CMotorController::setDirectionAndSpeed( Direction direction, int speed ) + !!!!!!!!! +64: void CMotorController::setDirectionAndSpeed( Direction direction, int speed ) + !!!!! +70: Direction CMotorController::getDirection() + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +70: Direction CMotorController::getDirection() + !!!!!!!!!!!! +75: bool CMotorController::getLimiter() + !!!!!!!!!!!!!!!!!!!!!!!!!!!! +75: bool CMotorController::getLimiter() + !!!!!!!!!! +80: Velocity CMotorController::getVelocity() + !!!!!!!!!!!!!!!!!!!!!!!!!!!!! +80: Velocity CMotorController::getVelocity() + !!!!!!!!!!! +85: void CMotorController::checkSpeed() + !!!!!!!!!!!!!!!!!!!!!!!!!!!! +85: void CMotorController::checkSpeed() + !!!!!!!!!! +88: int test1 = global1; + !!!!! +108: template< typename T > + ! +109: T* factoryFunction() + !!!!!!!!!!!!!!! +114: void main() + !!!! diff --git a/cxx-sensors/src/test/resources/org/sonar/cxx/eclipsecdt/symbols_inline_references.txt b/cxx-sensors/src/test/resources/org/sonar/cxx/eclipsecdt/symbols_inline_references.txt new file mode 100644 index 0000000000..18cc591f30 --- /dev/null +++ b/cxx-sensors/src/test/resources/org/sonar/cxx/eclipsecdt/symbols_inline_references.txt @@ -0,0 +1,418 @@ +DECLARATION: +3: enum Direction + !!!!!!!!! +REFERENCES: +20: Direction direction; + ^^^^^^^^^ +33: void setDirection( Direction direction ); + ^^^^^^^^^ +34: Direction getDirection(); + ^^^^^^^^^ +59: void CMotorController::setDirection( Direction direction ) + ^^^^^^^^^ +64: void CMotorController::setDirectionAndSpeed( Direction direction, int speed ) + ^^^^^^^^^ +70: Direction CMotorController::getDirection() + ^^^^^^^^^ +116: factoryFunction< CMotorController >()->setDirection( Direction::Forward ); + ^^^^^^^^^ + + +DECLARATION: +5: Forward, Reverse + !!!!!!! +REFERENCES: +45: speed( 0 ), direction( Forward ), limiter( false ), velocity( Decelerate ) + ^^^^^^^ +116: factoryFunction< CMotorController >()->setDirection( Direction::Forward ); + ^^^^^^^ + + +DECLARATION: +5: Forward, Reverse + !!!!!!! +REFERENCES: + + +DECLARATION: +8: enum Velocity + !!!!!!!! +REFERENCES: +22: Velocity velocity; + ^^^^^^^^ +31: Velocity getVelocity(); + ^^^^^^^^ +80: Velocity CMotorController::getVelocity() + ^^^^^^^^ + + +DECLARATION: +10: Accelerate, Decelerate + !!!!!!!!!! +REFERENCES: +94: velocity = Accelerate; + ^^^^^^^^^^ + + +DECLARATION: +10: Accelerate, Decelerate + !!!!!!!!!! +REFERENCES: +45: speed( 0 ), direction( Forward ), limiter( false ), velocity( Decelerate ) + ^^^^^^^^^^ +99: velocity = Decelerate; + ^^^^^^^^^^ + + +DECLARATION: +13: static int global1 = 0; + !!!!!!! +REFERENCES: +87: global1 = 1; + ^^^^^^^ +88: int test1 = global1; + ^^^^^^^ + + +DECLARATION: +16: class CMotorController + !!!!!!!!!!!!!!!! +REFERENCES: +44: CMotorController::CMotorController() : + ^^^^^^^^^^^^^^^^ +49: void CMotorController::setSpeed( int speed ) + ^^^^^^^^^^^^^^^^ +54: int CMotorController::getSpeed() + ^^^^^^^^^^^^^^^^ +59: void CMotorController::setDirection( Direction direction ) + ^^^^^^^^^^^^^^^^ +64: void CMotorController::setDirectionAndSpeed( Direction direction, int speed ) + ^^^^^^^^^^^^^^^^ +70: Direction CMotorController::getDirection() + ^^^^^^^^^^^^^^^^ +75: bool CMotorController::getLimiter() + ^^^^^^^^^^^^^^^^ +80: Velocity CMotorController::getVelocity() + ^^^^^^^^^^^^^^^^ +85: void CMotorController::checkSpeed() + ^^^^^^^^^^^^^^^^ +116: factoryFunction< CMotorController >()->setDirection( Direction::Forward ); + ^^^^^^^^^^^^^^^^ + + +DECLARATION: +19: int speed; + !!!!! +REFERENCES: +45: speed( 0 ), direction( Forward ), limiter( false ), velocity( Decelerate ) + ^^^^^ +51: this->speed = speed; + ^^^^^ +56: return speed; + ^^^^^ +67: this->speed = speed; + ^^^^^ +90: switch ( speed ) + ^^^^^ + + +DECLARATION: +20: Direction direction; + !!!!!!!!! +REFERENCES: +45: speed( 0 ), direction( Forward ), limiter( false ), velocity( Decelerate ) + ^^^^^^^^^ +61: this->direction = direction; + ^^^^^^^^^ +66: this->direction = direction; + ^^^^^^^^^ +72: return direction; + ^^^^^^^^^ + + +DECLARATION: +21: bool limiter; + !!!!!!! +REFERENCES: +45: speed( 0 ), direction( Forward ), limiter( false ), velocity( Decelerate ) + ^^^^^^^ +77: return limiter; + ^^^^^^^ +93: limiter = false; + ^^^^^^^ +98: limiter = true; + ^^^^^^^ + + +DECLARATION: +22: Velocity velocity; + !!!!!!!! +REFERENCES: +45: speed( 0 ), direction( Forward ), limiter( false ), velocity( Decelerate ) + ^^^^^^^^ +94: velocity = Accelerate; + ^^^^^^^^ +99: velocity = Decelerate; + ^^^^^^^^ + + +DECLARATION: +25: CMotorController( void ); + !!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +27: void setSpeed( int speed ); + !!!!!!!! +REFERENCES: + + +DECLARATION: +27: void setSpeed( int speed ); + !!!!! +REFERENCES: +51: this->speed = speed; + ^^^^^ + + +DECLARATION: +28: int getSpeed(); + !!!!!!!! +REFERENCES: + + +DECLARATION: +29: void checkSpeed(); + !!!!!!!!!! +REFERENCES: + + +DECLARATION: +30: bool getLimiter(); + !!!!!!!!!! +REFERENCES: + + +DECLARATION: +31: Velocity getVelocity(); + !!!!!!!!!!! +REFERENCES: + + +DECLARATION: +33: void setDirection( Direction direction ); + !!!!!!!!!!!! +REFERENCES: +116: factoryFunction< CMotorController >()->setDirection( Direction::Forward ); + ^^^^^^^^^^^^ + + +DECLARATION: +33: void setDirection( Direction direction ); + !!!!!!!!! +REFERENCES: +61: this->direction = direction; + ^^^^^^^^^ + + +DECLARATION: +34: Direction getDirection(); + !!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +39: constexpr int factorial( int n ) + !!!!!!!!! +REFERENCES: +41: return n <= 1 ? 1 : ( n * factorial( n - 1 ) ); + ^^^^^^^^^ +103: factorial( 4 ); + ^^^^^^^^^ + + +DECLARATION: +39: constexpr int factorial( int n ) + ! +REFERENCES: +41: return n <= 1 ? 1 : ( n * factorial( n - 1 ) ); + ^ +41: return n <= 1 ? 1 : ( n * factorial( n - 1 ) ); + ^ +41: return n <= 1 ? 1 : ( n * factorial( n - 1 ) ); + ^ + + +DECLARATION: +44: CMotorController::CMotorController() : + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +44: CMotorController::CMotorController() : + !!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +49: void CMotorController::setSpeed( int speed ) + !!!!!!!!!!!!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +49: void CMotorController::setSpeed( int speed ) + !!!!!!!! +REFERENCES: + + +DECLARATION: +49: void CMotorController::setSpeed( int speed ) + !!!!! +REFERENCES: +51: this->speed = speed; + ^^^^^ + + +DECLARATION: +54: int CMotorController::getSpeed() + !!!!!!!!!!!!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +54: int CMotorController::getSpeed() + !!!!!!!! +REFERENCES: + + +DECLARATION: +59: void CMotorController::setDirection( Direction direction ) + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +REFERENCES: +116: factoryFunction< CMotorController >()->setDirection( Direction::Forward ); + ^^^^^^^^^^^^ + + +DECLARATION: +59: void CMotorController::setDirection( Direction direction ) + !!!!!!!!!!!! +REFERENCES: +116: factoryFunction< CMotorController >()->setDirection( Direction::Forward ); + ^^^^^^^^^^^^ + + +DECLARATION: +59: void CMotorController::setDirection( Direction direction ) + !!!!!!!!! +REFERENCES: +61: this->direction = direction; + ^^^^^^^^^ + + +DECLARATION: +64: void CMotorController::setDirectionAndSpeed( Direction direction, int speed ) + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +64: void CMotorController::setDirectionAndSpeed( Direction direction, int speed ) + !!!!!!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +64: void CMotorController::setDirectionAndSpeed( Direction direction, int speed ) + !!!!!!!!! +REFERENCES: +66: this->direction = direction; + ^^^^^^^^^ + + +DECLARATION: +64: void CMotorController::setDirectionAndSpeed( Direction direction, int speed ) + !!!!! +REFERENCES: +67: this->speed = speed; + ^^^^^ + + +DECLARATION: +70: Direction CMotorController::getDirection() + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +70: Direction CMotorController::getDirection() + !!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +75: bool CMotorController::getLimiter() + !!!!!!!!!!!!!!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +75: bool CMotorController::getLimiter() + !!!!!!!!!! +REFERENCES: + + +DECLARATION: +80: Velocity CMotorController::getVelocity() + !!!!!!!!!!!!!!!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +80: Velocity CMotorController::getVelocity() + !!!!!!!!!!! +REFERENCES: + + +DECLARATION: +85: void CMotorController::checkSpeed() + !!!!!!!!!!!!!!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +85: void CMotorController::checkSpeed() + !!!!!!!!!! +REFERENCES: + + +DECLARATION: +88: int test1 = global1; + !!!!! +REFERENCES: + + +DECLARATION: +108: template< typename T > + ! +REFERENCES: +109: T* factoryFunction() + ^ +111: return new T(); + ^ + + +DECLARATION: +109: T* factoryFunction() + !!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +114: void main() + !!!! +REFERENCES: + + diff --git a/cxx-sensors/src/test/resources/org/sonar/cxx/eclipsecdt/symbols_noinclude_references.txt b/cxx-sensors/src/test/resources/org/sonar/cxx/eclipsecdt/symbols_noinclude_references.txt new file mode 100644 index 0000000000..1a66c5560d --- /dev/null +++ b/cxx-sensors/src/test/resources/org/sonar/cxx/eclipsecdt/symbols_noinclude_references.txt @@ -0,0 +1,194 @@ +DECLARATION: +6: int global1 = 0; + !!!!!!! +REFERENCES: + + +DECLARATION: +8: constexpr int factorial( int n ) + !!!!!!!!! +REFERENCES: +10: return n <= 1 ? 1 : ( n * factorial( n - 1 ) ); + ^^^^^^^^^ + + +DECLARATION: +8: constexpr int factorial( int n ) + ! +REFERENCES: +10: return n <= 1 ? 1 : ( n * factorial( n - 1 ) ); + ^ +10: return n <= 1 ? 1 : ( n * factorial( n - 1 ) ); + ^ +10: return n <= 1 ? 1 : ( n * factorial( n - 1 ) ); + ^ + + +DECLARATION: +13: CMotorController::CMotorController() : + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +13: CMotorController::CMotorController() : + !!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +18: void CMotorController::setSpeed( int speed ) + !!!!!!!!!!!!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +18: void CMotorController::setSpeed( int speed ) + !!!!!!!! +REFERENCES: + + +DECLARATION: +18: void CMotorController::setSpeed( int speed ) + !!!!! +REFERENCES: +20: this->speed = speed; + ^^^^^ + + +DECLARATION: +23: int CMotorController::getSpeed() + !!!!!!!!!!!!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +23: int CMotorController::getSpeed() + !!!!!!!! +REFERENCES: + + +DECLARATION: +28: void CMotorController::setDirection( Direction direction ) + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +28: void CMotorController::setDirection( Direction direction ) + !!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +28: void CMotorController::setDirection( Direction direction ) + !!!!!!!!! +REFERENCES: +30: this->direction = direction; + ^^^^^^^^^ + + +DECLARATION: +33: void CMotorController::setDirectionAndSpeed( Direction direction, int speed ) + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +33: void CMotorController::setDirectionAndSpeed( Direction direction, int speed ) + !!!!!!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +33: void CMotorController::setDirectionAndSpeed( Direction direction, int speed ) + !!!!!!!!! +REFERENCES: +35: this->direction = direction; + ^^^^^^^^^ + + +DECLARATION: +33: void CMotorController::setDirectionAndSpeed( Direction direction, int speed ) + !!!!! +REFERENCES: +36: this->speed = speed; + ^^^^^ + + +DECLARATION: +39: Direction CMotorController::getDirection() + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +39: Direction CMotorController::getDirection() + !!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +44: bool CMotorController::getLimiter() + !!!!!!!!!!!!!!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +44: bool CMotorController::getLimiter() + !!!!!!!!!! +REFERENCES: + + +DECLARATION: +49: Velocity CMotorController::getVelocity() + !!!!!!!!!!!!!!!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +49: Velocity CMotorController::getVelocity() + !!!!!!!!!!! +REFERENCES: + + +DECLARATION: +54: void CMotorController::checkSpeed() + !!!!!!!!!!!!!!!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +54: void CMotorController::checkSpeed() + !!!!!!!!!! +REFERENCES: + + +DECLARATION: +57: int test1 = global1; + !!!!! +REFERENCES: + + +DECLARATION: +77: template< typename T > + ! +REFERENCES: +78: T* factoryFunction() + ^ +80: return new T(); + ^ + + +DECLARATION: +78: T* factoryFunction() + !!!!!!!!!!!!!!! +REFERENCES: + + +DECLARATION: +83: void main() + !!!! +REFERENCES: + + diff --git a/cxx-sensors/src/test/resources/org/sonar/cxx/eclipsecdt/syntaxerror.cc b/cxx-sensors/src/test/resources/org/sonar/cxx/eclipsecdt/syntaxerror.cc new file mode 100644 index 0000000000..65304c4c69 --- /dev/null +++ b/cxx-sensors/src/test/resources/org/sonar/cxx/eclipsecdt/syntaxerror.cc @@ -0,0 +1,13 @@ +// see https://github.com/SonarOpenCommunity/sonar-cxx/wiki/Error-Recovery + +int i = 0; + +void func1() +{ + i = 1 //; +} + +void func2() +{ + i = 2; +} diff --git a/cxx-sensors/src/test/resources/org/sonar/cxx/eclipsecdt/syntaxerror_references.txt b/cxx-sensors/src/test/resources/org/sonar/cxx/eclipsecdt/syntaxerror_references.txt new file mode 100644 index 0000000000..fc547b8a7d --- /dev/null +++ b/cxx-sensors/src/test/resources/org/sonar/cxx/eclipsecdt/syntaxerror_references.txt @@ -0,0 +1,22 @@ +DECLARATION: +3: int i = 0; + ! +REFERENCES: +7: i = 1 //; + ^ +12: i = 2; + ^ + + +DECLARATION: +5: void func1() + !!!!! +REFERENCES: + + +DECLARATION: +10: void func2() + !!!!! +REFERENCES: + +