diff options
author | German M. Bravo <german.mb@deipi.com> | 2013-10-04 15:23:51 -0500 |
---|---|---|
committer | German M. Bravo <german.mb@deipi.com> | 2013-10-04 15:23:51 -0500 |
commit | 4ab721722ccc1473cbf32c1407d26f84e613bb98 (patch) | |
tree | 48ae126229d709e5a8f80c6637dc32f75d0ddb36 | |
parent | f11f1ec17aa7babcf20ce87629fd4f9394fa8994 (diff) | |
download | pyscss-4ab721722ccc1473cbf32c1407d26f84e613bb98.tar.gz |
Added "Unused @import" warning message
-rw-r--r-- | scss/__init__.py | 31 | ||||
-rw-r--r-- | scss/rule.py | 29 | ||||
-rw-r--r-- | scss/tests/files/kronuz/imports-unused.css | 6 | ||||
-rw-r--r-- | scss/tests/files/kronuz/imports-unused.scss | 14 |
4 files changed, 65 insertions, 15 deletions
diff --git a/scss/__init__.py b/scss/__init__.py index 9193d29..284744e 100644 --- a/scss/__init__.py +++ b/scss/__init__.py @@ -146,7 +146,7 @@ class SourceFile(object): self.line_numbers = line_numbers self.line_strip = line_strip self.contents = self.prepare_source(contents) - self.parent_dir = parent_dir + self.parent_dir = os.path.realpath(parent_dir) self.is_string = is_string @classmethod @@ -494,6 +494,8 @@ class Scss(object): for rule in children: self.manage_children(rule, scope) + root_namespace.warn_unused_imports() + @print_timing(4) def manage_children(self, rule, scope): try: @@ -652,7 +654,7 @@ class Scss(object): if default is not None: defaults[var_name] = default - mixin = [list(new_params), defaults, block.unparsed_contents, rule.namespace, argspec_node] + mixin = [list(new_params), defaults, block.unparsed_contents, rule.namespace, argspec_node, rule.import_key] if block.directive == '@function': def _call(mixin): def __call(namespace, *args, **kwargs): @@ -662,6 +664,8 @@ class Scss(object): m_params = mixin[0] m_defaults = mixin[1] m_codestr = mixin[2] + pristine_callee_namespace = mixin[3] + import_key = mixin[5] params = [] params_dict = {} @@ -695,6 +699,7 @@ class Scss(object): # consider itself as existing where it was defined, not # called? source_file=rule.source_file, + import_key=rule.import_key, # TODO unparsed_contents=m_codestr, @@ -708,6 +713,7 @@ class Scss(object): namespace=m_vars, ) + pristine_callee_namespace.use_import(import_key) self.manage_children(_rule, scope) ret = _rule.retval if ret is None: @@ -769,6 +775,7 @@ class Scss(object): m_codestr = mixin[2] pristine_callee_namespace = mixin[3] callee_argspec = mixin[4] + import_key = mixin[5] if caller_argspec.inject and callee_argspec.inject: # DEVIATION: Pass the ENTIRE local namespace to the mixin (yikes) @@ -824,6 +831,7 @@ class Scss(object): _rule.lineno = block.lineno _rule.options['@content'] = block.unparsed_contents + pristine_callee_namespace.use_import(import_key) self.manage_children(_rule, scope) @print_timing(10) @@ -851,9 +859,6 @@ class Scss(object): names = block.argument.split(',') for name in names: name = dequote(name.strip()) - if rule.namespace.has_import(name, rule.source_file.parent_dir): - # If already imported in this scope, skip - continue source_file = None full_filename, seen_paths = self._find_import(rule, name) @@ -873,7 +878,7 @@ class Scss(object): source_file = SourceFile( full_filename, source, - parent_dir=os.path.dirname(full_filename), + parent_dir=os.path.realpath(os.path.dirname(full_filename)), ) self.source_files.append(source_file) @@ -884,8 +889,14 @@ class Scss(object): log.warn("File to import not found or unreadable: '%s' (%s)%s", name, rule.file_and_line, load_paths_msg) continue + import_key = (name, source_file.parent_dir) + if rule.namespace.has_import(import_key): + # If already imported in this scope, skip + continue + _rule = SassRule( source_file=source_file, + import_key=import_key, lineno=block.lineno, unparsed_contents=source_file.contents, @@ -896,7 +907,7 @@ class Scss(object): ancestry=rule.ancestry, namespace=rule.namespace, ) - rule.namespace.add_import(name, rule.source_file.parent_dir) + rule.namespace.add_import(import_key, rule.import_key, rule.file_and_line) self.manage_children(_rule, scope) def _find_import(self, rule, name): @@ -1248,6 +1259,7 @@ class Scss(object): from scss.rule import RuleAncestry new_rule = SassRule( source_file=rule.source_file, + import_key=rule.import_key, lineno=block.lineno, unparsed_contents=block.unparsed_contents, @@ -1260,7 +1272,9 @@ class Scss(object): nested=rule.nested + 1, ) self.rules.append(new_rule) + rule.namespace.use_import(rule.import_key) self.manage_children(new_rule, scope) + new_rule.namespace.warn_unused_imports() @print_timing(10) def _nest_rules(self, rule, scope, block): @@ -1277,6 +1291,7 @@ class Scss(object): new_rule = SassRule( source_file=rule.source_file, + import_key=rule.import_key, lineno=block.lineno, unparsed_contents=block.unparsed_contents, @@ -1289,7 +1304,9 @@ class Scss(object): nested=rule.nested + 1, ) self.rules.append(new_rule) + rule.namespace.use_import(rule.import_key) self.manage_children(new_rule, scope) + new_rule.namespace.warn_unused_imports() @print_timing(3) def apply_extends(self): diff --git a/scss/rule.py b/scss/rule.py index 6d3b856..dc1dd08 100644 --- a/scss/rule.py +++ b/scss/rule.py @@ -104,8 +104,7 @@ class MixinScope(Scope): class ImportScope(Scope): - def __repr__(self): - return "<%s(%s) at 0x%x>" % (type(self).__name__, ', '.join('[%s]' % ', '.join(repr(k) for k in sorted(map.keys())) for map in self.maps), id(self)) + pass class Namespace(object): @@ -170,14 +169,27 @@ class Namespace(object): raise TypeError("Expected a Sass type, while setting %s got %r" % (name, value,)) self._variables.set(name, value, force_local=local_only) - def has_import(self, name, path=None): - import_key = (name, path) + def has_import(self, import_key): return import_key in self._imports - def add_import(self, name, path=None): + def add_import(self, import_key, parent_import_key, file_and_line): self._assert_mutable() - import_key = (name, path) - self._imports[import_key] = True + if import_key: + imports = [0, parent_import_key, file_and_line] + self._imports[import_key] = imports + + def use_import(self, import_key): + self._assert_mutable() + if import_key and import_key in self._imports: + imports = self._imports[import_key] + imports[0] += 1 + self.use_import(imports[1]) + + def warn_unused_imports(self): + for import_key in self._imports.keys(): + imports = self._imports[import_key] + if not imports[0]: + log.warn("Unused @import: '%s' (%s)", import_key[0], imports[2]) def _get_callable(self, chainmap, name, arity): name = normalize_var(name) @@ -216,7 +228,7 @@ class SassRule(object): metadata, like `@extend` rules and `@media` nesting. """ - def __init__(self, source_file, unparsed_contents=None, + def __init__(self, source_file, import_key=None, unparsed_contents=None, options=None, properties=None, namespace=None, lineno=0, extends_selectors=frozenset(), @@ -224,6 +236,7 @@ class SassRule(object): nested=-1): self.source_file = source_file + self.import_key = import_key self.lineno = lineno self.unparsed_contents = unparsed_contents diff --git a/scss/tests/files/kronuz/imports-unused.css b/scss/tests/files/kronuz/imports-unused.css new file mode 100644 index 0000000..fd7e4e6 --- /dev/null +++ b/scss/tests/files/kronuz/imports-unused.css @@ -0,0 +1,6 @@ +#test { + width: 490px; +} +div { + width: 990px; +} diff --git a/scss/tests/files/kronuz/imports-unused.scss b/scss/tests/files/kronuz/imports-unused.scss new file mode 100644 index 0000000..127a655 --- /dev/null +++ b/scss/tests/files/kronuz/imports-unused.scss @@ -0,0 +1,14 @@ +@option compress:no; + +@import "functions-context"; + +#test { + @import "functions-context"; + @import "imports-unused"; + @import "menu"; + width: grid-width(10); +} + +div { + width: grid-width(20); +} |