Index: tools/cc-frame-viewer/build/parse_deps.py |
diff --git a/tools/cc-frame-viewer/build/parse_deps.py b/tools/cc-frame-viewer/build/parse_deps.py |
deleted file mode 100644 |
index 7cd5c387bc633dcbcfbfce278161ed9cd5c74ccc..0000000000000000000000000000000000000000 |
--- a/tools/cc-frame-viewer/build/parse_deps.py |
+++ /dev/null |
@@ -1,372 +0,0 @@ |
-# Copyright (c) 2012 The Chromium Authors. All rights reserved. |
-# Use of this source code is governed by a BSD-style license that can be |
-# found in the LICENSE file. |
-import sys |
-import os |
-import re |
- |
-class DepsException(Exception): |
- pass |
- |
-""" |
-The core of this script is the calc_load_sequence function. In total, this |
-walks over the provided javascript files and figures out their dependencies |
-using the module definitions provided in each file. This allows us to, for |
-example, have a trio of modules: |
- |
-foo.js: |
- base.require('bar'); |
-and bar.js: |
- base.require('baz'); |
- |
-calc_load_sequence(['foo'], '.') will yield: |
- [Module('baz'), Module('bar'), Module('foo')] |
- |
-which is, based on the dependencies, the correct sequence in which to load |
-those modules. |
-""" |
- |
-class ResourceFinder(object): |
- """Helper code for finding a module given a name and current module. |
- |
- The dependency resolution code in Module.resolve will find bits of code in the |
- actual javascript that says things require('bar'). This |
- code is responsible for figuring out what filename corresponds to 'bar' given |
- a Module('foo'). |
- """ |
- def __init__(self, root_dir): |
- self._root_dir = root_dir |
- pass |
- |
- @property |
- def root_dir(self): |
- return self._root_dir |
- |
- def _find_and_load_filename(self, absolute_path): |
- if not os.path.exists(absolute_path): |
- return None, None |
- |
- f = open(absolute_path, 'r') |
- contents = f.read() |
- f.close() |
- |
- return absolute_path, contents |
- |
- def _find_and_load(self, current_module, requested_name, extension): |
- assert current_module.filename |
- pathy_name = requested_name.replace(".", os.sep) |
- filename = pathy_name + extension |
- absolute_path = os.path.join(self._root_dir, filename) |
- return self._find_and_load_filename(absolute_path) |
- |
- def find_and_load_module(self, current_module, requested_module_name): |
- return self._find_and_load(current_module, requested_module_name, ".js") |
- |
- def find_and_load_raw_script(self, current_module, filename): |
- absolute_path = os.path.join(self._root_dir, filename) |
- return self._find_and_load_filename(absolute_path) |
- |
- def find_and_load_style_sheet(self, |
- current_module, requested_style_sheet_name): |
- return self._find_and_load( |
- current_module, requested_style_sheet_name, ".css") |
- |
- |
-class StyleSheet(object): |
- """Represents a stylesheet resource referenced by a module via the |
- base.requireStylesheet(xxx) directive.""" |
- def __init__(self, name, filename, contents): |
- self.name = name |
- self.filename = filename |
- self.contents = contents |
- |
- def __repr__(self): |
- return "StyleSheet(%s)" % self.name |
- |
-class RawScript(object): |
- """Represents a raw script resource referenced by a module via the |
- base.requireRawScript(xxx) directive.""" |
- def __init__(self, name, filename, contents): |
- self.name = name |
- self.filename = filename |
- self.contents = contents |
- |
- def __repr__(self): |
- return "RawScript(%s)" % self.name |
- |
-def _tokenize_js(text): |
- rest = text |
- tokens = ["//", "/*", "*/", "\n"] |
- while len(rest): |
- indices = [rest.find(token) for token in tokens] |
- found_indices = [index for index in indices if index >= 0] |
- |
- if len(found_indices) == 0: |
- # end of string |
- yield rest |
- return |
- |
- min_index = min(found_indices) |
- token_with_min = tokens[indices.index(min_index)] |
- |
- if min_index > 0: |
- yield rest[:min_index] |
- |
- yield rest[min_index:min_index + len(token_with_min)] |
- rest = rest[min_index + len(token_with_min):] |
- |
-def _strip_js_comments(text): |
- result_tokens = [] |
- token_stream = _tokenize_js(text).__iter__() |
- while True: |
- try: |
- t = token_stream.next() |
- except StopIteration: |
- break |
- |
- if t == "//": |
- while True: |
- try: |
- t2 = token_stream.next() |
- if t2 == "\n": |
- break |
- except StopIteration: |
- break |
- elif t == '/*': |
- nesting = 1 |
- while True: |
- try: |
- t2 = token_stream.next() |
- if t2 == "/*": |
- nesting += 1 |
- elif t2 == "*/": |
- nesting -= 1 |
- if nesting == 0: |
- break |
- except StopIteration: |
- break |
- else: |
- result_tokens.append(t) |
- return "".join(result_tokens) |
- |
-def _MangleRawScriptFilenameToModuleName(filename): |
- name = filename |
- name = name.replace(os.sep, ':') |
- name = name.replace('..', '!!') |
- return name |
- |
-class Module(object): |
- """Represents a javascript module. It can either be directly requested, e.g. |
- passed in by name to calc_load_sequence, or created by being referenced a |
- module via the base.require(xxx) directive. |
- |
- Interesting properties on this object are: |
- |
- - filename: the file of the actual module |
- - contents: the actual text contents of the module |
- - style_sheets: StyleSheet objects that this module relies on for styling |
- information. |
- - dependent_modules: other modules that this module needs in order to run |
- """ |
- def __init__(self, name = None): |
- self.name = name |
- self.filename = None |
- self.contents = None |
- |
- self.dependent_module_names = [] |
- self.dependent_modules = [] |
- self.dependent_raw_script_names = [] |
- self.dependent_raw_scripts = [] |
- self.style_sheet_names = [] |
- self.style_sheets = [] |
- |
- def __repr__(self): |
- return "Module(%s)" % self.name |
- |
- def load_and_parse(self, module_filename, |
- module_contents = None, |
- decl_required = True): |
- if not module_contents: |
- f = open(module_filename, 'r') |
- self.contents = f.read() |
- f.close() |
- else: |
- self.contents = module_contents |
- self.filename = module_filename |
- self.parse_definition_(self.contents, decl_required) |
- |
- def resolve(self, all_resources, resource_finder): |
- if "scripts" not in all_resources: |
- all_resources["scripts"] = {} |
- if "style_sheets" not in all_resources: |
- all_resources["style_sheets"] = {} |
- if "raw_scripts" not in all_resources: |
- all_resources["raw_scripts"] = {} |
- |
- assert self.filename |
- |
- for name in self.dependent_module_names: |
- if name in all_resources["scripts"]: |
- assert all_resources["scripts"][name].contents |
- self.dependent_modules.append(all_resources["scripts"][name]) |
- continue |
- |
- filename, contents = resource_finder.find_and_load_module(self, name) |
- if not filename: |
- raise DepsException("Could not find a file for module %s" % name) |
- |
- module = Module(name) |
- all_resources["scripts"][name] = module |
- self.dependent_modules.append(module) |
- module.load_and_parse(filename, contents) |
- module.resolve(all_resources, resource_finder) |
- |
- for name in self.dependent_raw_script_names: |
- filename, contents = resource_finder.find_and_load_raw_script(self, name) |
- if not filename: |
- raise DepsException("Could not find a file for module %s" % name) |
- |
- if name in all_resources["raw_scripts"]: |
- assert all_resources["raw_scripts"][name].contents |
- self.dependent_raw_scripts.append(all_resources["raw_scripts"][name]) |
- continue |
- |
- raw_script = RawScript(name, filename, contents) |
- all_resources["raw_scripts"][name] = raw_script |
- self.dependent_raw_scripts.append(raw_script) |
- |
- for name in self.style_sheet_names: |
- if name in all_resources["style_sheets"]: |
- assert all_resources["style_sheets"][name].contents |
- self.style_sheets.append(all_resources["scripts"][name]) |
- continue |
- |
- filename, contents = resource_finder.find_and_load_style_sheet(self, name) |
- if not filename: |
- raise DepsException("Could not find a file for stylesheet %s" % name) |
- |
- style_sheet = StyleSheet(name, filename, contents) |
- all_resources["style_sheets"][name] = style_sheet |
- self.style_sheets.append(style_sheet) |
- |
- def compute_load_sequence_recursive(self, load_sequence, already_loaded_set): |
- for dependent_module in self.dependent_modules: |
- dependent_module.compute_load_sequence_recursive(load_sequence, |
- already_loaded_set) |
- if self.name not in already_loaded_set: |
- already_loaded_set.add(self.name) |
- load_sequence.append(self) |
- |
- def parse_definition_(self, text, decl_required = True): |
- if not decl_required and not self.name: |
- raise Exception("Module.name must be set for decl_required to be false.") |
- |
- stripped_text = _strip_js_comments(text) |
- rest = stripped_text |
- while True: |
- # Things to search for. |
- m_r = re.search("""base\s*\.\s*require\((["'])(.+?)\\1\)""", |
- rest, re.DOTALL) |
- m_s = re.search("""base\s*\.\s*requireStylesheet\((["'])(.+?)\\1\)""", |
- rest, re.DOTALL) |
- m_irs = re.search("""base\s*\.\s*requireRawScript\((["'])(.+?)\\1\)""", |
- rest, re.DOTALL) |
- matches = [m for m in [m_r, m_s, m_irs] if m] |
- |
- # Figure out which was first. |
- matches.sort(key=lambda x: x.start()) |
- if len(matches): |
- m = matches[0] |
- else: |
- break |
- |
- if m == m_r: |
- dependent_module_name = m.group(2) |
- if '/' in dependent_module_name: |
- raise DepsException("Slashes are not allowed in module names. " |
- "Use '.' instead: %s" % dependent_module_name) |
- if dependent_module_name.endswith('js'): |
- raise DepsException("module names shouldn't end with .js" |
- "The module system will append that for you: %s" % |
- dependent_module_name) |
- self.dependent_module_names.append(dependent_module_name) |
- elif m == m_s: |
- style_sheet_name = m.group(2) |
- if '/' in style_sheet_name: |
- raise DepsException("Slashes are not allowed in style sheet names. " |
- "Use '.' instead: %s" % style_sheet_name) |
- if style_sheet_name.endswith('.css'): |
- raise DepsException("Style sheets should not end in .css. " |
- "The module system will append that for you" % |
- style_sheet_name) |
- self.style_sheet_names.append(style_sheet_name) |
- elif m == m_irs: |
- name = m.group(2) |
- self.dependent_raw_script_names.append(name) |
- |
- rest = rest[m.end():] |
- |
- |
-def calc_load_sequence(filenames, toplevel_dir): |
- """Given a list of starting javascript files, figure out all the Module |
- objects that need to be loaded to satisfiy their dependencies. |
- |
- The javascript files shoud specify their dependencies in a format that is |
- textually equivalent to base.js' require syntax, namely: |
- |
- base.require(module1); |
- base.require(module2); |
- base.requireStylesheet(stylesheet); |
- |
- The output of this function is an array of Module objects ordered by |
- dependency. |
- """ |
- all_resources = {} |
- all_resources["scripts"] = {} |
- toplevel_modules = [] |
- root_dir = '' |
- if filenames: |
- root_dir = os.path.abspath(os.path.dirname(filenames[0])) |
- resource_finder = ResourceFinder(root_dir) |
- for filename in filenames: |
- if not os.path.exists(filename): |
- raise Exception("Could not find %s" % filename) |
- |
- rel_filename = os.path.relpath(filename, toplevel_dir) |
- dirname = os.path.dirname(rel_filename) |
- modname = os.path.splitext(os.path.basename(rel_filename))[0] |
- if len(dirname): |
- name = dirname.replace('/', '.') + '.' + modname |
- else: |
- name = modname |
- |
- if name in all_resources["scripts"]: |
- continue |
- |
- module = Module(name) |
- module.load_and_parse(filename, decl_required = False) |
- all_resources["scripts"][module.name] = module |
- module.resolve(all_resources, resource_finder) |
- |
- # Find the root modules: ones who have no dependencies. |
- module_ref_counts = {} |
- for module in all_resources["scripts"].values(): |
- module_ref_counts[module.name] = 0 |
- |
- def inc_ref_count(name): |
- module_ref_counts[name] = module_ref_counts[name] + 1 |
- for module in all_resources["scripts"].values(): |
- for dependent_module in module.dependent_modules: |
- inc_ref_count(dependent_module.name) |
- |
- root_modules = [all_resources["scripts"][name] |
- for name, ref_count in module_ref_counts.items() |
- if ref_count == 0] |
- |
- root_modules.sort(lambda x, y: cmp(x.name, y.name)) |
- |
- already_loaded_set = set() |
- load_sequence = [] |
- for module in root_modules: |
- module.compute_load_sequence_recursive(load_sequence, already_loaded_set) |
- return load_sequence |