Browse Source

SONAR-5894 Support symbol references with different length

tags/5.3-RC1
Duarte Meneses 8 years ago
parent
commit
d986919813

+ 23
- 4
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/lang/SymbolReferencesSensor.java View File

@@ -81,17 +81,36 @@ public class SymbolReferencesSensor implements Sensor {
private static void processLine(File symbolFile, int lineNumber, Symbolizable.SymbolTableBuilder symbolTableBuilder, String line) {
try {
Iterator<String> split = Splitter.on(",").split(line).iterator();
int startOffset = Integer.parseInt(split.next());
int endOffset = Integer.parseInt(split.next());
Symbol s = symbolTableBuilder.newSymbol(startOffset, endOffset);

Symbol s = addSymbol(symbolTableBuilder, split.next());
while (split.hasNext()) {
symbolTableBuilder.newReference(s, Integer.parseInt(split.next()));
addReference(symbolTableBuilder, s, split.next());
}
} catch (Exception e) {
throw new IllegalStateException("Error processing line " + lineNumber + " of file " + symbolFile.getAbsolutePath(), e);
}
}

private static void addReference(Symbolizable.SymbolTableBuilder symbolTableBuilder, Symbol s, String str) {
if (str.contains(":")) {
Iterator<String> split = Splitter.on(":").split(str).iterator();
int startOffset = Integer.parseInt(split.next());
int toOffset = Integer.parseInt(split.next());
symbolTableBuilder.newReference(s, startOffset, toOffset);
} else {
symbolTableBuilder.newReference(s, Integer.parseInt(str));
}
}

private static Symbol addSymbol(Symbolizable.SymbolTableBuilder symbolTableBuilder, String str) {
Iterator<String> split = Splitter.on(":").split(str).iterator();

int startOffset = Integer.parseInt(split.next());
int endOffset = Integer.parseInt(split.next());

return symbolTableBuilder.newSymbol(startOffset, endOffset);
}

@Override
public void describe(SensorDescriptor descriptor) {
descriptor

+ 2
- 2
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/SymbolReferencesSensorTest.java View File

@@ -74,7 +74,7 @@ public class SymbolReferencesSensorTest {
@Test
public void testExecution() throws IOException {
File symbol = new File(baseDir, "src/foo.xoo.symbol");
FileUtils.write(symbol, "1,4,7\n12,15,23\n\n#comment");
FileUtils.write(symbol, "1:4,7\n12:15,23:33\n\n#comment");
DefaultInputFile inputFile = new DefaultInputFile("foo", "src/foo.xoo").setLanguage("xoo");
fileSystem.add(inputFile);
Symbolizable symbolizable = mock(Symbolizable.class);
@@ -92,7 +92,7 @@ public class SymbolReferencesSensorTest {
verify(symbolTableBuilder).newSymbol(1, 4);
verify(symbolTableBuilder).newReference(symbol1, 7);
verify(symbolTableBuilder).newSymbol(12, 15);
verify(symbolTableBuilder).newReference(symbol2, 23);
verify(symbolTableBuilder).newReference(symbol2, 23, 33);
}

}

+ 6
- 1
sonar-batch/src/main/java/org/sonar/batch/source/DefaultSymbolTable.java View File

@@ -99,10 +99,15 @@ public class DefaultSymbolTable implements Symbolizable.SymbolTable {

@Override
public void newReference(Symbol symbol, int fromOffset) {
newReference(symbol, fromOffset, fromOffset + ((DefaultSymbol) symbol).getLength());
}

@Override
public void newReference(Symbol symbol, int fromOffset, int toOffset) {
if (!referencesBySymbol.containsKey(symbol)) {
throw new UnsupportedOperationException("Cannot add reference to a symbol in another file");
}
TextRange referenceRange = inputFile.newRange(fromOffset, fromOffset + ((DefaultSymbol) symbol).getLength());
TextRange referenceRange = inputFile.newRange(fromOffset, toOffset);

if (referenceRange.overlap(((DefaultSymbol) symbol).range())) {
throw new UnsupportedOperationException("Cannot add reference (" + fromOffset + ") overlapping " + symbol + " in " + inputFile.key());

+ 5
- 0
sonar-batch/src/main/java/org/sonar/batch/source/DefaultSymbolizable.java View File

@@ -45,6 +45,11 @@ public class DefaultSymbolizable implements Symbolizable {
// Do nothing
}

@Override
public void newReference(Symbol symbol, int fromOffset, int toOffset) {
// Do nothing
}

@Override
public SymbolTable build() {
return NO_OP_SYMBOL_TABLE;

+ 30
- 1
sonar-batch/src/test/java/org/sonar/batch/mediumtest/symbol/SymbolMediumTest.java View File

@@ -66,7 +66,7 @@ public class SymbolMediumTest {
File xooSymbolFile = new File(srcDir, "sample.xoo.symbol");
FileUtils.write(xooFile, "Sample xoo\ncontent\nanother xoo");
// Highlight xoo symbol
FileUtils.write(xooSymbolFile, "7,10,27");
FileUtils.write(xooSymbolFile, "7:10,27");

TaskResult result = tester.newTask()
.properties(ImmutableMap.<String, String>builder()
@@ -84,4 +84,33 @@ public class SymbolMediumTest {
assertThat(result.symbolReferencesFor(file, 1, 7)).containsOnly(BatchReport.TextRange.newBuilder().setStartLine(3).setStartOffset(8).setEndLine(3).setEndOffset(11).build());
}

@Test
public void computeSymbolReferencesWithVariableLength() throws IOException {

File baseDir = temp.getRoot();
File srcDir = new File(baseDir, "src");
srcDir.mkdir();

File xooFile = new File(srcDir, "sample.xoo");
File xooSymbolFile = new File(srcDir, "sample.xoo.symbol");
FileUtils.write(xooFile, "Sample xoo\ncontent\nanother xoo\nyet another");
// Highlight xoo symbol
FileUtils.write(xooSymbolFile, "7:10,27:32");

TaskResult result = tester.newTask()
.properties(ImmutableMap.<String, String>builder()
.put("sonar.task", "scan")
.put("sonar.projectBaseDir", baseDir.getAbsolutePath())
.put("sonar.projectKey", "com.foo.project")
.put("sonar.projectName", "Foo Project")
.put("sonar.projectVersion", "1.0-SNAPSHOT")
.put("sonar.projectDescription", "Description of Foo Project")
.put("sonar.sources", "src")
.build())
.start();

InputFile file = result.inputFile("src/sample.xoo");
assertThat(result.symbolReferencesFor(file, 1, 7)).containsOnly(BatchReport.TextRange.newBuilder().setStartLine(3).setStartOffset(8).setEndLine(4).setEndOffset(1).build());
}

}

+ 23
- 1
sonar-batch/src/test/java/org/sonar/batch/source/DefaultSymbolTableTest.java View File

@@ -20,8 +20,12 @@

package org.sonar.batch.source;

import org.sonar.api.batch.fs.TextRange;
import com.google.common.base.Strings;

import java.io.StringReader;
import java.util.Set;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -30,7 +34,6 @@ import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.fs.internal.FileMetadata;
import org.sonar.api.source.Symbol;
import org.sonar.api.source.Symbolizable;

import static org.assertj.core.api.Assertions.assertThat;

public class DefaultSymbolTableTest {
@@ -60,6 +63,25 @@ public class DefaultSymbolTableTest {
assertThat(symbolTable.symbols()).containsExactly(firstSymbol, secondSymbol, thirdSymbol);
}

@Test
public void variable_length_references() {
Symbolizable.SymbolTableBuilder symbolTableBuilder = new DefaultSymbolTable.Builder(inputFile);
Symbol firstSymbol = symbolTableBuilder.newSymbol(10, 20);
symbolTableBuilder.newReference(firstSymbol, 32);
symbolTableBuilder.newReference(firstSymbol, 44, 47);

DefaultSymbolTable symbolTable = (DefaultSymbolTable) symbolTableBuilder.build();

assertThat(symbolTable.symbols()).containsExactly(firstSymbol);

Set<TextRange> references = symbolTable.getReferencesBySymbol().get(firstSymbol);
assertThat(references).containsExactly(range(32, 42), range(44, 47));
}

private TextRange range(int start, int end) {
return inputFile.newRange(start, end);
}

@Test
public void should_reject_reference_conflicting_with_declaration() {
throwable.expect(UnsupportedOperationException.class);

+ 18
- 0
sonar-plugin-api/src/main/java/org/sonar/api/source/Symbolizable.java View File

@@ -33,11 +33,29 @@ public interface Symbolizable extends Perspective {

interface SymbolTableBuilder {

/**
* Creates a new Symbol.
* The offsets are global in the file.
*/
Symbol newSymbol(int fromOffset, int toOffset);

/**
* Creates a new reference for a symbol.
* The length of the reference is assumed to be the same as the symbol's length.
*/
void newReference(Symbol symbol, int fromOffset);
/**
* Creates a new reference for a symbol.
* The offsets are global in the file.
*/
void newReference(Symbol symbol, int fromOffset, int toOffset);

/**
* Creates a {@link SymbolTable} containing all symbols and references previously created in this file.
*/
SymbolTable build();

}

interface SymbolTable {

Loading…
Cancel
Save