|
Packit Service |
7770af |
#include "sass.hpp"
|
|
Packit Service |
7770af |
#include <string>
|
|
Packit Service |
7770af |
#include <sstream>
|
|
Packit Service |
7770af |
#include <iostream>
|
|
Packit Service |
7770af |
#include <iomanip>
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
#include "ast.hpp"
|
|
Packit Service |
7770af |
#include "json.hpp"
|
|
Packit Service |
7770af |
#include "context.hpp"
|
|
Packit Service |
7770af |
#include "position.hpp"
|
|
Packit Service |
7770af |
#include "source_map.hpp"
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
namespace Sass {
|
|
Packit Service |
7770af |
SourceMap::SourceMap() : current_position(0, 0, 0), file("stdin") { }
|
|
Packit Service |
7770af |
SourceMap::SourceMap(const std::string& file) : current_position(0, 0, 0), file(file) { }
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
std::string SourceMap::render_srcmap(Context &ctx) {
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
const bool include_sources = ctx.c_options.source_map_contents;
|
|
Packit Service |
7770af |
const std::vector<std::string> links = ctx.srcmap_links;
|
|
Packit Service |
7770af |
const std::vector<Resource>& sources(ctx.resources);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
JsonNode* json_srcmap = json_mkobject();
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
json_append_member(json_srcmap, "version", json_mknumber(3));
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
const char *file_name = file.c_str();
|
|
Packit Service |
7770af |
JsonNode *json_file_name = json_mkstring(file_name);
|
|
Packit Service |
7770af |
json_append_member(json_srcmap, "file", json_file_name);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// pass-through sourceRoot option
|
|
Packit Service |
7770af |
if (!ctx.source_map_root.empty()) {
|
|
Packit Service |
7770af |
JsonNode* root = json_mkstring(ctx.source_map_root.c_str());
|
|
Packit Service |
7770af |
json_append_member(json_srcmap, "sourceRoot", root);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
JsonNode *json_sources = json_mkarray();
|
|
Packit Service |
7770af |
for (size_t i = 0; i < source_index.size(); ++i) {
|
|
Packit Service |
7770af |
std::string source(links[source_index[i]]);
|
|
Packit Service |
7770af |
if (ctx.c_options.source_map_file_urls) {
|
|
Packit Service |
7770af |
source = File::rel2abs(source);
|
|
Packit Service |
7770af |
// check for windows abs path
|
|
Packit Service |
7770af |
if (source[0] == '/') {
|
|
Packit Service |
7770af |
// ends up with three slashes
|
|
Packit Service |
7770af |
source = "file://" + source;
|
|
Packit Service |
7770af |
} else {
|
|
Packit Service |
7770af |
// needs an additional slash
|
|
Packit Service |
7770af |
source = "file:///" + source;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
const char* source_name = source.c_str();
|
|
Packit Service |
7770af |
JsonNode *json_source_name = json_mkstring(source_name);
|
|
Packit Service |
7770af |
json_append_element(json_sources, json_source_name);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
json_append_member(json_srcmap, "sources", json_sources);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
if (include_sources && source_index.size()) {
|
|
Packit Service |
7770af |
JsonNode *json_contents = json_mkarray();
|
|
Packit Service |
7770af |
for (size_t i = 0; i < source_index.size(); ++i) {
|
|
Packit Service |
7770af |
const Resource& resource(sources[source_index[i]]);
|
|
Packit Service |
7770af |
JsonNode *json_content = json_mkstring(resource.contents);
|
|
Packit Service |
7770af |
json_append_element(json_contents, json_content);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
json_append_member(json_srcmap, "sourcesContent", json_contents);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
JsonNode *json_names = json_mkarray();
|
|
Packit Service |
7770af |
// so far we have no implementation for names
|
|
Packit Service |
7770af |
// no problem as we do not alter any identifiers
|
|
Packit Service |
7770af |
json_append_member(json_srcmap, "names", json_names);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
std::string mappings = serialize_mappings();
|
|
Packit Service |
7770af |
JsonNode *json_mappings = json_mkstring(mappings.c_str());
|
|
Packit Service |
7770af |
json_append_member(json_srcmap, "mappings", json_mappings);
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
char *str = json_stringify(json_srcmap, "\t");
|
|
Packit Service |
7770af |
std::string result = std::string(str);
|
|
Packit Service |
7770af |
free(str);
|
|
Packit Service |
7770af |
json_delete(json_srcmap);
|
|
Packit Service |
7770af |
return result;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
std::string SourceMap::serialize_mappings() {
|
|
Packit Service |
7770af |
std::string result = "";
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
size_t previous_generated_line = 0;
|
|
Packit Service |
7770af |
size_t previous_generated_column = 0;
|
|
Packit Service |
7770af |
size_t previous_original_line = 0;
|
|
Packit Service |
7770af |
size_t previous_original_column = 0;
|
|
Packit Service |
7770af |
size_t previous_original_file = 0;
|
|
Packit Service |
7770af |
for (size_t i = 0; i < mappings.size(); ++i) {
|
|
Packit Service |
7770af |
const size_t generated_line = mappings[i].generated_position.line;
|
|
Packit Service |
7770af |
const size_t generated_column = mappings[i].generated_position.column;
|
|
Packit Service |
7770af |
const size_t original_line = mappings[i].original_position.line;
|
|
Packit Service |
7770af |
const size_t original_column = mappings[i].original_position.column;
|
|
Packit Service |
7770af |
const size_t original_file = mappings[i].original_position.file;
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
if (generated_line != previous_generated_line) {
|
|
Packit Service |
7770af |
previous_generated_column = 0;
|
|
Packit Service |
7770af |
if (generated_line > previous_generated_line) {
|
|
Packit Service |
7770af |
result += std::string(generated_line - previous_generated_line, ';');
|
|
Packit Service |
7770af |
previous_generated_line = generated_line;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
else if (i > 0) {
|
|
Packit Service |
7770af |
result += ",";
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
// generated column
|
|
Packit Service |
7770af |
result += base64vlq.encode(static_cast<int>(generated_column) - static_cast<int>(previous_generated_column));
|
|
Packit Service |
7770af |
previous_generated_column = generated_column;
|
|
Packit Service |
7770af |
// file
|
|
Packit Service |
7770af |
result += base64vlq.encode(static_cast<int>(original_file) - static_cast<int>(previous_original_file));
|
|
Packit Service |
7770af |
previous_original_file = original_file;
|
|
Packit Service |
7770af |
// source line
|
|
Packit Service |
7770af |
result += base64vlq.encode(static_cast<int>(original_line) - static_cast<int>(previous_original_line));
|
|
Packit Service |
7770af |
previous_original_line = original_line;
|
|
Packit Service |
7770af |
// source column
|
|
Packit Service |
7770af |
result += base64vlq.encode(static_cast<int>(original_column) - static_cast<int>(previous_original_column));
|
|
Packit Service |
7770af |
previous_original_column = original_column;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
return result;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
void SourceMap::prepend(const OutputBuffer& out)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
Offset size(out.smap.current_position);
|
|
Packit Service |
7770af |
for (Mapping mapping : out.smap.mappings) {
|
|
Packit Service |
7770af |
if (mapping.generated_position.line > size.line) {
|
|
Packit Service |
7770af |
throw(std::runtime_error("prepend sourcemap has illegal line"));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
if (mapping.generated_position.line == size.line) {
|
|
Packit Service |
7770af |
if (mapping.generated_position.column > size.column) {
|
|
Packit Service |
7770af |
throw(std::runtime_error("prepend sourcemap has illegal column"));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// will adjust the offset
|
|
Packit Service |
7770af |
prepend(Offset(out.buffer));
|
|
Packit Service |
7770af |
// now add the new mappings
|
|
Packit Service |
7770af |
VECTOR_UNSHIFT(mappings, out.smap.mappings);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
void SourceMap::append(const OutputBuffer& out)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
append(Offset(out.buffer));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
void SourceMap::prepend(const Offset& offset)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
if (offset.line != 0 || offset.column != 0) {
|
|
Packit Service |
7770af |
for (Mapping& mapping : mappings) {
|
|
Packit Service |
7770af |
// move stuff on the first old line
|
|
Packit Service |
7770af |
if (mapping.generated_position.line == 0) {
|
|
Packit Service |
7770af |
mapping.generated_position.column += offset.column;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
// make place for the new lines
|
|
Packit Service |
7770af |
mapping.generated_position.line += offset.line;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
if (current_position.line == 0) {
|
|
Packit Service |
7770af |
current_position.column += offset.column;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
current_position.line += offset.line;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
void SourceMap::append(const Offset& offset)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
current_position += offset;
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
void SourceMap::add_open_mapping(const AST_Node_Ptr node)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
mappings.push_back(Mapping(node->pstate(), current_position));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
void SourceMap::add_close_mapping(const AST_Node_Ptr node)
|
|
Packit Service |
7770af |
{
|
|
Packit Service |
7770af |
mappings.push_back(Mapping(node->pstate() + node->pstate().offset, current_position));
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
ParserState SourceMap::remap(const ParserState& pstate) {
|
|
Packit Service |
7770af |
for (size_t i = 0; i < mappings.size(); ++i) {
|
|
Packit Service |
7770af |
if (
|
|
Packit Service |
7770af |
mappings[i].generated_position.file == pstate.file &&
|
|
Packit Service |
7770af |
mappings[i].generated_position.line == pstate.line &&
|
|
Packit Service |
7770af |
mappings[i].generated_position.column == pstate.column
|
|
Packit Service |
7770af |
) return ParserState(pstate.path, pstate.src, mappings[i].original_position, pstate.offset);
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
return ParserState(pstate.path, pstate.src, Position(-1, -1, -1), Offset(0, 0));
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
}
|
|
Packit Service |
7770af |
|
|
Packit Service |
7770af |
}
|