}
}
+ void loadLineSymbolReferences(String symbolsReferences) {
+ String[] symbols = symbolsReferences.split(ENTITY_SEPARATOR);
+ for (String symbol : symbols) {
+ String[] symbolFields = symbol.split(FIELD_SEPARATOR);
+ int startOffset = Integer.parseInt(symbolFields[0]);
+ int endOffset = Integer.parseInt(symbolFields[1]);
+ int symbolLength = endOffset - startOffset;
+ int symbolId = Integer.parseInt(symbolFields[2]);
+ loadSymbolOccurrences(symbolId, symbolLength, new String[] { Integer.toString(startOffset) });
+ }
+ }
+
+
void loadSyntaxHighlightingData(String syntaxHighlightingRules) {
String[] rules = syntaxHighlightingRules.split(ENTITY_SEPARATOR);
for (String rule : rules) {
public class HtmlSourceDecorator implements ServerComponent {
+ private static final String SINGLE_LINE_SYMBOLS = "single_line_symbols";
+
private final MyBatis mybatis;
private final SnapshotSourceDao snapshotSourceDao;
}
@CheckForNull
- public String getDecoratedSourceAsHtml(@Nullable String sourceLine, @Nullable String highlighting) {
+ public String getDecoratedSourceAsHtml(@Nullable String sourceLine, @Nullable String highlighting, @Nullable String symbols) {
Collection<SnapshotDataDto> snapshotDataEntries = Lists.newArrayList();
if (highlighting != null) {
SnapshotDataDto highlightingDto = new SnapshotDataDto();
highlightingDto.setDataType(SnapshotDataTypes.SYNTAX_HIGHLIGHTING);
snapshotDataEntries.add(highlightingDto);
}
+ if (symbols != null) {
+ SnapshotDataDto symbolsDto = new SnapshotDataDto();
+ symbolsDto.setData(symbols);
+ symbolsDto.setDataType(SINGLE_LINE_SYMBOLS);
+ snapshotDataEntries.add(symbolsDto);
+ }
List<String> decoratedSource = decorate(sourceLine, snapshotDataEntries, 1, 1);
if (decoratedSource == null) {
return null;
dataHolder.loadSyntaxHighlightingData(entry.getData());
} else if (SnapshotDataTypes.SYMBOL_HIGHLIGHTING.equals(entry.getDataType())) {
dataHolder.loadSymbolReferences(entry.getData());
+ } else if (SINGLE_LINE_SYMBOLS.equals(entry.getDataType())) {
+ dataHolder.loadLineSymbolReferences(entry.getData());
}
}
}
setField(SourceLineIndexDefinition.FIELD_SCM_DATE, scmDate);
}
+ @CheckForNull
public String highlighting() {
- return getField(SourceLineIndexDefinition.FIELD_HIGHLIGHTING);
+ return getNullableField(SourceLineIndexDefinition.FIELD_HIGHLIGHTING);
}
public void setHighlighting(String s) {
return String.format("%s_%d", fileUuid(), line());
}
- @Nullable
+ @CheckForNull
public Integer utLineHits() {
Number lineHits = (Number)getNullableField(SourceLineIndexDefinition.FIELD_UT_LINE_HITS);
return lineHits == null ? null : lineHits.intValue();
setField(SourceLineIndexDefinition.FIELD_UT_LINE_HITS, lineHits);
}
- @Nullable
+ @CheckForNull
public Integer utConditions() {
Number conditions = (Number)getNullableField(SourceLineIndexDefinition.FIELD_UT_CONDITIONS);
return conditions == null ? null : conditions.intValue();
setField(SourceLineIndexDefinition.FIELD_UT_CONDITIONS, conditions);
}
- @Nullable
+ @CheckForNull
public Integer utCoveredConditions() {
Number coveredConditions = (Number)getNullableField(SourceLineIndexDefinition.FIELD_UT_COVERED_CONDITIONS);
return coveredConditions == null ? null : coveredConditions.intValue();
setField(SourceLineIndexDefinition.FIELD_UT_COVERED_CONDITIONS, coveredConditions);
}
- @Nullable
+ @CheckForNull
public Integer itLineHits() {
Number lineHits = (Number)getNullableField(SourceLineIndexDefinition.FIELD_IT_LINE_HITS);
return lineHits == null ? null : lineHits.intValue();
setField(SourceLineIndexDefinition.FIELD_IT_LINE_HITS, lineHits);
}
- @Nullable
+ @CheckForNull
public Integer itConditions() {
Number conditions = (Number)getNullableField(SourceLineIndexDefinition.FIELD_IT_CONDITIONS);
return conditions == null ? null : conditions.intValue();
setField(SourceLineIndexDefinition.FIELD_IT_CONDITIONS, conditions);
}
- @Nullable
+ @CheckForNull
public Integer itCoveredConditions() {
Number coveredConditions = (Number)getNullableField(SourceLineIndexDefinition.FIELD_IT_COVERED_CONDITIONS);
return coveredConditions == null ? null : coveredConditions.intValue();
setField(SourceLineIndexDefinition.FIELD_IT_COVERED_CONDITIONS, coveredConditions);
}
- @Nullable
+ @CheckForNull
public Integer overallLineHits() {
Number lineHits = (Number)getNullableField(SourceLineIndexDefinition.FIELD_OVERALL_LINE_HITS);
return lineHits == null ? null : lineHits.intValue();
setField(SourceLineIndexDefinition.FIELD_OVERALL_LINE_HITS, lineHits);
}
- @Nullable
+ @CheckForNull
public Integer overallConditions() {
Number conditions = (Number)getNullableField(SourceLineIndexDefinition.FIELD_OVERALL_CONDITIONS);
return conditions == null ? null : conditions.intValue();
setField(SourceLineIndexDefinition.FIELD_OVERALL_CONDITIONS, conditions);
}
- @Nullable
+ @CheckForNull
public Integer overallCoveredConditions() {
Number coveredConditions = (Number)getNullableField(SourceLineIndexDefinition.FIELD_OVERALL_COVERED_CONDITIONS);
return coveredConditions == null ? null : coveredConditions.intValue();
public void setOverallCoveredConditions(@Nullable Integer coveredConditions) {
setField(SourceLineIndexDefinition.FIELD_OVERALL_COVERED_CONDITIONS, coveredConditions);
}
+
+ @CheckForNull
+ public String symbols() {
+ return getNullableField(SourceLineIndexDefinition.FIELD_SYMBOLS);
+ }
+
+ public void setSymbols(@Nullable String s) {
+ setField(SourceLineIndexDefinition.FIELD_SYMBOLS, s);
+ }
+
}
public static final String FIELD_OVERALL_LINE_HITS = "overallLineHits";
public static final String FIELD_OVERALL_CONDITIONS = "overallConditions";
public static final String FIELD_OVERALL_COVERED_CONDITIONS = "overallCoveredConditions";
+ public static final String FIELD_SYMBOLS = "symbols";
public static final String INDEX = "sourcelines";
sourceLineMapping.createShortField(FIELD_OVERALL_LINE_HITS);
sourceLineMapping.createShortField(FIELD_OVERALL_CONDITIONS);
sourceLineMapping.createShortField(FIELD_OVERALL_COVERED_CONDITIONS);
+ sourceLineMapping.stringFieldBuilder(FIELD_SYMBOLS).build();
sourceLineMapping.createDateTimeField(BaseNormalizer.UPDATED_AT_FIELD);
}
}
doc.setOverallConditions(parseIntegerFromRecord(csvRecord, 10));
doc.setOverallCoveredConditions(parseIntegerFromRecord(csvRecord, 11));
doc.setHighlighting(csvRecord.get(12));
+ doc.setSymbols(csvRecord.get(13));
doc.setSource(csvRecord.get(csvRecord.size() - 1));
result.addLine(doc);
for (SourceLineDoc line: lines) {
json.beginObject()
.prop("line", line.line())
- .prop("code", htmlSourceDecorator.getDecoratedSourceAsHtml(line.source(), line.highlighting()))
+ .prop("code", htmlSourceDecorator.getDecoratedSourceAsHtml(line.source(), line.highlighting(), line.symbols()))
.prop("scmAuthor", line.scmAuthor())
.prop("scmRevision", line.scmRevision());
Date scmDate = line.scmDate();
@Test
public void highlight_syntax_with_html_from_component() throws Exception {
- List<String> decoratedSource = sourceDecorator.getDecoratedSourceAsHtml("org.apache.struts:struts:Dispatcher", null, null);
+ List<String> decoratedSource = sourceDecorator.getDecoratedSourceAsHtml("org.apache.struts:struts:Dispatcher", (Integer) null, (Integer) null);
assertThat(decoratedSource).containsExactly(
"<span class=\"cppd\">/*</span>",
@Test
public void mark_symbols_with_html_from_component() throws Exception {
- List<String> decoratedSource = sourceDecorator.getDecoratedSourceAsHtml("org.apache.struts:struts:VelocityManager", null, null);
+ List<String> decoratedSource = sourceDecorator.getDecoratedSourceAsHtml("org.apache.struts:struts:VelocityManager", (Integer) null, (Integer) null);
assertThat(decoratedSource).containsExactly(
"/*",
@Test
public void decorate_source_with_multiple_decoration_strategies_from_component() throws Exception {
- List<String> decoratedSource = sourceDecorator.getDecoratedSourceAsHtml("org.apache.struts:struts:DebuggingInterceptor", null, null);
+ List<String> decoratedSource = sourceDecorator.getDecoratedSourceAsHtml("org.apache.struts:struts:DebuggingInterceptor", (Integer) null, (Integer) null);
assertThat(decoratedSource).containsExactly(
"<span class=\"cppd\">/*</span>",
HtmlSourceDecorator sourceDecorator = new HtmlSourceDecorator(mock(MyBatis.class), snapshotSourceDao, snapshotDataDao);
- sourceDecorator.getDecoratedSourceAsHtml("org.apache.struts:struts:DebuggingInterceptor", null, null);
+ sourceDecorator.getDecoratedSourceAsHtml("org.apache.struts:struts:DebuggingInterceptor", (Integer) null, (Integer) null);
verify(snapshotDataDao, times(1)).selectSnapshotDataByComponentKey(eq("org.apache.struts:struts:DebuggingInterceptor"), eq(Lists.newArrayList("highlight_syntax", "symbol")),
any(SqlSession.class));
public void should_decorate_single_line() {
String sourceLine = "package org.polop;";
String highlighting = "0,7,k";
- assertThat(sourceDecorator.getDecoratedSourceAsHtml(sourceLine, highlighting)).isEqualTo("<span class=\"k\">package</span> org.polop;");
+ String symbols = "8,17,42";
+ assertThat(sourceDecorator.getDecoratedSourceAsHtml(sourceLine, highlighting, symbols)).isEqualTo("<span class=\"k\">package</span> <span class=\"sym-42 sym\">org.polop</span>;");
}
@Test
public void should_ignore_missing_highlighting() {
String sourceLine = " if (toto < 42) {";
- assertThat(sourceDecorator.getDecoratedSourceAsHtml(sourceLine, null)).isEqualTo(" if (toto < 42) {");
- assertThat(sourceDecorator.getDecoratedSourceAsHtml(sourceLine, "")).isEqualTo(" if (toto < 42) {");
+ assertThat(sourceDecorator.getDecoratedSourceAsHtml(sourceLine, (String) null, (String) null)).isEqualTo(" if (toto < 42) {");
+ assertThat(sourceDecorator.getDecoratedSourceAsHtml(sourceLine, "", (String) null)).isEqualTo(" if (toto < 42) {");
}
@Test
public void should_ignore_null_source() {
- assertThat(sourceDecorator.getDecoratedSourceAsHtml(null, null)).isNull();
+ assertThat(sourceDecorator.getDecoratedSourceAsHtml(null, (String) null, (String) null)).isNull();
}
@Test
public void should_ignore_empty_source() {
- assertThat(sourceDecorator.getDecoratedSourceAsHtml("", null)).isEqualTo("");
+ assertThat(sourceDecorator.getDecoratedSourceAsHtml("", (String) null, (String) null)).isEqualTo("");
}
}
service.getLinesAsHtml(COMPONENT_KEY);
- verify(sourceDecorator).getDecoratedSourceAsHtml(COMPONENT_KEY, null, null);
+ verify(sourceDecorator).getDecoratedSourceAsHtml(COMPONENT_KEY, (Integer) null, (Integer) null);
}
@Test
public void should_generate_source_line_documents() throws Exception {
db.prepareDbUnit(getClass(), "shared.xml");
PreparedStatement stmt = connection.prepareStatement("UPDATE file_sources SET data = ? WHERE id=1");
- stmt.setString(1, "aef12a,alice,2014-04-25T12:34:56+0100,1,0,0,2,0,0,3,0,0,polop,class Foo {\r\n" +
- "abe465,bob,2014-07-25T12:34:56+0100,,,,,,,,,,, // Empty\r\n" +
- "afb789,carol,2014-03-23T12:34:56+0100,,,,,,,,,,,}\r\n" +
- "afb789,carol,2014-03-23T12:34:56+0100,,,,,,,,,,,\r\n");
+ stmt.setString(1, "aef12a,alice,2014-04-25T12:34:56+0100,1,0,0,2,0,0,3,0,0,polop,palap,class Foo {\r\n" +
+ "abe465,bob,2014-07-25T12:34:56+0100,,,,,,,,,,,, // Empty\r\n" +
+ "afb789,carol,2014-03-23T12:34:56+0100,,,,,,,,,,,,}\r\n" +
+ "afb789,carol,2014-03-23T12:34:56+0100,,,,,,,,,,,,\r\n");
stmt.executeUpdate();
SourceLineResultSetIterator iterator = SourceLineResultSetIterator.create(dbClient, connection, 0L);
// TODO Sanitize usage of fscking dates
// assertThat(firstLine.scmDate()).isEqualTo(DateUtils.parseDateTime("2014-04-25T12:34:56+0100"));
assertThat(firstLine.highlighting()).isEqualTo("polop");
+ assertThat(firstLine.symbols()).isEqualTo("palap");
assertThat(firstLine.source()).isEqualTo("class Foo {");
assertThat(firstLine.utLineHits()).isEqualTo(1);
assertThat(firstLine.utConditions()).isEqualTo(0);
mock(HashAction.class)
)
);
- when(htmlSourceDecorator.getDecoratedSourceAsHtml(anyString(), anyString())).thenAnswer(new Answer<String>() {
+ when(htmlSourceDecorator.getDecoratedSourceAsHtml(anyString(), anyString(), anyString())).thenAnswer(new Answer<String>() {
@Override
public String answer(InvocationOnMock invocation) throws Throwable {
- return "<span class=\"" + invocation.getArguments()[1] + "\">" +
+ return "<span class=\"" + invocation.getArguments()[1] + " sym-" + invocation.getArguments()[2] + "\">" +
StringEscapeUtils.escapeHtml((String) invocation.getArguments()[0]) +
"</span>";
}
.put(SourceLineIndexDefinition.FIELD_SCM_AUTHOR, "polop")
.put(SourceLineIndexDefinition.FIELD_SOURCE, "class Polop {")
.put(SourceLineIndexDefinition.FIELD_HIGHLIGHTING, "h1")
+ .put(SourceLineIndexDefinition.FIELD_SYMBOLS, "palap")
.put(SourceLineIndexDefinition.FIELD_OVERALL_LINE_HITS, 3)
.put(SourceLineIndexDefinition.FIELD_OVERALL_CONDITIONS, 2)
.put(SourceLineIndexDefinition.FIELD_OVERALL_COVERED_CONDITIONS, 1)
.put(SourceLineIndexDefinition.FIELD_SCM_AUTHOR, "polop")
.put(SourceLineIndexDefinition.FIELD_SOURCE, " // Empty")
.put(SourceLineIndexDefinition.FIELD_HIGHLIGHTING, "h2")
+ .put(SourceLineIndexDefinition.FIELD_SYMBOLS, "pulup")
.put(SourceLineIndexDefinition.FIELD_OVERALL_LINE_HITS, 3)
.put(SourceLineIndexDefinition.FIELD_OVERALL_CONDITIONS, 2)
.put(SourceLineIndexDefinition.FIELD_OVERALL_COVERED_CONDITIONS, 1)
.put(SourceLineIndexDefinition.FIELD_SCM_AUTHOR, "polop")
.put(SourceLineIndexDefinition.FIELD_SOURCE, "}")
.put(SourceLineIndexDefinition.FIELD_HIGHLIGHTING, "h3")
+ .put(SourceLineIndexDefinition.FIELD_SYMBOLS, "pylyp")
.put(SourceLineIndexDefinition.FIELD_OVERALL_LINE_HITS, 3)
.put(SourceLineIndexDefinition.FIELD_OVERALL_CONDITIONS, 2)
.put(SourceLineIndexDefinition.FIELD_OVERALL_COVERED_CONDITIONS, 1)
fieldMap.put(SourceLineIndexDefinition.FIELD_SCM_AUTHOR, "polop");
fieldMap.put(SourceLineIndexDefinition.FIELD_SOURCE, "}");
fieldMap.put(SourceLineIndexDefinition.FIELD_HIGHLIGHTING, "");
+ fieldMap.put(SourceLineIndexDefinition.FIELD_SYMBOLS, "");
fieldMap.put(SourceLineIndexDefinition.FIELD_OVERALL_LINE_HITS, null);
fieldMap.put(SourceLineIndexDefinition.FIELD_OVERALL_CONDITIONS, null);
fieldMap.put(SourceLineIndexDefinition.FIELD_OVERALL_COVERED_CONDITIONS, null);
{
"sources": [
{
- "code": "<span class=\"h1\">class Polop {</span>",
+ "code": "<span class=\"h1 sym-palap\">class Polop {</span>",
"line": 1,
"scmAuthor": "polop",
"scmRevision": "cafebabe",
"coveredConditions": 1
},
{
- "code": "<span class=\"h2\"> // Empty</span>",
+ "code": "<span class=\"h2 sym-pulup\"> // Empty</span>",
"line": 2,
"scmAuthor": "polop",
"scmRevision": "cafebabe",
"coveredConditions": 1
},
{
- "code": "<span class=\"h3\">}</span>",
+ "code": "<span class=\"h3 sym-pylyp\">}</span>",
"line": 3,
"scmAuthor": "polop",
"scmRevision": "cafebabe",
{
"sources": [
{
- "code": "<span class=\"\">}</span>",
+ "code": "<span class=\" sym-\">}</span>",
"line": 3,
"scmAuthor": "polop",
"scmRevision": "cafebabe"