Skip to content

Commit

Permalink
JSUtils modification to handle es6 constructs (adobe#13635)
Browse files Browse the repository at this point in the history
* JSUtils modification to handle es6 constructs

* Addressed review comments and added es6 test cases

* Address Code review comments and add support for ArrowFunctionExpressions with new test case

* Update comments

* Refactor to remove extra variables
  • Loading branch information
swmitra authored and ficristo committed Nov 26, 2017
1 parent 9f3abb6 commit e95aea7
Showing 11 changed files with 700 additions and 51 deletions.
8 changes: 8 additions & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
@@ -138,6 +138,14 @@ module.exports = function (grunt) {
src: [
'less/dist/less.min.js'
]
},
{
expand: true,
dest: 'src/thirdparty/acorn',
cwd: 'src/node_modules/acorn',
src: [
'dist/{,*/}*'
]
}
]
}
4 changes: 1 addition & 3 deletions src/extensions/default/QuickOpenJavaScript/main.js
Original file line number Diff line number Diff line change
@@ -65,9 +65,7 @@ define(function (require, exports, module) {
var lines = docText.split("\n");
var functions = JSUtils.findAllMatchingFunctionsInText(docText, "*");
functions.forEach(function (funcEntry) {
var chFrom = lines[funcEntry.lineStart].indexOf(funcEntry.name);
var chTo = chFrom + funcEntry.name.length;
functionList.push(new FileLocation(null, funcEntry.lineStart, chFrom, chTo, funcEntry.name));
functionList.push(new FileLocation(null, funcEntry.nameLineStart, funcEntry.columnStart, funcEntry.columnEnd, funcEntry.label || funcEntry.name));
});
return functionList;
}
130 changes: 108 additions & 22 deletions src/language/JSUtils.js
Original file line number Diff line number Diff line change
@@ -21,15 +21,16 @@
*
*/

/*jslint regexp: true */

/**
* Set of utilities for simple parsing of JS text.
*/
define(function (require, exports, module) {
"use strict";

var _ = require("thirdparty/lodash");
var _ = require("thirdparty/lodash"),
Acorn = require("thirdparty/acorn/dist/acorn"),
AcornLoose = require("thirdparty/acorn/dist/acorn_loose"),
ASTWalker = require("thirdparty/acorn/dist/walk");

// Load brackets modules
var CodeMirror = require("thirdparty/CodeMirror/lib/codemirror"),
@@ -47,17 +48,6 @@ define(function (require, exports, module) {
*/
var _changedDocumentTracker = new ChangedDocumentTracker();

/**
* Function matching regular expression. Recognizes the forms:
* "function functionName()", "functionName = function()", and
* "functionName: function()".
*
* Note: JavaScript identifier matching is not strictly to spec. This
* RegExp matches any sequence of characters that is not whitespace.
* @type {RegExp}
*/
var _functionRegExp = /(function\s+([$_A-Za-z\u007F-\uFFFF][$_A-Za-z0-9\u007F-\uFFFF]*)\s*(\([^)]*\)))|(([$_A-Za-z\u007F-\uFFFF][$_A-Za-z0-9\u007F-\uFFFF]*)\s*[:=]\s*function\s*(\([^)]*\)))/g;

/**
* @private
* Return an object mapping function name to offset info for all functions in the specified text.
@@ -66,21 +56,112 @@ define(function (require, exports, module) {
* @return {Object.<string, Array.<{offsetStart: number, offsetEnd: number}>}
*/
function _findAllFunctionsInText(text) {
var results = {},
var AST,
results = {},
functionName,
resultNode,
memberPrefix,
match;

PerfUtils.markStart(PerfUtils.JSUTILS_REGEXP);

while ((match = _functionRegExp.exec(text)) !== null) {
functionName = (match[2] || match[5]).trim();


try {
AST = Acorn.parse(text, {locations: true});
} catch (e) {
AST = AcornLoose.parse_dammit(text, {locations: true});
}

function _addResult(node, offset, prefix) {
memberPrefix = prefix ? prefix + " - " : "";
resultNode = node.id || node.key || node;
functionName = resultNode.name;
if (!Array.isArray(results[functionName])) {
results[functionName] = [];
}

results[functionName].push({offsetStart: match.index});
results[functionName].push(
{
offsetStart: offset || node.start,
label: memberPrefix ? memberPrefix + functionName : null,
location: resultNode.loc
}
);
}

ASTWalker.simple(AST, {
/*
function <functionName> () {}
*/
FunctionDeclaration: function (node) {
// As acorn_loose marks identifier names with '✖' under erroneous declarations
// we should have a check to discard such 'FunctionDeclaration' nodes
if (node.id.name !== '✖') {
_addResult(node);
}
},
/*
class <className> () {}
*/
ClassDeclaration: function (node) {
_addResult(node);
ASTWalker.simple(node, {
/*
class <className> () {
<methodName> () {
}
}
*/
MethodDefinition: function (methodNode) {
_addResult(methodNode, methodNode.key.start, node.id.name);
}
});
},
/*
var <functionName> = function () {}
or
var <functionName> = () => {}
*/
VariableDeclarator: function (node) {
if (node.init && (node.init.type === "FunctionExpression" || node.init.type === "ArrowFunctionExpression")) {
_addResult(node);
}
},
/*
SomeFunction.prototype.<functionName> = function () {}
*/
AssignmentExpression: function (node) {
if (node.right && node.right.type === "FunctionExpression") {
if (node.left && node.left.type === "MemberExpression" && node.left.property) {
_addResult(node.left.property);
}
}
},
/*
{
<functionName>: function() {}
}
*/
Property: function (node) {
if (node.value && node.value.type === "FunctionExpression") {
if (node.key && node.key.type === "Identifier") {
_addResult(node.key);
}
}
},
/*
<functionName>: function() {}
*/
LabeledStatement: function (node) {
if (node.body && node.body.type === "FunctionDeclaration") {
if (node.label) {
_addResult(node.label);
}
}
}
});

PerfUtils.addMeasurement(PerfUtils.JSUTILS_REGEXP);

@@ -415,8 +496,13 @@ define(function (require, exports, module) {
var endOffset = _getFunctionEndOffset(text, funcEntry.offsetStart);
result.push({
name: functionName,
label: funcEntry.label,
lineStart: StringUtils.offsetToLineNum(lines, funcEntry.offsetStart),
lineEnd: StringUtils.offsetToLineNum(lines, endOffset)
lineEnd: StringUtils.offsetToLineNum(lines, endOffset),
nameLineStart: funcEntry.location.start.line - 1,
nameLineEnd: funcEntry.location.end.line - 1,
columnStart: funcEntry.location.start.column,
columnEnd: funcEntry.location.end.column
});
});
}
Loading

0 comments on commit e95aea7

Please sign in to comment.