Skip to content

Commit efeace5

Browse files
committed
Merge pull request #1000 from mgreter/feature/expose-file-resolver
Implement support for multiple importers
2 parents ba0b3e0 + f98127a commit efeace5

24 files changed

+755
-440
lines changed

ast.hpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -644,15 +644,17 @@ namespace Sass {
644644
ADD_PROPERTY(Env*, environment);
645645
ADD_PROPERTY(Type, type);
646646
ADD_PROPERTY(Native_Function, native_function);
647-
ADD_PROPERTY(Sass_C_Function, c_function);
647+
ADD_PROPERTY(Sass_Function_Entry, c_function);
648648
ADD_PROPERTY(void*, cookie);
649+
ADD_PROPERTY(Context*, ctx);
649650
ADD_PROPERTY(bool, is_overload_stub);
650651
ADD_PROPERTY(Signature, signature);
651652
public:
652653
Definition(ParserState pstate,
653654
string n,
654655
Parameters* params,
655656
Block* b,
657+
Context* ctx,
656658
Type t)
657659
: Has_Block(pstate, b),
658660
name_(n),
@@ -662,6 +664,7 @@ namespace Sass {
662664
native_function_(0),
663665
c_function_(0),
664666
cookie_(0),
667+
ctx_(ctx),
665668
is_overload_stub_(false),
666669
signature_(0)
667670
{ }
@@ -670,6 +673,7 @@ namespace Sass {
670673
string n,
671674
Parameters* params,
672675
Native_Function func_ptr,
676+
Context* ctx,
673677
bool overload_stub = false)
674678
: Has_Block(pstate, 0),
675679
name_(n),
@@ -679,15 +683,16 @@ namespace Sass {
679683
native_function_(func_ptr),
680684
c_function_(0),
681685
cookie_(0),
686+
ctx_(ctx),
682687
is_overload_stub_(overload_stub),
683688
signature_(sig)
684689
{ }
685690
Definition(ParserState pstate,
686691
Signature sig,
687692
string n,
688693
Parameters* params,
689-
Sass_C_Function func_ptr,
690-
void* cookie,
694+
Sass_Function_Entry c_func,
695+
Context* ctx,
691696
bool whatever,
692697
bool whatever2)
693698
: Has_Block(pstate, 0),
@@ -696,8 +701,9 @@ namespace Sass {
696701
environment_(0),
697702
type_(FUNCTION),
698703
native_function_(0),
699-
c_function_(func_ptr),
700-
cookie_(cookie),
704+
c_function_(c_func),
705+
cookie_(sass_function_get_cookie(c_func)),
706+
ctx_(ctx),
701707
is_overload_stub_(false),
702708
signature_(sig)
703709
{ }

context.cpp

Lines changed: 67 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -50,18 +50,25 @@ namespace Sass {
5050
this->source = source;
5151
}
5252

53+
inline bool sort_importers (const Sass_Importer_Entry& i, const Sass_Importer_Entry& j)
54+
{ return sass_importer_get_priority(i) > sass_importer_get_priority(j); }
5355

5456
Context::Context(Context::Data initializers)
5557
: // Output(this),
58+
head_imports(0),
5659
mem(Memory_Manager<AST_Node>()),
60+
c_options (initializers.c_options()),
61+
c_compiler (initializers.c_compiler()),
5762
source_c_str (initializers.source_c_str()),
5863
sources (vector<const char*>()),
5964
plugin_paths (initializers.plugin_paths()),
6065
include_paths (initializers.include_paths()),
6166
queue (vector<Sass_Queued>()),
6267
style_sheets (map<string, Block*>()),
6368
emitter (this),
64-
c_functions (vector<Sass_C_Function_Callback>()),
69+
c_headers (vector<Sass_Importer_Entry>()),
70+
c_importers (vector<Sass_Importer_Entry>()),
71+
c_functions (vector<Sass_Function_Entry>()),
6572
indent (initializers.indent()),
6673
linefeed (initializers.linefeed()),
6774
input_path (make_canonical_path(initializers.input_path())),
@@ -74,7 +81,6 @@ namespace Sass {
7481
source_map_contents (initializers.source_map_contents()),
7582
omit_source_map_url (initializers.omit_source_map_url()),
7683
is_indented_syntax_src (initializers.is_indented_syntax_src()),
77-
importer (initializers.importer()),
7884
names_to_colors (map<string, Color*>()),
7985
colors_to_names (map<int, string>()),
8086
precision (initializers.precision()),
@@ -91,9 +97,9 @@ namespace Sass {
9197

9298
include_paths.push_back(cwd);
9399
collect_include_paths(initializers.include_paths_c_str());
94-
collect_include_paths(initializers.include_paths_array());
100+
// collect_include_paths(initializers.include_paths_array());
95101
collect_plugin_paths(initializers.plugin_paths_c_str());
96-
collect_plugin_paths(initializers.plugin_paths_array());
102+
// collect_plugin_paths(initializers.plugin_paths_array());
97103

98104
setup_color_map();
99105

@@ -104,7 +110,15 @@ namespace Sass {
104110
for(auto fn : plugins.get_functions()) {
105111
c_functions.push_back(fn);
106112
}
113+
for(auto fn : plugins.get_headers()) {
114+
c_headers.push_back(fn);
115+
}
116+
for(auto fn : plugins.get_importers()) {
117+
c_importers.push_back(fn);
118+
}
107119

120+
sort (c_headers.begin(), c_headers.end(), sort_importers);
121+
sort (c_importers.begin(), c_importers.end(), sort_importers);
108122
string entry_point = initializers.entry_point();
109123
if (!entry_point.empty()) {
110124
string result(add_file(entry_point));
@@ -117,6 +131,23 @@ namespace Sass {
117131

118132
}
119133

134+
void Context::add_c_function(Sass_Function_Entry function)
135+
{
136+
c_functions.push_back(function);
137+
}
138+
void Context::add_c_header(Sass_Importer_Entry header)
139+
{
140+
c_headers.push_back(header);
141+
// need to sort the array afterwards (no big deal)
142+
sort (c_headers.begin(), c_headers.end(), sort_importers);
143+
}
144+
void Context::add_c_importer(Sass_Importer_Entry importer)
145+
{
146+
c_importers.push_back(importer);
147+
// need to sort the array afterwards (no big deal)
148+
sort (c_importers.begin(), c_importers.end(), sort_importers);
149+
}
150+
120151
Context::~Context()
121152
{
122153
// everything that gets put into sources will be freed by us
@@ -225,58 +256,45 @@ namespace Sass {
225256
include_links.push_back(resolve_relative_path(abs_path, source_map_file, cwd));
226257
}
227258

228-
string Context::add_file(string path)
259+
// Add a new import file to the context
260+
string Context::add_file(const string& file)
229261
{
230262
using namespace File;
231-
char* contents = 0;
232-
string real_path;
233-
path = make_canonical_path(path);
234-
for (size_t i = 0, S = include_paths.size(); i < S; ++i) {
235-
string full_path(join_paths(include_paths[i], path));
236-
if (style_sheets.count(full_path)) return full_path;
237-
contents = resolve_and_load(full_path, real_path);
238-
if (contents) {
239-
add_source(full_path, real_path, contents);
240-
style_sheets[full_path] = 0;
241-
return full_path;
242-
}
263+
string path(make_canonical_path(file));
264+
string resolved(find_file(path, include_paths));
265+
if (resolved == "") return resolved;
266+
if (char* contents = read_file(resolved)) {
267+
add_source(path, resolved, contents);
268+
style_sheets[path] = 0;
269+
return path;
243270
}
244-
return string();
271+
return string("");
245272
}
246273

247-
string Context::add_file(string dir, string rel_filepath)
274+
// Add a new import file to the context
275+
// This has some previous directory context
276+
string Context::add_file(const string& base, const string& file)
248277
{
249278
using namespace File;
250-
char* contents = 0;
251-
string real_path;
252-
rel_filepath = make_canonical_path(rel_filepath);
253-
string full_path(join_paths(dir, rel_filepath));
254-
if (style_sheets.count(full_path)) return full_path;
255-
contents = resolve_and_load(full_path, real_path);
256-
if (contents) {
257-
add_source(full_path, real_path, contents);
258-
style_sheets[full_path] = 0;
259-
return full_path;
260-
}
261-
for (size_t i = 0, S = include_paths.size(); i < S; ++i) {
262-
string full_path(join_paths(include_paths[i], rel_filepath));
263-
if (style_sheets.count(full_path)) return full_path;
264-
contents = resolve_and_load(full_path, real_path);
265-
if (contents) {
266-
add_source(full_path, real_path, contents);
267-
style_sheets[full_path] = 0;
268-
return full_path;
269-
}
279+
string path(make_canonical_path(file));
280+
string base_file(join_paths(base, path));
281+
string resolved(resolve_file(base_file));
282+
if (style_sheets.count(base_file)) return base_file;
283+
if (char* contents = read_file(resolved)) {
284+
add_source(base_file, resolved, contents);
285+
style_sheets[base_file] = 0;
286+
return base_file;
270287
}
271-
return string();
288+
// now go the regular code path
289+
return add_file(path);
272290
}
273291

274292
void register_function(Context&, Signature sig, Native_Function f, Env* env);
275293
void register_function(Context&, Signature sig, Native_Function f, size_t arity, Env* env);
276294
void register_overload_stub(Context&, string name, Env* env);
277295
void register_built_in_functions(Context&, Env* env);
278-
void register_c_functions(Context&, Env* env, Sass_C_Function_List);
279-
void register_c_function(Context&, Env* env, Sass_C_Function_Callback);
296+
void register_c_functions(Context&, Env* env, Sass_Function_List);
297+
void register_c_function(Context&, Env* env, Sass_Function_Entry);
280298

281299
char* Context::compile_block(Block* root)
282300
{
@@ -295,7 +313,7 @@ namespace Sass {
295313
{
296314
Block* root = 0;
297315
for (size_t i = 0; i < queue.size(); ++i) {
298-
struct Sass_Import* import = sass_make_import(
316+
Sass_Import_Entry import = sass_make_import(
299317
queue[i].load_path.c_str(),
300318
queue[i].abs_path.c_str(),
301319
0, 0
@@ -388,7 +406,9 @@ namespace Sass {
388406
std::vector<std::string> Context::get_included_files(size_t skip)
389407
{
390408
vector<string> includes = included_files;
409+
if (includes.size() == 0) return includes;
391410
std::sort( includes.begin() + skip, includes.end() );
411+
includes.erase( includes.begin(), includes.begin() + skip );
392412
includes.erase( std::unique( includes.begin(), includes.end() ), includes.end() );
393413
// the skip solution seems more robust, as we may have real files named stdin
394414
// includes.erase( std::remove( includes.begin(), includes.end(), "stdin" ), includes.end() );
@@ -423,6 +443,7 @@ namespace Sass {
423443
name,
424444
0,
425445
0,
446+
&ctx,
426447
true);
427448
(*env)[name + "[f]"] = stub;
428449
}
@@ -521,21 +542,16 @@ namespace Sass {
521542
register_function(ctx, unique_id_sig, unique_id, env);
522543
}
523544

524-
void register_c_functions(Context& ctx, Env* env, Sass_C_Function_List descrs)
545+
void register_c_functions(Context& ctx, Env* env, Sass_Function_List descrs)
525546
{
526547
while (descrs && *descrs) {
527548
register_c_function(ctx, env, *descrs);
528549
++descrs;
529550
}
530551
}
531-
void register_c_function(Context& ctx, Env* env, Sass_C_Function_Callback descr)
552+
void register_c_function(Context& ctx, Env* env, Sass_Function_Entry descr)
532553
{
533-
Definition* def = make_c_function(
534-
sass_function_get_signature(descr),
535-
sass_function_get_function(descr),
536-
sass_function_get_cookie(descr),
537-
ctx
538-
);
554+
Definition* def = make_c_function(descr, ctx);
539555
def->environment(env);
540556
(*env)[def->name() + "[f]"] = def;
541557
}

context.hpp

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#include "plugins.hpp"
1919
#include "sass_functions.h"
2020

21-
struct Sass_C_Function_Descriptor;
21+
struct Sass_Function;
2222

2323
namespace Sass {
2424
using namespace std;
@@ -32,8 +32,11 @@ namespace Sass {
3232

3333
class Context {
3434
public:
35+
size_t head_imports;
3536
Memory_Manager<AST_Node> mem;
3637

38+
struct Sass_Options* c_options;
39+
struct Sass_Compiler* c_compiler;
3740
const char* source_c_str;
3841

3942
// c-strs containing Sass file contents
@@ -51,7 +54,14 @@ namespace Sass {
5154
map<string, Block*> style_sheets; // map of paths to ASTs
5255
// SourceMap source_map;
5356
Output emitter;
54-
vector<Sass_C_Function_Callback> c_functions;
57+
58+
vector<Sass_Importer_Entry> c_headers;
59+
vector<Sass_Importer_Entry> c_importers;
60+
vector<Sass_Function_Entry> c_functions;
61+
62+
void add_c_header(Sass_Importer_Entry header);
63+
void add_c_importer(Sass_Importer_Entry importer);
64+
void add_c_function(Sass_Function_Entry function);
5565

5666
string indent; // String to be used for indentation
5767
string linefeed; // String to be used for line feeds
@@ -67,15 +77,16 @@ namespace Sass {
6777
bool is_indented_syntax_src; // treat source string as sass
6878

6979
// overload import calls
70-
Sass_C_Import_Callback importer;
71-
vector<struct Sass_Import*> import_stack;
80+
vector<Sass_Import_Entry> import_stack;
7281

7382
map<string, Color*> names_to_colors;
7483
map<int, string> colors_to_names;
7584

7685
size_t precision; // precision for outputting fractional numbers
7786

7887
KWD_ARG_SET(Data) {
88+
KWD_ARG(Data, struct Sass_Options*, c_options);
89+
KWD_ARG(Data, struct Sass_Compiler*, c_compiler);
7990
KWD_ARG(Data, const char*, source_c_str);
8091
KWD_ARG(Data, string, entry_point);
8192
KWD_ARG(Data, string, input_path);
@@ -84,8 +95,8 @@ namespace Sass {
8495
KWD_ARG(Data, string, linefeed);
8596
KWD_ARG(Data, const char*, include_paths_c_str);
8697
KWD_ARG(Data, const char*, plugin_paths_c_str);
87-
KWD_ARG(Data, const char**, include_paths_array);
88-
KWD_ARG(Data, const char**, plugin_paths_array);
98+
// KWD_ARG(Data, const char**, include_paths_array);
99+
// KWD_ARG(Data, const char**, plugin_paths_array);
89100
KWD_ARG(Data, vector<string>, include_paths);
90101
KWD_ARG(Data, vector<string>, plugin_paths);
91102
KWD_ARG(Data, bool, source_comments);
@@ -97,18 +108,21 @@ namespace Sass {
97108
KWD_ARG(Data, size_t, precision);
98109
KWD_ARG(Data, bool, source_map_embed);
99110
KWD_ARG(Data, bool, source_map_contents);
100-
KWD_ARG(Data, Sass_C_Import_Callback, importer);
101111
};
102112

103113
Context(Data);
104114
~Context();
105115
static string get_cwd();
106116
void setup_color_map();
107-
string add_file(string);
117+
108118
Block* parse_file();
109-
string add_file(string, string);
110119
Block* parse_string();
111120
void add_source(string, string, const char*);
121+
122+
string add_file(const string& file);
123+
string add_file(const string& base, const string& file);
124+
125+
112126
// allow to optionally overwrite the input path
113127
// default argument for input_path is string("stdin")
114128
// usefull to influence the source-map generating etc.

0 commit comments

Comments
 (0)