use of com.google.debugging.sourcemap.proto.Mapping.OriginalMapping in project closure-compiler by google.
the class SourceMap method addMapping.
public void addMapping(Node node, FilePosition outputStartPosition, FilePosition outputEndPosition) {
// If the node does not have an associated source file or
// its line number is -1, then the node does not have sufficient
// information for a mapping to be useful.
StaticSourceFile sourceFile = node.getStaticSourceFile();
if (sourceFile == null || node.getLineno() < 0) {
return;
}
String sourceFileName = sourceFile.getName();
int lineNo = node.getLineno();
int charNo = node.getCharno();
String originalName = SourceMap.getOriginalName(node);
if (mapping != null) {
OriginalMapping sourceMapping = mapping.getSourceMapping(sourceFileName, lineNo, charNo);
if (sourceMapping != null) {
sourceFileName = sourceMapping.getOriginalFile();
lineNo = sourceMapping.getLineNumber();
charNo = sourceMapping.getColumnPosition();
String identifier = sourceMapping.getIdentifier();
if (sourceMapping.hasIdentifier() && !identifier.isEmpty()) {
originalName = identifier;
}
}
}
sourceFileName = fixupSourceLocation(sourceFileName);
// Rhino source lines are one based but for v3 source maps, we make
// them zero based.
int lineBaseOffset = 1;
generator.addMapping(sourceFileName, originalName, new FilePosition(lineNo - lineBaseOffset, charNo), outputStartPosition, outputEndPosition);
}
use of com.google.debugging.sourcemap.proto.Mapping.OriginalMapping in project closure-compiler by google.
the class SourceMapConsumerV3Test method testSourceMappingApproximatedLine.
@Test
public void testSourceMappingApproximatedLine() throws Exception {
consumer.parse(GSON.toJson(TestJsonBuilder.create().setVersion(3).setMappings(";;;;;;;;;;;;;;;;;;IAAMA,K,GACL,eAAaC,EAAb,EAAiB;AAAA;;AAAA;;AAChB,OAAKA,EAAL,GAAUA,EAAV;AACA,C;;IAEIC,S;;;;;;;AACL,qBAAYD,EAAZ,EAAgB;AAAA;;AAAA,6BACTA,EADS;AAEf;;;EAHsBD,K;;AAKxB,IAAIG,CAAC,GAAG,IAAID,SAAJ,CAAc,UAAd,CAAR").setSourcesContent("class Shape {\n" + "\tconstructor (id) {\n" + "\t\tthis.id = id;\n" + "\t}\n" + "}\n" + "class Rectangle extends Shape {\n" + "\tconstructor(id) {\n" + "\t\tsuper(id);\n" + "\t}\n" + "}\n" + "var s = new Rectangle(\"Shape ID\");").setSources("testcode").setNames("Shape", "id", "Rectangle", "s").build()));
OriginalMapping mapping = consumer.getMappingForLine(40, 10);
assertThat(mapping).isNotNull();
// The Previous line mapping was retrieved, and thus it is "approximated"
assertThat(mapping.getLineNumber()).isEqualTo(9);
assertThat(mapping.getPrecision()).isEqualTo(Precision.APPROXIMATE_LINE);
}
use of com.google.debugging.sourcemap.proto.Mapping.OriginalMapping in project closure-compiler by google.
the class Compiler method getSourceMapping.
@Override
@Nullable
public OriginalMapping getSourceMapping(String sourceName, int lineNumber, int columnNumber) {
if (sourceName == null) {
return null;
}
SourceMapInput sourceMap = inputSourceMaps.get(sourceName);
if (sourceMap == null) {
return null;
}
// JSCompiler uses 1-indexing for lineNumber and 0-indexing for columnNumber.
// Sourcemaps use 1-indexing for both.
SourceMapConsumerV3 consumer = sourceMap.getSourceMap(errorManager);
if (consumer == null) {
return null;
}
OriginalMapping result = consumer.getMappingForLine(lineNumber, columnNumber + 1);
if (result == null) {
return null;
}
// First check to see if the original file was loaded from an input source map.
String sourceMapOriginalPath = sourceMap.getOriginalPath();
String resultOriginalPath = result.getOriginalFile();
final String relativePath;
// Resolving the paths to a source file is expensive, so check the cache first.
if (sourceMapOriginalPath.equals(resolvedSourceMap.originalPath) && resultOriginalPath.equals(resolvedSourceMap.sourceMapPath)) {
relativePath = resolvedSourceMap.relativePath;
} else {
relativePath = resolveSibling(sourceMapOriginalPath, resultOriginalPath);
SourceFile source = getSourceFileByName(relativePath);
if (source == null && !isNullOrEmpty(resultOriginalPath)) {
source = SourceMapResolver.getRelativePath(sourceMap.getOriginalPath(), result.getOriginalFile());
if (source != null) {
sourceMapOriginalSources.putIfAbsent(relativePath, source);
}
}
// Cache this resolved source for the next caller.
resolvedSourceMap.originalPath = sourceMapOriginalPath;
resolvedSourceMap.sourceMapPath = resultOriginalPath;
resolvedSourceMap.relativePath = relativePath;
}
return result.toBuilder().setOriginalFile(relativePath).setColumnPosition(result.getColumnPosition() - 1).build();
}
use of com.google.debugging.sourcemap.proto.Mapping.OriginalMapping in project closure-compiler by google.
the class SourceMapConsumerV3 method createReverseMapping.
/**
* Reverse the source map; the created mapping will allow us to quickly go
* from a source file and line number to a collection of target
* OriginalMappings.
*/
private void createReverseMapping() {
reverseSourceMapping = new HashMap<>();
for (int targetLine = 0; targetLine < lines.size(); targetLine++) {
ArrayList<Entry> entries = lines.get(targetLine);
if (entries != null) {
for (Entry entry : entries) {
if (entry.getSourceFileId() != UNMAPPED && entry.getSourceLine() != UNMAPPED) {
String originalFile = sources[entry.getSourceFileId()];
if (!reverseSourceMapping.containsKey(originalFile)) {
reverseSourceMapping.put(originalFile, new HashMap<Integer, Collection<OriginalMapping>>());
}
Map<Integer, Collection<OriginalMapping>> lineToCollectionMap = reverseSourceMapping.get(originalFile);
int sourceLine = entry.getSourceLine();
if (!lineToCollectionMap.containsKey(sourceLine)) {
lineToCollectionMap.put(sourceLine, new ArrayList<OriginalMapping>(1));
}
Collection<OriginalMapping> mappings = lineToCollectionMap.get(sourceLine);
Builder builder = OriginalMapping.newBuilder().setLineNumber(targetLine).setColumnPosition(entry.getGeneratedColumn());
mappings.add(builder.build());
}
}
}
}
}
use of com.google.debugging.sourcemap.proto.Mapping.OriginalMapping in project closure-compiler by google.
the class JsMessageVisitor method visit.
@Override
public void visit(NodeTraversal traversal, Node node, Node parent) {
String messageKey;
String originalMessageKey;
boolean isVar;
Node msgNode;
switch(node.getToken()) {
case NAME:
// var MSG_HELLO = 'Message'
if ((parent != null) && (NodeUtil.isNameDeclaration(parent))) {
messageKey = node.getString();
originalMessageKey = node.getOriginalName();
isVar = true;
} else {
return;
}
msgNode = node.getFirstChild();
break;
case ASSIGN:
// somenamespace.someclass.MSG_HELLO = 'Message'
isVar = false;
Node getProp = node.getFirstChild();
if (!getProp.isGetProp()) {
return;
}
Node propNode = getProp.getLastChild();
messageKey = propNode.getString();
originalMessageKey = getProp.getOriginalName();
msgNode = node.getLastChild();
break;
case STRING_KEY:
if (node.isQuotedString() || !node.hasChildren()) {
return;
}
isVar = false;
messageKey = node.getString();
originalMessageKey = node.getOriginalName();
msgNode = node.getFirstChild();
break;
case CALL:
// goog.getMsg()
if (node.getFirstChild().matchesQualifiedName(MSG_FUNCTION_NAME)) {
googMsgNodes.add(node);
} else if (node.getFirstChild().matchesQualifiedName(MSG_FALLBACK_FUNCTION_NAME)) {
visitFallbackFunctionCall(traversal, node);
}
return;
default:
return;
}
if (originalMessageKey != null) {
messageKey = originalMessageKey;
}
// Is this a message name?
boolean isNewStyleMessage = msgNode != null && msgNode.isCall();
if (!isMessageName(messageKey, isNewStyleMessage)) {
return;
}
if (msgNode == null) {
compiler.report(traversal.makeError(node, MESSAGE_HAS_NO_VALUE, messageKey));
return;
}
if (msgNode.isGetProp() && msgNode.isQualifiedName() && msgNode.getLastChild().getString().equals(messageKey)) {
// message will have already been extracted from the base class.
return;
}
// (e.g. "a.b.MSG_X") 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(traversal.makeError(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);
Builder builder = new Builder(isUnnamedMsg ? null : messageKey);
OriginalMapping mapping = compiler.getSourceMapping(traversal.getSourceName(), traversal.getLineNumber(), traversal.getCharno());
if (mapping != null) {
builder.setSourceName(mapping.getOriginalFile());
} else {
builder.setSourceName(traversal.getSourceName());
}
try {
if (isVar) {
extractMessageFromVariable(builder, node, parent, parent.getParent());
} else {
extractMessageFrom(builder, msgNode, node);
}
} catch (MalformedException ex) {
compiler.report(traversal.makeError(ex.getNode(), MESSAGE_TREE_MALFORMED, ex.getMessage()));
return;
}
JsMessage extractedMessage = builder.build(idGenerator);
// If asked to check named internal messages.
if (needToCheckDuplications && !isUnnamedMsg && !extractedMessage.isExternal()) {
checkIfMessageDuplicated(messageKey, msgNode);
}
trackMessage(traversal, extractedMessage, messageKey, msgNode, isUnnamedMsg);
if (extractedMessage.isEmpty()) {
// value of the message is an empty string. Translators do not like it.
compiler.report(traversal.makeError(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(traversal.makeError(node, MESSAGE_HAS_NO_DESCRIPTION, messageKey));
}
JsMessageDefinition msgDefinition = new JsMessageDefinition(msgNode);
processJsMessage(extractedMessage, msgDefinition);
}
Aggregations