use of com.google.debugging.sourcemap.proto.Mapping.OriginalMapping in project closure-compiler by google.
the class PrintStreamJSONErrorManager method generateReport.
@Override
@GwtIncompatible
public void generateReport() {
ByteArrayOutputStream bufferedStream = new ByteArrayOutputStream();
List<ErrorWithLevel> list = new ArrayList<>();
try (JsonWriter jsonWriter = new JsonWriter(new OutputStreamWriter(bufferedStream, "UTF-8"))) {
jsonWriter.beginArray();
for (ErrorWithLevel message = messages.poll(); message != null; message = messages.poll()) {
String sourceName = message.error.sourceName;
int lineNumber = message.error.getLineNumber();
int charno = message.error.getCharno();
jsonWriter.beginObject();
jsonWriter.name("level").value(message.level == CheckLevel.ERROR ? "error" : "warning");
jsonWriter.name("description").value(message.error.description);
jsonWriter.name("source").value(sourceName);
jsonWriter.name("line").value(lineNumber);
jsonWriter.name("column").value(charno);
// extract source excerpt
String sourceExcerpt = SourceExcerpt.LINE.get(sourceExcerptProvider, sourceName, lineNumber, excerptFormatter);
if (sourceExcerpt != null) {
StringBuilder b = new StringBuilder(sourceExcerpt);
b.append("\n");
// at the end of the line
if (0 <= charno && charno <= sourceExcerpt.length()) {
for (int i = 0; i < charno; i++) {
char c = sourceExcerpt.charAt(i);
if (TokenUtil.isWhitespace(c)) {
b.append(c);
} else {
b.append(' ');
}
}
if (message.error.node == null) {
b.append("^");
} else {
int length = Math.max(1, Math.min(message.error.node.getLength(), sourceExcerpt.length() - charno));
for (int i = 0; i < length; i++) {
b.append("^");
}
}
}
jsonWriter.name("context").value(b.toString());
}
OriginalMapping mapping = sourceExcerptProvider.getSourceMapping(sourceName, message.error.lineNumber, message.error.getCharno());
if (mapping != null) {
jsonWriter.name("originalLocation").beginObject();
jsonWriter.name("source").value(mapping.getOriginalFile());
jsonWriter.name("line").value(mapping.getLineNumber());
jsonWriter.name("column").value(mapping.getColumnPosition());
jsonWriter.endObject();
}
jsonWriter.endObject();
list.add(message);
}
StringBuilder summaryBuilder = new StringBuilder();
if (getTypedPercent() > 0.0) {
summaryBuilder.append(SimpleFormat.format("%d error(s), %d warning(s), %.1f%% typed", getErrorCount(), getWarningCount(), getTypedPercent()));
} else {
summaryBuilder.append(SimpleFormat.format("%d error(s), %d warning(s)", getErrorCount(), getWarningCount()));
}
jsonWriter.beginObject();
jsonWriter.name("level").value("info");
jsonWriter.name("description").value(summaryBuilder.toString());
jsonWriter.endObject();
jsonWriter.endArray();
jsonWriter.flush();
jsonWriter.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
stream.append(bufferedStream.toString());
// Restore the messages since some tests assert the values after generating the report.
messages.addAll(list);
}
use of com.google.debugging.sourcemap.proto.Mapping.OriginalMapping in project closure-compiler by google.
the class JsMessageVisitor method checkMessageInitialization.
/**
* This method is called for every Node in the sources AST.
*/
private void checkMessageInitialization(NodeTraversal traversal, Node node) {
final Node parent = node.getParent();
final String originalMessageKey;
String possiblyObfuscatedMessageKey;
final Node msgNode;
final boolean isVar;
switch(node.getToken()) {
case NAME:
// Case: `var MSG_HELLO = 'Message';`
if (parent == null || !NodeUtil.isNameDeclaration(parent)) {
return;
}
possiblyObfuscatedMessageKey = node.getString();
originalMessageKey = node.getOriginalName();
msgNode = node.getFirstChild();
isVar = true;
break;
case ASSIGN:
// Case: `somenamespace.someclass.MSG_HELLO = 'Message';`
Node getProp = node.getFirstChild();
if (!getProp.isGetProp()) {
return;
}
possiblyObfuscatedMessageKey = getProp.getString();
originalMessageKey = getProp.getOriginalName();
msgNode = node.getLastChild();
isVar = false;
break;
case STRING_KEY:
// Case: `var t = {MSG_HELLO: 'Message'}`;
if (node.isQuotedString() || !node.hasChildren() || parent.isObjectPattern()) {
// Case: `var {something: MSG_HELLO} = anything;
return;
}
checkState(parent.isObjectLit(), parent);
possiblyObfuscatedMessageKey = node.getString();
originalMessageKey = node.getOriginalName();
msgNode = node.getFirstChild();
isVar = false;
break;
default:
return;
}
String messageKey = originalMessageKey != null ? originalMessageKey : possiblyObfuscatedMessageKey;
// If we've reached this point, then messageKey is the name of a variable or a property that is
// being assigned a value and msgNode is the Node representing the value being assigned.
// However, we haven't actually determined yet that name looks like it should be a translatable
// message or that the value is a call to goog.getMsg().
// Is this a message name?
boolean isNewStyleMessage = msgNode != null && msgNode.isCall();
if (!isMessageName(messageKey, isNewStyleMessage)) {
return;
}
if (msgNode == null) {
compiler.report(JSError.make(node, MESSAGE_HAS_NO_VALUE, messageKey));
return;
}
if (isLegalMessageVarAlias(msgNode)) {
return;
}
// doesn't use goog.getMsg().
if (isNewStyleMessage) {
googMsgNodes.remove(msgNode);
} else if (style != JsMessage.Style.LEGACY) {
// TODO(johnlenz): promote this to an error once existing conflicts have been
// cleaned up.
compiler.report(JSError.make(node, MESSAGE_NOT_INITIALIZED_USING_NEW_SYNTAX));
if (style == JsMessage.Style.CLOSURE) {
// Don't extract the message if we aren't accepting LEGACY messages
return;
}
}
boolean isUnnamedMsg = isUnnamedMessageName(messageKey);
JsMessage.Builder builder = new JsMessage.Builder(isUnnamedMsg ? null : messageKey);
OriginalMapping mapping = compiler.getSourceMapping(traversal.getSourceName(), node.getLineno(), node.getCharno());
if (mapping != null) {
builder.setSourceName(mapping.getOriginalFile() + ":" + mapping.getLineNumber());
} else {
builder.setSourceName(traversal.getSourceName() + ":" + node.getLineno());
}
try {
if (isVar) {
extractMessageFromVariable(builder, node, parent, parent.getParent());
} else {
extractMessageFrom(builder, msgNode, node);
}
} catch (MalformedException ex) {
compiler.report(JSError.make(ex.getNode(), MESSAGE_TREE_MALFORMED, ex.getMessage()));
return;
}
JsMessage extractedMessage = builder.build(idGenerator);
// If asked to check named internal messages.
if (!isUnnamedMsg && !extractedMessage.isExternal()) {
checkIfMessageDuplicated(messageKey, msgNode);
}
if (isUnnamedMsg) {
trackUnnamedMessage(traversal, extractedMessage, possiblyObfuscatedMessageKey);
} else {
trackNormalMessage(extractedMessage, messageKey, msgNode);
}
if (extractedMessage.isEmpty()) {
// value of the message is an empty string. Translators do not like it.
compiler.report(JSError.make(node, MESSAGE_HAS_NO_TEXT, messageKey));
}
// New-style messages must have descriptions. We don't emit a warning
// for legacy-style messages, because there are thousands of
// them in legacy code that are not worth the effort to fix, since they've
// already been translated anyway.
String desc = extractedMessage.getDesc();
if (isNewStyleMessage && (desc == null || desc.trim().isEmpty()) && !extractedMessage.isExternal()) {
compiler.report(JSError.make(node, MESSAGE_HAS_NO_DESCRIPTION, messageKey));
}
JsMessageDefinition msgDefinition = new JsMessageDefinition(msgNode);
processJsMessage(extractedMessage, msgDefinition);
}
use of com.google.debugging.sourcemap.proto.Mapping.OriginalMapping in project closure-compiler by google.
the class JsonErrorReportGenerator method generateReport.
@Override
@GwtIncompatible
public void generateReport(SortingErrorManager manager) {
ByteArrayOutputStream bufferedStream = new ByteArrayOutputStream();
try (JsonWriter jsonWriter = new JsonWriter(new OutputStreamWriter(bufferedStream, UTF_8))) {
jsonWriter.beginArray();
for (ErrorWithLevel message : manager.getSortedDiagnostics()) {
String sourceName = message.error.getSourceName();
int lineNumber = message.error.getLineNumber();
int charno = message.error.getCharno();
jsonWriter.beginObject();
jsonWriter.name("level").value(message.level == CheckLevel.ERROR ? "error" : "warning");
jsonWriter.name("description").value(message.error.getDescription());
jsonWriter.name("key").value(message.error.getType().key);
jsonWriter.name("source").value(sourceName);
jsonWriter.name("line").value(lineNumber);
jsonWriter.name("column").value(charno);
Node node = message.error.getNode();
if (node != null) {
jsonWriter.name("length").value(node.getLength());
}
// extract source excerpt
String sourceExcerpt = SourceExcerpt.LINE.get(sourceExcerptProvider, sourceName, lineNumber, excerptFormatter);
if (sourceExcerpt != null) {
StringBuilder b = new StringBuilder(sourceExcerpt);
b.append("\n");
// at the end of the line
if (0 <= charno && charno <= sourceExcerpt.length()) {
for (int i = 0; i < charno; i++) {
char c = sourceExcerpt.charAt(i);
if (TokenUtil.isWhitespace(c)) {
b.append(c);
} else {
b.append(' ');
}
}
if (message.error.getNode() == null) {
b.append("^");
} else {
int length = max(1, min(message.error.getNode().getLength(), sourceExcerpt.length() - charno));
for (int i = 0; i < length; i++) {
b.append("^");
}
}
}
jsonWriter.name("context").value(b.toString());
}
OriginalMapping mapping = sourceExcerptProvider.getSourceMapping(sourceName, message.error.getLineNumber(), message.error.getCharno());
if (mapping != null) {
jsonWriter.name("originalLocation").beginObject();
jsonWriter.name("source").value(mapping.getOriginalFile());
jsonWriter.name("line").value(mapping.getLineNumber());
jsonWriter.name("column").value(mapping.getColumnPosition());
jsonWriter.endObject();
}
jsonWriter.endObject();
}
StringBuilder summaryBuilder = new StringBuilder();
if (manager.getTypedPercent() > 0.0) {
summaryBuilder.append(SimpleFormat.format("%d error(s), %d warning(s), %.1f%% typed", manager.getErrorCount(), manager.getWarningCount(), manager.getTypedPercent()));
} else {
summaryBuilder.append(SimpleFormat.format("%d error(s), %d warning(s)", manager.getErrorCount(), manager.getWarningCount()));
}
jsonWriter.beginObject();
jsonWriter.name("level").value("info");
jsonWriter.name("description").value(summaryBuilder.toString());
jsonWriter.endObject();
jsonWriter.endArray();
jsonWriter.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
stream.append(bufferedStream.toString());
}
use of com.google.debugging.sourcemap.proto.Mapping.OriginalMapping in project closure-compiler by google.
the class LightweightMessageFormatter method format.
private String format(JSError error, boolean warning) {
SourceExcerptProvider source = getSource();
String sourceName = error.getSourceName();
int lineNumber = error.getLineNumber();
int charno = error.getCharno();
// Format the non-reverse-mapped position.
StringBuilder b = new StringBuilder();
StringBuilder boldLine = new StringBuilder();
OriginalMapping mapping = source == null ? null : source.getSourceMapping(error.getSourceName(), error.getLineNumber(), error.getCharno());
// Check if we can reverse-map the source.
if (includeLocation) {
if (mapping != null) {
appendPosition(b, sourceName, lineNumber, charno);
sourceName = mapping.getOriginalFile();
lineNumber = mapping.getLineNumber();
charno = mapping.getColumnPosition();
b.append("\nOriginally at:\n");
}
appendPosition(boldLine, sourceName, lineNumber, charno);
}
if (includeLevel) {
boldLine.append(getLevelName(warning ? CheckLevel.WARNING : CheckLevel.ERROR));
boldLine.append(" - [");
boldLine.append(error.getType().key);
boldLine.append("] ");
}
boldLine.append(error.getDescription());
b.append(maybeEmbolden(boldLine.toString()));
b.append('\n');
// For reverse-mapped sources, fall back to a single line excerpt because the excerpt length
// cannot be reliably mapped.
String sourceExcerptWithPosition = getExcerptWithPosition(error, sourceName, lineNumber, charno, mapping != null ? LINE : defaultFormat);
if (sourceExcerptWithPosition != null) {
b.append(sourceExcerptWithPosition);
}
return b.toString();
}
use of com.google.debugging.sourcemap.proto.Mapping.OriginalMapping in project closure-compiler by google.
the class SourceMapConsumerV3Test method testSourceMappingExactMatch.
@Test
public void testSourceMappingExactMatch() throws Exception {
consumer.parse(GSON.toJson(TestJsonBuilder.create().setVersion(3).setFile("testcode").setLineCount(1).setMappings("AAAAA,QAASA,UAAS,EAAG;").setSources("testcode").setNames("__BASIC__").build()));
OriginalMapping mapping = consumer.getMappingForLine(1, 1);
assertThat(mapping).isNotNull();
assertThat(mapping.getLineNumber()).isEqualTo(1);
assertThat(mapping.getPrecision()).isEqualTo(Precision.EXACT);
}
Aggregations