如何识别下面的代码模式

我有一个js承诺的模式,我想确定几个关键字

例如,如果我把这样的代码:

var deferred = Q.defer(); 

而在文件中,我也有以下各自的价值

 deferred.reject(err); deferred.resolve(); return deferred.promise; 

完整的代码

例1

 function writeError(errMessage) { var deferred = Q.defer(); fs.writeFile("errors.log", errMessage, function (err) { if (err) { deferred.reject(err); } else { deferred.resolve(); } }); return deferred.promise; } 

我想如果我把大的代码文件(作为string) ,发现这个文件包含模式

另一个例子

var d = Q.defer(); / *或$ q.defer * /

而在文件中,你也有以下各自的价值

 d.resolve(val); d.reject(err); return d.promise; 

完成示例2

 function getStuffDone(param) { var d = Q.defer(); /* or $q.defer */ Promise(function(resolve, reject) { // or = new $.Deferred() etc. myPromiseFn(param+1) .then(function(val) { /* or .done */ d.resolve(val); }).catch(function(err) { /* .fail */ d.reject(err); }); return d.promise; /* or promise() */ } 

有开放的来源,可以用来做这样的分析(提供一个模式,它会发现…)

有一些更复杂的patter与childProcess,但现在这是OK 🙂

更新 :我做了一个更正的代码,即改变set[2] set[set.length - 1]适应任何大小的查询集。 然后,我对两个例子应用了完全相同的algorithm。

我提供的解决scheme遵循一些规则,我认为您提出的searchtypes是合理的。 假设你正在寻找四行,ABCD(不区分大小写,所以它会findABCD或abcd或aBcD):

  • 多个匹配集可以在一个文件中find,即它将在ABCDabcd中find两个集合。
  • 正则expression式用于个别行,这意味着可以包括变化。 (这只是一个结果,如果你在你的代码的匹配行末尾有一个注释,那也没有关系。)
  • 所寻找的模式必须始终位于不同的行上,例如A和B不能在同一行上。
  • 匹配的集合必须是完整的,例如它不会findABC或ABD。
  • 匹配的集合必须是不间断的,即它不会在ABCaD中find任何东西。 (重要的是,这也意味着在重叠集合中找不到任何东西,比如ABCaDbcd,你可能会认为这太局限了,但是在这个例子中,应该找哪个ABCD或者abcd?答案是随心所欲的,任意性而且,根据你所展示的例子,这样的重叠通常是不可预期的,所以这种边缘情况似乎不大可能,因此这个限制是合理的)。
  • 匹配的集合必须在内部不重复,例如它不会findABbCD。 然而,用AaBCD,它find一个集合,即它会find一个BCD。
  • embedded式设置是允许的,但只有内部设置会被find,例如ABabcdCD,只有abcd将被find。

下面的代码片段显示了一个示例search。 它不显示所有的边缘情况。 但是,它确实显示了整体function。

 var queryRegexStrs = [ "I( really)? (like|adore) strawberry", "I( really)? (like|adore) chocolate", "I( really)? (like|adore) vanilla" ]; var codeStr = "....\n" + "Most people would say 'I like vanilla'\n" + "....\n" + "....\n" + "....\n" + "....\n" + "Amir's taste profile:\n" + "....\n" + "I like strawberry\n" + "....\n" + "....\n" + "I told Billy that I really adore chocolate a lot\n" + "....\n" + "I like vanilla most of the time\n" + "....\n" + "Let me emphasize that I like strawberry\n" + "....\n" + "....\n" + "....\n" + "....\n" + "Juanita's taste profile:\n" + "....\n" + "I really adore strawberry\n" + "I like vanilla\n" + "....\n" + "....\n" + "....\n" + "....\n" + "Rachel's taste profile:\n" + "I adore strawberry\n" + "....\n" + "Sometimes I like chocolate, I guess\n" + "....\n" + "I adore vanilla\n" + "....\n" + "....\n" + "....\n" + "....\n" + ""; // allow for different types of end-of-line characters or character sequences var endOfLineStr = "\n"; var matchSets = search(queryRegexStrs, codeStr, endOfLineStr); function search(queryRegexStrs, codeStr, endOfLineStr) { // break the large code string into an array of line strings var codeLines = codeStr.split(endOfLineStr); // remember the number of lines being sought var numQueryLines = queryRegexStrs.length; // convert the input regex strings into actual regex's in a parallel array var queryRegexs = queryRegexStrs.map(function(queryRegexStr) { return new RegExp(queryRegexStr); }); // search the array for each query line // to find complete, uninterrupted, non-repeating sets of matches // make an array to hold potentially multiple match sets from the same file var matchSets = []; // prepare to try finding the next match set var currMatchSet; // keep track of which query line number is currently being sought var idxOfCurrQuery = 0; // whenever looking for a match set is (re-)initialized, // start looking again for the first query, // and forget any previous individual query matches that have been found var resetCurrQuery = function() { idxOfCurrQuery = 0; currMatchSet = []; }; // check each line of code... codeLines.forEach(function(codeLine, codeLineNum, codeLines) { // ...against each query line queryRegexs.forEach(function(regex, regexNum, regexs) { // check if this line of code is a match with this query line var matchFound = regex.test(codeLine); // if so, remember which query line it matched if (matchFound) { // if this code line matches the first query line, // then reset the current query and continue if (regexNum === 0) { resetCurrQuery(); } // if this most recent individual match is the one expected next, proceed if (regexNum === idxOfCurrQuery) { // temporarily remember the line number of this most recent individual match currMatchSet.push(codeLineNum); // prepare to find the next query in the sequence idxOfCurrQuery += 1; // if a whole query set has just been found, then permanently remember // the corresponding code line numbers, and reset the search if (idxOfCurrQuery === numQueryLines) { matchSets.push(currMatchSet); resetCurrQuery(); } // if this most recent match is NOT the one expected next in the sequence, // then start over in terms of starting to look again for the first query } else { resetCurrQuery(); } } }); }); return matchSets; } // report the results document.write("<b>The code lines being sought:</b>"); document.write("<pre>" + JSON.stringify(queryRegexStrs, null, 2) + "</pre>"); document.write("<b>The code being searched:</b>"); document.write( "<pre><ol start='0'><li>" + codeStr.replace(new RegExp("\n", "g"), "</li><li>") + "</li></ol></pre>" ); document.write("<b>The code line numbers of query 'hits', grouped by query set:</b>"); document.write("<pre>" + JSON.stringify(matchSets) + "</pre>"); document.write("<b>One possible formatted output:</b>"); var str = "<p>(Note that line numbers are 0-based...easily changed to 1-based if desired)</p>"; str += "<pre>"; matchSets.forEach(function(set, setNum, arr) { str += "Matching code block #" + (setNum + 1) + ": lines " + set[0] + "-" + set[set.length - 1] + "<br />"; }); str += "</pre>"; document.write(str); 

下面的正则expression式可能看起来有点吓人,但已经从简单的概念构build,并允许比您提到的更多的余地 – 例如额外的空白,不同的variables名称,省略var等似乎适用于这两个例子 – 请看看它是否满足您的需求。

 ([^\s\r\n]+)\s*=\s*(?:Q|\$q)\.defer\s*\(\s*\)\s*;(?:\r?\n|.)*(?:\s|\r?\n)(?:\1\.reject\(\w+\)\s*;(?:\r?\n|.)*(?:\s|\r?\n)\1\.resolve\(\s*\w*\)\s*;|\1\.resolve\(\s*\w*\)\s*;(?:\r?\n|.)*(?:\s|\r?\n)\1\.reject\(\w+\)\s*;)(?:\r?\n|.)*(?:\s|\r?\n)return\s+(?:\1\.)?promise\s*; 

正则表达式可视化

Debuggex演示