/* * SonarQube Java * Copyright (C) 2012-2016 SonarSource SA * mailto:contact AT sonarsource DOT com * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package org.sonar.java.ast.visitors; import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; import com.google.common.io.Files; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.sonar.api.batch.fs.TextPointer; import org.sonar.api.batch.fs.TextRange; import org.sonar.api.batch.fs.internal.DefaultFileSystem; import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.batch.fs.internal.DefaultTextPointer; import org.sonar.api.batch.rule.CheckFactory; import org.sonar.api.batch.sensor.internal.SensorContextTester; import org.sonar.api.measures.FileLinesContextFactory; import org.sonar.java.JavaClasspath; import org.sonar.java.JavaTestClasspath; import org.sonar.java.SonarComponents; import org.sonar.java.ast.JavaAstScanner; import org.sonar.java.model.VisitorsBridge; import java.io.File; import java.nio.charset.StandardCharsets; import java.util.Collection; import java.util.List; import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; public class SonarSymbolTableVisitorTest { @Rule public TemporaryFolder temp = new TemporaryFolder(); private static final String EOL = "\n"; private List<String> lines; private SensorContextTester context; private DefaultFileSystem fs; private SonarComponents sonarComponents; @Before public void setUp() throws Exception { context = SensorContextTester.create(temp.getRoot()); fs = context.fileSystem(); sonarComponents = new SonarComponents(mock(FileLinesContextFactory.class), fs, mock(JavaClasspath.class), mock(JavaTestClasspath.class), mock(CheckFactory.class)); sonarComponents.setSensorContext(context); } @Test public void sonar_symbol_table() throws Exception { File file = temp.newFile(); Files.write(Files.toString(new File("src/test/files/highlighter/SonarSymTable.java"), StandardCharsets.UTF_8).replaceAll("\\r\\n", "\n").replaceAll("\\n", EOL), file, StandardCharsets.UTF_8); lines = Files.readLines(file, StandardCharsets.UTF_8); String content = Joiner.on(EOL).join(lines); fs.add(new DefaultInputFile("", file.getName()).initMetadata(content)); JavaAstScanner.scanSingleFileForTests(file, new VisitorsBridge(ImmutableList.of(), sonarComponents.getJavaClasspath(), sonarComponents)); String componentKey = ":" + file.getName(); verifyUsages(componentKey, 1, 17, reference(5,2), reference(9,10)); // Example class declaration verifyUsages(componentKey, 4, 6); verifyUsages(componentKey, 4, 14); // list field verifyUsages(componentKey, 5, 15, reference(10, 9)); // Example empty constructor verifyUsages(componentKey, 6, 2); // Do not reference constructor of class using this() and super() as long as SONAR-5894 is not fixed //verify(symboltableBuilder).newReference(any(Symbol.class), eq(offset(7, 5))); // Example list constructor verifyUsages(componentKey, 9, 2, reference(7, 4)); // list local var verifyUsages(componentKey, 9, 23, reference(10, 16)); // method verifyUsages(componentKey, 12, 6); //label verifyUsages(componentKey, 13, 4); //Enum verifyUsages(componentKey, 16, 7); verifyUsages(componentKey, 17, 5); // Do not reference constructor of enum as it can leads to failure in analysis as long as SONAR-5894 is not fixed //verify(symboltableBuilder).newReference(any(Symbol.class), eq(offset(14, 5))); verifyUsages(componentKey, 18, 4, reference(17, 4)); verifyUsages(componentKey, 21, 3, reference(21, 19)); verifyUsages(componentKey, 21, 11); verifyUsages(componentKey, 21, 21); } private void verifyUsages(String componentKey, int line, int offset, TextPointer... tps) { Collection<TextRange> textRanges = context.referencesForSymbolAt(componentKey, line, offset); if(tps.length == 0) { // TODO assert correctly that symbol is effectevly created see : SONAR-7850 assertThat(textRanges).isEmpty(); } else { assertThat(textRanges.stream().map(TextRange::start).collect(Collectors.toList())).isNotEmpty().containsOnly(tps); } } private static TextPointer reference(int line, int column) { return new DefaultTextPointer(line, column); } }