git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [GSoC][PATCH v3] Add a diff driver for JavaScript languages.

From
Johannes Sixt <j6t@kdbg.org>
Date
Apr 3, 2022, 14:40 UTC
Message-ID
<595d535d-3d3e-9994-0b80-4521a753c74c@kdbg.org>
In-Reply-To
<20220403132508.28196-1-a97410985new@gmail.com>
Am 03.04.22 um 15:25 schrieb xing zhi jiang:
Show 34 quoted lines
> In the xfunction part that matches normal functions,
> a variable declaration with an assignment of function, the function declaration
> in the class, named export for function in ECMA2015, CommonJS exports for
> named function, and also the function is object literal's property[1].
> The special match is this would match the popular framework test case
> pattern(most is same as regex for matching function in class).
> 
> And in the word regex part, that matches numbers, punctuations, and also the
> JavaScript identifier.
> This part reference the formal ECMA specification[2].
> 
> [1]https://github.com/jquery/jquery/blob/de5398a6ad088dc006b46c6a870a2a053f4cd663/src/core.js#L201
> [2]https://262.ecma-international.org/12.0/#sec-ecmascript-language-lexical-grammar
> 
> Signed-off-by: xing zhi jiang <a97410985new@gmail.com>
> ---
> I write a simple python script to help me observe the diff's results easier. 
> And the result is in https://github.com/a97410985/user_diff_observe_tool.
> I observe the six popular JavaScript projects - Jquery, NodeJS, React, TensorflowJS, 
> Vue, and Webpack. The result is not perfect but acceptable.
> Most of the mismatch is related to the function in class. Ex:
> https://github.com/a97410985/user_diff_observe_tool/blob/092bd14c849b9a3f61bb872d730e38b58cc9c303/diff_result/jquery_result.diff#L1094.
> But this is inevitable.
> And besides, apply the code reviews suggestions. I add some new regex.
> 1. "!^[\t ]*[$_[:alpha:]][$_[:alnum:]][\t ]*\\(.*\\)\\.\n"
>    this is for the case below
>    `
>     function RIGHT(a, b) {
> 
>         WRONG(spy.calls.count()).toBe(1)
>         return a + b; // ChangeMe
>     }
>    `
>    if we don't skip chained function call. This would happen mismatch.
OK, but see below.
Show 9 quoted lines
> 2. "^[\t ]*(QUnit.test\\(.*)\n"
>    I oberve there are many test case pattern in JavaScript. And most of popular JavaScript
>    unit test framework's test case pattern is function call can be matched by the regex, which
>    match "function in class". So it is no problem. But `QUnit framework` don't matched by that.
>    Then add this regex into JavaScript userdiff.
>    And the reason includes test case pattern has two
>    1. This is inevitable. Because we can't distinguish that with function in class.
>    2. This can help the user understand what change is happening in which test case. And if 
>       don't match the test case, it has the large possibility to match no related function.

Good. I consider this like matching a language keyword. If additional patterns of this kind occur, they can be added later, but we must make sure that this does not proliferate.

Show 7 quoted lines
>       
> And I move the regex, which match normal function in object literal, under the regex 
> ""!^(\t{2,}|[ ]{5,})\n".
> Because I found it would many mismatch if function in object literal has too many indent level(
> the function body usually just few lines of code, and the below has large of code. If has change
> on below, it would happen mismatch).
> And there are two example for hunk header that match test case pattern.
OK.
Show 11 quoted lines
> diff --git a/t/t4018/javascript-skip-chained-function b/t/t4018/javascript-skip-chained-function
> new file mode 100644
> index 0000000000..4ce23901cf
> --- /dev/null
> +++ b/t/t4018/javascript-skip-chained-function
> @@ -0,0 +1,5 @@
> +function RIGHT(a, b) {
> +
> +  expect(spy.calls.count()).toBe(1)
> +  return a + b; // ChangeMe
> +}

This is the test case that attempts to make sure that the chained function calls are not matched. But since there is no line between ChangeMe and the not-to-be-matched line, this test case would not detect such an incorrect match. You have to insert a line between expect... and return...ChangeMe

