]> code.delx.au - gnu-emacs-elpa/blobdiff - scopifier.js
Add tty faces.
[gnu-emacs-elpa] / scopifier.js
index a94790eaa0d78dfe1439e7edda01114e95d519db..814550106e9087caec60fed2797d7e86fef00051 100644 (file)
@@ -1,47 +1,32 @@
 'use strict';
 
-var escope = require('escope'),
-    esprima = require('esprima'),
+var escope = require('./lib/escope'),
+    esprima = require('./lib/esprima'),
 
-    // Given an array of definitions, determines if a definition already exists
-    // for a given range. (escope detects variables twice if they are declared
-    // and initialized simultaneously; this filters them.)
-    isDefined = function (definitions, range) {
-        var i, definition;
-        for (i = 0; i < definitions.length; i += 1) {
-            definition = definitions[i];
-            if (definition[1] === range[0] && definition[2] === range[1]) {
-                return true;
-            }
-        }
-        return false;
-    };
+    normal = 0,
+    bold = 1,
+    italic = 2;
 
-// Given code, returns an array of `[level, start, end]' tokens for
+// Given code, returns an array of `[start, end, level, style]' tokens for
 // context-coloring.
 module.exports = function (code) {
-    var ast,
-
-        analyzedScopes,
+    var analyzedScopes,
+        ast,
+        comment,
+        definition,
+        definitionsCount,
+        definitionsIndex,
         i,
-        scope,
-        range,
-
+        isDefined,
         j,
         k,
-        variable,
-        mappedDefinitions,
-        definition,
+        pointer,
+        range,
         reference,
-
-        definitions,
-        references,
-
-        scopes = [],
-        symbols = [],
-
-        comments,
-        comment;
+        scope,
+        scopes,
+        tokens,
+        variable;
 
     // Gracefully handle parse errors by doing nothing.
     try {
@@ -54,6 +39,9 @@ module.exports = function (code) {
         process.exit(1);
     }
 
+    scopes = [];
+    tokens = [];
+
     for (i = 0; i < analyzedScopes.length; i += 1) {
         scope = analyzedScopes[i];
         // Having its level set implies it was already annotated.
@@ -74,55 +62,68 @@ module.exports = function (code) {
             // done now.
             if (!scope.functionExpressionScope) {
                 range = scope.block.range;
-                scopes.push([
-                    scope.level,
+                scopes.push(
                     range[0] + 1,
-                    range[1] + 1
-                ]);
-                definitions = [];
+                    range[1] + 1,
+                    scope.level,
+                    normal
+                );
+                definitionsIndex = tokens.length;
+                definitionsCount = 0;
                 for (j = 0; j < scope.variables.length; j += 1) {
                     variable = scope.variables[j];
-                    mappedDefinitions = [];
+                    definitionsCount += variable.defs.length;
                     for (k = 0; k < variable.defs.length; k += 1) {
                         definition = variable.defs[k];
                         range = definition.name.range;
-                        mappedDefinitions.push([
-                            scope.level,
+                        tokens.push(
                             range[0] + 1,
-                            range[1] + 1
-                        ]);
+                            range[1] + 1,
+                            scope.level,
+                            bold
+                        );
                     }
-                    Array.prototype.push.apply(definitions, mappedDefinitions);
                 }
-                references = [];
                 for (j = 0; j < scope.references.length; j += 1) {
                     reference = scope.references[j];
                     range = reference.identifier.range;
-                    if (!isDefined(definitions, range)) {
-                        references.push([
+                    isDefined = false;
+                    // Determine if a definition already exists for the
+                    // range. (escope detects variables twice if they are
+                    // declared and initialized simultaneously; this filters
+                    // them.)
+                    for (k = 0; k < definitionsCount; k += 1) {
+                        pointer = definitionsIndex + (k * 4);
+                        if (tokens[pointer] === range[0] + 1 &&
+                                tokens[pointer + 1] === range[1] + 1) {
+                            isDefined = true;
+                            break;
+                        }
+                    }
+                    if (!isDefined) {
+                        tokens.push(
                             // Handle global references too.
-                            reference.resolved ? reference.resolved.scope.level : 0,
                             range[0] + 1,
-                            range[1] + 1
-                        ]);
+                            range[1] + 1,
+                            reference.resolved ? reference.resolved.scope.level : 0,
+                            reference.__maybeImplicitGlobal ? bold : normal
+                        );
                     }
                 }
-                Array.prototype.push.apply(symbols, definitions);
-                Array.prototype.push.apply(symbols, references);
             }
         }
     }
 
-    comments = [];
     for (i = 0; i < ast.comments.length; i += 1) {
         comment = ast.comments[i];
         range = comment.range;
-        comments.push([
-            -1,
+        tokens.push(
             range[0] + 1,
-            range[1] + 1
-        ]);
+            range[1] + 1,
+            -1,
+            italic
+        );
     }
 
-    return scopes.concat(symbols).concat(comments);
+    return scopes.concat(tokens);
 };