jsParse: Use JSDoc to document functions
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2842>
This commit is contained in:
parent
561d0d3758
commit
a66ffcfc74
@ -1,12 +1,18 @@
|
|||||||
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
||||||
/* exported getCompletions, getCommonPrefix, getDeclaredConstants */
|
/* exported getCompletions, getCommonPrefix, getDeclaredConstants */
|
||||||
|
|
||||||
// Returns a list of potential completions for text. Completions either
|
/**
|
||||||
// follow a dot (e.g. foo.ba -> bar) or they are picked from globalCompletionList (e.g. fo -> foo)
|
* Returns a list of potential completions for text. Completions either
|
||||||
// commandHeader is prefixed on any expression before it is eval'ed. It will most likely
|
* follow a dot (e.g. foo.ba -> bar) or they are picked from globalCompletionList (e.g. fo -> foo)
|
||||||
// consist of global constants that might not carry over from the calling environment.
|
* commandHeader is prefixed on any expression before it is eval'ed. It will most likely
|
||||||
//
|
* consist of global constants that might not carry over from the calling environment.
|
||||||
// This function is likely the one you want to call from external modules
|
*
|
||||||
|
* This function is likely the one you want to call from external modules
|
||||||
|
*
|
||||||
|
* @param {string} text
|
||||||
|
* @param {string} commandHeader
|
||||||
|
* @param {readonly string[]} [globalCompletionList]
|
||||||
|
*/
|
||||||
function getCompletions(text, commandHeader, globalCompletionList) {
|
function getCompletions(text, commandHeader, globalCompletionList) {
|
||||||
let methods = [];
|
let methods = [];
|
||||||
let expr_, base;
|
let expr_, base;
|
||||||
@ -41,18 +47,27 @@ function getCompletions(text, commandHeader, globalCompletionList) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
/**
|
||||||
// A few functions for parsing strings of javascript code.
|
* A few functions for parsing strings of javascript code.
|
||||||
//
|
*/
|
||||||
|
|
||||||
// Identify characters that delimit an expression. That is,
|
/**
|
||||||
// if we encounter anything that isn't a letter, '.', ')', or ']',
|
* Identify characters that delimit an expression. That is,
|
||||||
// we should stop parsing.
|
* if we encounter anything that isn't a letter, '.', ')', or ']',
|
||||||
|
* we should stop parsing.
|
||||||
|
*
|
||||||
|
* @param {string} c
|
||||||
|
*/
|
||||||
function isStopChar(c) {
|
function isStopChar(c) {
|
||||||
return !c.match(/[\w.)\]]/);
|
return !c.match(/[\w.)\]]/);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Given the ending position of a quoted string, find where it starts
|
/**
|
||||||
|
* Given the ending position of a quoted string, find where it starts
|
||||||
|
*
|
||||||
|
* @param {string} expr
|
||||||
|
* @param {number} offset
|
||||||
|
*/
|
||||||
function findMatchingQuote(expr, offset) {
|
function findMatchingQuote(expr, offset) {
|
||||||
let quoteChar = expr.charAt(offset);
|
let quoteChar = expr.charAt(offset);
|
||||||
for (let i = offset - 1; i >= 0; --i) {
|
for (let i = offset - 1; i >= 0; --i) {
|
||||||
@ -62,7 +77,12 @@ function findMatchingQuote(expr, offset) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Given the ending position of a regex, find where it starts
|
/**
|
||||||
|
* Given the ending position of a regex, find where it starts
|
||||||
|
*
|
||||||
|
* @param {string} expr
|
||||||
|
* @param {number} offset
|
||||||
|
*/
|
||||||
function findMatchingSlash(expr, offset) {
|
function findMatchingSlash(expr, offset) {
|
||||||
for (let i = offset - 1; i >= 0; --i) {
|
for (let i = offset - 1; i >= 0; --i) {
|
||||||
if (expr.charAt(i) == '/' && expr.charAt(i - 1) != '\\')
|
if (expr.charAt(i) == '/' && expr.charAt(i - 1) != '\\')
|
||||||
@ -71,10 +91,15 @@ function findMatchingSlash(expr, offset) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If expr.charAt(offset) is ')' or ']',
|
/**
|
||||||
// return the position of the corresponding '(' or '[' bracket.
|
* If expr.charAt(offset) is ')' or ']',
|
||||||
// This function does not check for syntactic correctness. e.g.,
|
* return the position of the corresponding '(' or '[' bracket.
|
||||||
// findMatchingBrace("[(])", 3) returns 1.
|
* This function does not check for syntactic correctness. e.g.,
|
||||||
|
* findMatchingBrace("[(])", 3) returns 1.
|
||||||
|
*
|
||||||
|
* @param {string} expr
|
||||||
|
* @param {number} offset
|
||||||
|
*/
|
||||||
function findMatchingBrace(expr, offset) {
|
function findMatchingBrace(expr, offset) {
|
||||||
let closeBrace = expr.charAt(offset);
|
let closeBrace = expr.charAt(offset);
|
||||||
let openBrace = { ')': '(', ']': '[' }[closeBrace];
|
let openBrace = { ')': '(', ']': '[' }[closeBrace];
|
||||||
@ -82,6 +107,12 @@ function findMatchingBrace(expr, offset) {
|
|||||||
return findTheBrace(expr, offset - 1, openBrace, closeBrace);
|
return findTheBrace(expr, offset - 1, openBrace, closeBrace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {*} expr
|
||||||
|
* @param {*} offset
|
||||||
|
* @param {...any} braces
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
function findTheBrace(expr, offset, ...braces) {
|
function findTheBrace(expr, offset, ...braces) {
|
||||||
let [openBrace, closeBrace] = braces;
|
let [openBrace, closeBrace] = braces;
|
||||||
|
|
||||||
@ -103,11 +134,16 @@ function findTheBrace(expr, offset, ...braces) {
|
|||||||
return findTheBrace(expr, offset - 1, ...braces);
|
return findTheBrace(expr, offset - 1, ...braces);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Walk expr backwards from offset looking for the beginning of an
|
/**
|
||||||
// expression suitable for passing to eval.
|
* Walk expr backwards from offset looking for the beginning of an
|
||||||
// There is no guarantee of correct javascript syntax between the return
|
* expression suitable for passing to eval.
|
||||||
// value and offset. This function is meant to take a string like
|
* There is no guarantee of correct javascript syntax between the return
|
||||||
// "foo(Obj.We.Are.Completing" and allow you to extract "Obj.We.Are.Completing"
|
* value and offset. This function is meant to take a string like
|
||||||
|
* "foo(Obj.We.Are.Completing" and allow you to extract "Obj.We.Are.Completing"
|
||||||
|
*
|
||||||
|
* @param {string} expr
|
||||||
|
* @param {number} offset
|
||||||
|
*/
|
||||||
function getExpressionOffset(expr, offset) {
|
function getExpressionOffset(expr, offset) {
|
||||||
while (offset >= 0) {
|
while (offset >= 0) {
|
||||||
let currChar = expr.charAt(offset);
|
let currChar = expr.charAt(offset);
|
||||||
@ -124,14 +160,22 @@ function getExpressionOffset(expr, offset) {
|
|||||||
return offset + 1;
|
return offset + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Things with non-word characters or that start with a number
|
/**
|
||||||
// are not accessible via .foo notation and so aren't returned
|
* Things with non-word characters or that start with a number
|
||||||
|
* are not accessible via .foo notation and so aren't returned
|
||||||
|
*
|
||||||
|
* @param {string} w
|
||||||
|
*/
|
||||||
function isValidPropertyName(w) {
|
function isValidPropertyName(w) {
|
||||||
return !(w.match(/\W/) || w.match(/^\d/));
|
return !(w.match(/\W/) || w.match(/^\d/));
|
||||||
}
|
}
|
||||||
|
|
||||||
// To get all properties (enumerable and not), we need to walk
|
/**
|
||||||
// the prototype chain ourselves
|
* To get all properties (enumerable and not), we need to walk
|
||||||
|
* the prototype chain ourselves
|
||||||
|
*
|
||||||
|
* @param {object} obj
|
||||||
|
*/
|
||||||
function getAllProps(obj) {
|
function getAllProps(obj) {
|
||||||
if (obj === null || obj === undefined)
|
if (obj === null || obj === undefined)
|
||||||
return [];
|
return [];
|
||||||
@ -139,11 +183,16 @@ function getAllProps(obj) {
|
|||||||
return Object.getOwnPropertyNames(obj).concat(getAllProps(Object.getPrototypeOf(obj)));
|
return Object.getOwnPropertyNames(obj).concat(getAllProps(Object.getPrototypeOf(obj)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Given a string _expr_, returns all methods
|
/**
|
||||||
// that can be accessed via '.' notation.
|
* Given a string _expr_, returns all methods
|
||||||
// e.g., expr="({ foo: null, bar: null, 4: null })" will
|
* that can be accessed via '.' notation.
|
||||||
// return ["foo", "bar", ...] but the list will not include "4",
|
* e.g., expr="({ foo: null, bar: null, 4: null })" will
|
||||||
// since methods accessed with '.' notation must star with a letter or _.
|
* return ["foo", "bar", ...] but the list will not include "4",
|
||||||
|
* since methods accessed with '.' notation must star with a letter or _.
|
||||||
|
*
|
||||||
|
* @param {string} expr
|
||||||
|
* @param {string=} commandHeader
|
||||||
|
*/
|
||||||
function getPropertyNamesFromExpression(expr, commandHeader = '') {
|
function getPropertyNamesFromExpression(expr, commandHeader = '') {
|
||||||
let obj = {};
|
let obj = {};
|
||||||
if (!isUnsafeExpression(expr)) {
|
if (!isUnsafeExpression(expr)) {
|
||||||
@ -169,7 +218,11 @@ function getPropertyNamesFromExpression(expr, commandHeader = '') {
|
|||||||
return Object.keys(propsUnique).sort();
|
return Object.keys(propsUnique).sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Given a list of words, returns the longest prefix they all have in common
|
/**
|
||||||
|
* Given a list of words, returns the longest prefix they all have in common
|
||||||
|
*
|
||||||
|
* @param {readonly string[]} words
|
||||||
|
*/
|
||||||
function getCommonPrefix(words) {
|
function getCommonPrefix(words) {
|
||||||
let word = words[0];
|
let word = words[0];
|
||||||
for (let i = 0; i < word.length; i++) {
|
for (let i = 0; i < word.length; i++) {
|
||||||
@ -181,7 +234,11 @@ function getCommonPrefix(words) {
|
|||||||
return word;
|
return word;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove any blocks that are quoted or are in a regex
|
/**
|
||||||
|
* Remove any blocks that are quoted or are in a regex
|
||||||
|
*
|
||||||
|
* @param {string} str
|
||||||
|
*/
|
||||||
function removeLiterals(str) {
|
function removeLiterals(str) {
|
||||||
if (str.length == 0)
|
if (str.length == 0)
|
||||||
return '';
|
return '';
|
||||||
@ -198,8 +255,12 @@ function removeLiterals(str) {
|
|||||||
return removeLiterals(str.slice(0, str.length - 1)) + currChar;
|
return removeLiterals(str.slice(0, str.length - 1)) + currChar;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if there is reason to think that eval(str)
|
/**
|
||||||
// will modify the global scope
|
* Returns true if there is reason to think that eval(str)
|
||||||
|
* will modify the global scope
|
||||||
|
*
|
||||||
|
* @param {string} str
|
||||||
|
*/
|
||||||
function isUnsafeExpression(str) {
|
function isUnsafeExpression(str) {
|
||||||
// Check for any sort of assignment
|
// Check for any sort of assignment
|
||||||
// The strategy used is dumb: remove any quotes
|
// The strategy used is dumb: remove any quotes
|
||||||
@ -220,7 +281,11 @@ function isUnsafeExpression(str) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a list of global keywords derived from str
|
/**
|
||||||
|
* Returns a list of global keywords derived from str
|
||||||
|
*
|
||||||
|
* @param {string} str
|
||||||
|
*/
|
||||||
function getDeclaredConstants(str) {
|
function getDeclaredConstants(str) {
|
||||||
let ret = [];
|
let ret = [];
|
||||||
str.split(';').forEach(s => {
|
str.split(';').forEach(s => {
|
||||||
|
Loading…
Reference in New Issue
Block a user