Show 33 quoted lines
> diff --git a/userdiff.c b/userdiff.c
> index 8578cb0d12..306286df35 100644
> --- a/userdiff.c
> +++ b/userdiff.c
> @@ -168,6 +168,43 @@ PATTERNS("java",
>  	 "|[-+0-9.e]+[fFlL]?|0[xXbB]?[0-9a-fA-F]+[lL]?"
>  	 "|[-+*/<>%&^|=!]="
>  	 "|--|\\+\\+|<<=?|>>>?=?|&&|\\|\\|"),
> +
> +PATTERNS("javascript",
> +	 /* don't match the expression may contain parenthesis, because it is not a function declaration */
> +	 "!^[ \t]*(if|do|while|for|with|switch|catch|import|return)\n"
> +	 /* don't match statement */
> +	 "!;\n"
> +	 /* match normal function or named export for function in ECMA2015 */
> +	 "^((export[\t ]+)?(async[\t ]+)?function[\t ]*[\t *]*[$_[:alpha:]][$_[:alnum:]]*[\t ]*\\(.*)\n"
> +	 /* match JavaScript variable declaration with a lambda expression at top level */
> +	 "^((const|let|var)[\t ]*[$_[:alpha:]][$_[:alnum:]]*[\t ]*=[\t ]*"
> +		"(\\(.*\\)|[$_[:alpha:]][$_[:alnum:]]*)[\t ]*=>[\t ]*\\{?)\n"
> +	 /* match object's property assignment by anonymous function and CommonJS exports for named function */
> +	 "^((module\\.)?[$_[:alpha:]][$_[:alnum:]]*\\.[$_[:alpha:]][$_[:alnum:]]*[\t ]*=[\t ]*(async[\t ]+)?(\\(.*\\)|[$_[:alpha:]][$_[:alnum:]]*)[\t ]*=>.*)\n"
> +	 /* match assign function to LHS with explicit function keyword */
> +	 "^(.*=[\t ]*function[\t ]*([$_[:alnum:]]+[\t ]*)?\\(.*)\n"
> +	 /* popular unit testing framework test case pattern. Most of framework pattern is match by regex for "function in class" */
> +	 "^[\t ]*(QUnit.test\\(.*)\n"
> +	 /* don't match the function in class or in object literal, which has more than one ident level */
> +	 "!^(\t{2,}|[ ]{5,})\n"
> +	 /* match normal function in object literal */
> +	 "^[\t ]*([$_[:alpha:]][$_[:alnum:]]*[\t ]*:[\t ]*function.*)\n"
> +	 /* don't match chained method call */
> +	 "!^[\t ]*[$_[:alpha:]][$_[:alnum:]][\t ]*\\(.*\\)\\.\n"
> +	 /* match function in class and ES5 method shorthand */
> +	 "^[\t ]*((static[\t ]+)?((async|get|set)[\t ]+)?[$_[:alpha:]][$_[:alnum:]]*[\t ]*\\(.*)",
No objections to these expressions.
Show 12 quoted lines
> +	 /* word regex */
> +	 /* hexIntegerLiteral, octalIntegerLiteral, binaryIntegerLiteral, and its big version */
> +	 "0[xXoObB][_0-9a-fA-F]+n?"
> +	 /* DecimalLiteral and its big version*/
> +	 "|[0-9][_0-9]*(\\.[0-9][_0-9]*|n)?([eE][+-]?[_0-9]+)?"
> +	 "|\\.[0-9][_0-9]*([eE][+-]?[_0-9]+)?"
> +	 /* punctuations */
> +	 "|\\.{3}|<=|>=|==|!=|={3}|!==|\\*{2}|\\+{2}|--|<<|>>"
> +	 "|>>>|&&|\\|{2}|\\?{2}|\\+=|-=|\\*=|%=|\\*{2}="
> +	 "|<<=|>>=|>>>=|&=|\\|=|\\^=|&&=|\\|{2}=|\\?{2}=|=>"
> +	 /* identifiers */
> +	 "|[$_[:alpha:]][$_[:alnum:]]*"),
These word-regexs look good.
>  PATTERNS("markdown",
>  	 "^ {0,3}#{1,6}[ \t].*",
>  	 /* -- */

This round looks quite good. With the one issue I noted above fixed, this should be good to go, IMO.

-- Hannes
Previous: xing zhi jiangNext: Ævar Arnfjörð Bjarmason
Message 20 of 25 in “userdiff: add buildin diff driver for JavaScript language”
  1. xing zhi jiangMar 4, 2022
  2. [GSoC][PATCH 1/1] Add a diff driver for JavaScript languages.xing zhi jiang, Mar 4, 2022
  3. Johannes SixtMar 5, 2022
  4. xing-zhi jiangMar 7, 2022
  5. Johannes SixtMar 8, 2022
  6. xing zhi jiangMar 12, 2022
  7. Johannes SixtMar 5, 2022
  8. [GSoC][PATCH v2] Add a diff driver for JavaScript languages.xing zhi jiang, Mar 12, 2022
  9. Johannes SixtMar 13, 2022
  10. xing zhi jiangApr 3, 2022
  11. Glen ChooMar 14, 2022
  12. Johannes SixtMar 15, 2022
  13. Glen ChooMar 15, 2022
  14. Junio C HamanoMar 15, 2022
  15. Glen ChooMar 15, 2022
  16. xing zhi jiangApr 3, 2022
  17. xing zhi jiangApr 3, 2022
  18. xing zhi jiangApr 3, 2022
  19. [GSoC][PATCH v3] Add a diff driver for JavaScript languages.xing zhi jiang, Apr 3, 2022
  20. Johannes SixtApr 3, 2022
  21. Ævar Arnfjörð BjarmasonApr 4, 2022
  22. Johannes SixtApr 4, 2022
  23. Junio C HamanoApr 4, 2022
  24. Ævar Arnfjörð BjarmasonApr 5, 2022
  25. Glen ChooApr 4, 2022

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.