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:
+
+