/** * Copyright (c) 2012-2016 André Bargull * Alle Rechte vorbehalten / All Rights Reserved. Use is subject to license terms. * * <https://github.com/anba/es6draft> */ package com.github.anba.es6draft.compiler; import java.nio.file.Path; import java.nio.file.Paths; import java.util.EnumSet; import java.util.Formatter; import java.util.Locale; import com.github.anba.es6draft.ast.FunctionNode; import com.github.anba.es6draft.ast.Module; import com.github.anba.es6draft.ast.Node; import com.github.anba.es6draft.ast.Script; import com.github.anba.es6draft.ast.scope.Scope; import com.github.anba.es6draft.ast.scope.ScriptScope; import com.github.anba.es6draft.compiler.assembler.SourceInfo; import com.github.anba.es6draft.runtime.internal.Source; /** * */ final class NodeSourceInfo { private NodeSourceInfo() { } static SourceInfo create(Script script, EnumSet<Compiler.Option> compilerOptions) { return new ScriptSourceInfo(script, compilerOptions.contains(Compiler.Option.SourceMap)); } static SourceInfo create(Module module, EnumSet<Compiler.Option> compilerOptions) { return new ModuleSourceInfo(module, compilerOptions.contains(Compiler.Option.SourceMap)); } static SourceInfo create(FunctionNode function, EnumSet<Compiler.Option> compilerOptions) { return new FunctionSourceInfo(function, compilerOptions.contains(Compiler.Option.SourceMap)); } private static final class ScriptSourceInfo implements SourceInfo { private final Script script; private final boolean includeSourceMap; ScriptSourceInfo(Script script, boolean includeSourceMap) { this.script = script; this.includeSourceMap = includeSourceMap; } @Override public String getFileName() { return script.getSource().getName(); } @Override public String getSourceMap() { return sourceMap(script, script.getSource(), includeSourceMap); } } private static final class ModuleSourceInfo implements SourceInfo { private final Module module; private final boolean includeSourceMap; ModuleSourceInfo(Module module, boolean includeSourceMap) { this.module = module; this.includeSourceMap = includeSourceMap; } @Override public String getFileName() { return module.getSource().getName(); } @Override public String getSourceMap() { return sourceMap(module, module.getSource(), includeSourceMap); } } private static final class FunctionSourceInfo implements SourceInfo { private final FunctionNode function; private final boolean includeSourceMap; FunctionSourceInfo(FunctionNode function, boolean includeSourceMap) { this.function = function; this.includeSourceMap = includeSourceMap; } @Override public String getFileName() { // return "<Function>"; return functionScript(function).getSource().getName(); } @Override public String getSourceMap() { Script script = functionScript(function); return sourceMap(script, script.getSource(), includeSourceMap); } private static Script functionScript(FunctionNode function) { Scope enclosingScope = function.getScope().getEnclosingScope(); assert enclosingScope instanceof ScriptScope; return ((ScriptScope) enclosingScope).getNode(); } } private static String sourceMap(Node node, Source source, boolean includeSourceMap) { if (!includeSourceMap) { return null; } Path sourceFile = source.getFile(); if (sourceFile == null) { // return if 'sourceFile' is not available return null; } Path relativePath = Paths.get("").toAbsolutePath().relativize(sourceFile); try (Formatter smap = new Formatter(Locale.ROOT)) { // Header // - ID smap.format("SMAP%n"); // - OutputFileName smap.format("%s%n", source.getName()); // - DefaultStratumId smap.format("Script%n"); // Section // - StratumSection smap.format("*S Script%n"); // - FileSection smap.format("*F%n"); // -- FileInfo smap.format("+ 1 %s%n%s%n", sourceFile.getFileName(), relativePath); // - LineSection smap.format("*L%n"); // -- LineInfo smap.format("%d#1,%d:%d%n", node.getBeginLine(), node.getEndLine(), node.getBeginLine()); // EndSection smap.format("*E%n"); return smap.toString(); } } }