Search in sources :

Example 6 with OriginalMapping

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);
}
Also used : OriginalMapping(com.google.debugging.sourcemap.proto.Mapping.OriginalMapping) ArrayList(java.util.ArrayList) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException) JsonWriter(com.google.gson.stream.JsonWriter) OutputStreamWriter(java.io.OutputStreamWriter) GwtIncompatible(com.google.common.annotations.GwtIncompatible)

Example 7 with OriginalMapping

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);
}
Also used : OriginalMapping(com.google.debugging.sourcemap.proto.Mapping.OriginalMapping) Node(com.google.javascript.rhino.Node)

Example 8 with OriginalMapping

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());
}
Also used : OriginalMapping(com.google.debugging.sourcemap.proto.Mapping.OriginalMapping) ErrorWithLevel(com.google.javascript.jscomp.SortingErrorManager.ErrorWithLevel) Node(com.google.javascript.rhino.Node) OutputStreamWriter(java.io.OutputStreamWriter) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException) JsonWriter(com.google.gson.stream.JsonWriter) GwtIncompatible(com.google.common.annotations.GwtIncompatible)

Example 9 with OriginalMapping

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();
}
Also used : OriginalMapping(com.google.debugging.sourcemap.proto.Mapping.OriginalMapping)

Example 10 with OriginalMapping

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);
}
Also used : OriginalMapping(com.google.debugging.sourcemap.proto.Mapping.OriginalMapping) Test(org.junit.Test)

Aggregations

OriginalMapping (com.google.debugging.sourcemap.proto.Mapping.OriginalMapping)13 Test (org.junit.Test)4 SourceMapConsumerV3 (com.google.debugging.sourcemap.SourceMapConsumerV3)3 Node (com.google.javascript.rhino.Node)3 GwtIncompatible (com.google.common.annotations.GwtIncompatible)2 FilePosition (com.google.debugging.sourcemap.FilePosition)2 JsonWriter (com.google.gson.stream.JsonWriter)2 ByteArrayOutputStream (java.io.ByteArrayOutputStream)2 IOException (java.io.IOException)2 OutputStreamWriter (java.io.OutputStreamWriter)2 TypeToken (com.google.common.reflect.TypeToken)1 Builder (com.google.debugging.sourcemap.proto.Mapping.OriginalMapping.Builder)1 Builder (com.google.javascript.jscomp.JsMessage.Builder)1 ErrorWithLevel (com.google.javascript.jscomp.SortingErrorManager.ErrorWithLevel)1 StaticSourceFile (com.google.javascript.rhino.StaticSourceFile)1 StringWriter (java.io.StringWriter)1 ArrayList (java.util.ArrayList)1 Collection (java.util.Collection)1 Nullable (javax.annotation.Nullable)1