Skip to content

Commit 72ccccb

Browse files
committed
Improve detection of call signature and kwargs.
Correctly identify calls of the form "foo[123](bar=2)" to highlight the contents of the parentheses as call arguments. Issue: #197
1 parent dd48b8f commit 72ccccb

File tree

5 files changed

+194
-0
lines changed

5 files changed

+194
-0
lines changed

grammars/MagicPython.cson

+26
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,9 @@ repository:
343343
{
344344
include: "#list"
345345
}
346+
{
347+
include: "#odd-function-call"
348+
}
346349
{
347350
include: "#round-braces"
348351
}
@@ -513,6 +516,28 @@ repository:
513516
include: "#expression"
514517
}
515518
]
519+
"odd-function-call":
520+
comment: '''
521+
A bit obscured function call where there may have been an
522+
arbitrary number of other operations to get the function.
523+
E.g. "arr[idx](args)"
524+
525+
'''
526+
begin: '''
527+
(?x)
528+
(?<= \\] | \\) ) \\s*
529+
(?=\\()
530+
531+
'''
532+
end: "(\\))"
533+
endCaptures:
534+
"1":
535+
name: "punctuation.definition.arguments.end.python"
536+
patterns: [
537+
{
538+
include: "#function-arguments"
539+
}
540+
]
516541
"round-braces":
517542
begin: "\\("
518543
end: "\\)"
@@ -1627,6 +1652,7 @@ repository:
16271652
]
16281653
"function-call":
16291654
name: "meta.function-call.python"
1655+
comment: "Regular function call of the type \"name(args)\""
16301656
begin: '''
16311657
(?x)
16321658
\\b(?=

grammars/MagicPython.tmLanguage

+36
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,10 @@ it's probably control flow like:
521521
<key>include</key>
522522
<string>#list</string>
523523
</dict>
524+
<dict>
525+
<key>include</key>
526+
<string>#odd-function-call</string>
527+
</dict>
524528
<dict>
525529
<key>include</key>
526530
<string>#round-braces</string>
@@ -779,6 +783,36 @@ it's probably control flow like:
779783
</dict>
780784
</array>
781785
</dict>
786+
<key>odd-function-call</key>
787+
<dict>
788+
<key>comment</key>
789+
<string>A bit obscured function call where there may have been an
790+
arbitrary number of other operations to get the function.
791+
E.g. "arr[idx](args)"
792+
</string>
793+
<key>begin</key>
794+
<string>(?x)
795+
(?&lt;= \] | \) ) \s*
796+
(?=\()
797+
</string>
798+
<key>end</key>
799+
<string>(\))</string>
800+
<key>endCaptures</key>
801+
<dict>
802+
<key>1</key>
803+
<dict>
804+
<key>name</key>
805+
<string>punctuation.definition.arguments.end.python</string>
806+
</dict>
807+
</dict>
808+
<key>patterns</key>
809+
<array>
810+
<dict>
811+
<key>include</key>
812+
<string>#function-arguments</string>
813+
</dict>
814+
</array>
815+
</dict>
782816
<key>round-braces</key>
783817
<dict>
784818
<key>begin</key>
@@ -2554,6 +2588,8 @@ it's probably control flow like:
25542588
<dict>
25552589
<key>name</key>
25562590
<string>meta.function-call.python</string>
2591+
<key>comment</key>
2592+
<string>Regular function call of the type "name(args)"</string>
25572593
<key>begin</key>
25582594
<string>(?x)
25592595
\b(?=

grammars/src/MagicPython.syntax.yaml

+17
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,7 @@ repository:
404404
- include: '#curly-braces'
405405
- include: '#item-access'
406406
- include: '#list'
407+
- include: '#odd-function-call'
407408
- include: '#round-braces'
408409
- include: '#function-call'
409410
- include: '#builtin-functions'
@@ -505,6 +506,21 @@ repository:
505506
patterns:
506507
- include: '#expression'
507508

509+
odd-function-call:
510+
comment: |
511+
A bit obscured function call where there may have been an
512+
arbitrary number of other operations to get the function.
513+
E.g. "arr[idx](args)"
514+
begin: |
515+
(?x)
516+
(?<= \] | \) ) \s*
517+
(?=\()
518+
end: (\))
519+
endCaptures:
520+
'1': {name: punctuation.definition.arguments.end.python}
521+
patterns:
522+
- include: '#function-arguments'
523+
508524
round-braces:
509525
begin: \(
510526
end: \)
@@ -1230,6 +1246,7 @@ repository:
12301246

12311247
function-call:
12321248
name: meta.function-call.python
1249+
comment: Regular function call of the type "name(args)"
12331250
begin: |
12341251
(?x)
12351252
\b(?=

test/atom-spec/python-spec.js

+71
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,77 @@ describe("Grammar Tests", function() {
651651
expect(tokens[3][3].scopes).toEqual(["source.python","meta.function-call.python","punctuation.definition.arguments.end.python"]);
652652
});
653653

654+
it("test/calls/call11.py",
655+
function() {
656+
tokens = grammar.tokenizeLines("id = Field[uuid.UUID] (\n uuid.UUID,\n inheritable=False,\n simpledelta=False,\n allow_ddl_set=True,\n)")
657+
expect(tokens[0][0].value).toBe("id");
658+
expect(tokens[0][0].scopes).toEqual(["source.python","support.function.builtin.python"]);
659+
expect(tokens[0][1].value).toBe(" ");
660+
expect(tokens[0][1].scopes).toEqual(["source.python"]);
661+
expect(tokens[0][2].value).toBe("=");
662+
expect(tokens[0][2].scopes).toEqual(["source.python","keyword.operator.assignment.python"]);
663+
expect(tokens[0][3].value).toBe(" ");
664+
expect(tokens[0][3].scopes).toEqual(["source.python"]);
665+
expect(tokens[0][4].value).toBe("Field");
666+
expect(tokens[0][4].scopes).toEqual(["source.python","meta.item-access.python","meta.indexed-name.python"]);
667+
expect(tokens[0][5].value).toBe("[");
668+
expect(tokens[0][5].scopes).toEqual(["source.python","meta.item-access.python","punctuation.definition.arguments.begin.python"]);
669+
expect(tokens[0][6].value).toBe("uuid");
670+
expect(tokens[0][6].scopes).toEqual(["source.python","meta.item-access.python","meta.item-access.arguments.python"]);
671+
expect(tokens[0][7].value).toBe(".");
672+
expect(tokens[0][7].scopes).toEqual(["source.python","meta.item-access.python","meta.item-access.arguments.python","meta.member.access.python","punctuation.separator.period.python"]);
673+
expect(tokens[0][8].value).toBe("UUID");
674+
expect(tokens[0][8].scopes).toEqual(["source.python","meta.item-access.python","meta.item-access.arguments.python","meta.member.access.python","constant.other.caps.python"]);
675+
expect(tokens[0][9].value).toBe("]");
676+
expect(tokens[0][9].scopes).toEqual(["source.python","meta.item-access.python","punctuation.definition.arguments.end.python"]);
677+
expect(tokens[0][10].value).toBe(" ");
678+
expect(tokens[0][10].scopes).toEqual(["source.python"]);
679+
expect(tokens[0][11].value).toBe("(");
680+
expect(tokens[0][11].scopes).toEqual(["source.python","punctuation.definition.arguments.begin.python"]);
681+
expect(tokens[1][0].value).toBe(" ");
682+
expect(tokens[1][0].scopes).toEqual(["source.python","meta.function-call.arguments.python"]);
683+
expect(tokens[1][1].value).toBe("uuid");
684+
expect(tokens[1][1].scopes).toEqual(["source.python","meta.function-call.arguments.python"]);
685+
expect(tokens[1][2].value).toBe(".");
686+
expect(tokens[1][2].scopes).toEqual(["source.python","meta.function-call.arguments.python","meta.member.access.python","punctuation.separator.period.python"]);
687+
expect(tokens[1][3].value).toBe("UUID");
688+
expect(tokens[1][3].scopes).toEqual(["source.python","meta.function-call.arguments.python","meta.member.access.python","constant.other.caps.python"]);
689+
expect(tokens[1][4].value).toBe(",");
690+
expect(tokens[1][4].scopes).toEqual(["source.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
691+
expect(tokens[2][0].value).toBe(" ");
692+
expect(tokens[2][0].scopes).toEqual(["source.python","meta.function-call.arguments.python"]);
693+
expect(tokens[2][1].value).toBe("inheritable");
694+
expect(tokens[2][1].scopes).toEqual(["source.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
695+
expect(tokens[2][2].value).toBe("=");
696+
expect(tokens[2][2].scopes).toEqual(["source.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
697+
expect(tokens[2][3].value).toBe("False");
698+
expect(tokens[2][3].scopes).toEqual(["source.python","meta.function-call.arguments.python","constant.language.python"]);
699+
expect(tokens[2][4].value).toBe(",");
700+
expect(tokens[2][4].scopes).toEqual(["source.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
701+
expect(tokens[3][0].value).toBe(" ");
702+
expect(tokens[3][0].scopes).toEqual(["source.python","meta.function-call.arguments.python"]);
703+
expect(tokens[3][1].value).toBe("simpledelta");
704+
expect(tokens[3][1].scopes).toEqual(["source.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
705+
expect(tokens[3][2].value).toBe("=");
706+
expect(tokens[3][2].scopes).toEqual(["source.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
707+
expect(tokens[3][3].value).toBe("False");
708+
expect(tokens[3][3].scopes).toEqual(["source.python","meta.function-call.arguments.python","constant.language.python"]);
709+
expect(tokens[3][4].value).toBe(",");
710+
expect(tokens[3][4].scopes).toEqual(["source.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
711+
expect(tokens[4][0].value).toBe(" ");
712+
expect(tokens[4][0].scopes).toEqual(["source.python","meta.function-call.arguments.python"]);
713+
expect(tokens[4][1].value).toBe("allow_ddl_set");
714+
expect(tokens[4][1].scopes).toEqual(["source.python","meta.function-call.arguments.python","variable.parameter.function-call.python"]);
715+
expect(tokens[4][2].value).toBe("=");
716+
expect(tokens[4][2].scopes).toEqual(["source.python","meta.function-call.arguments.python","keyword.operator.assignment.python"]);
717+
expect(tokens[4][3].value).toBe("True");
718+
expect(tokens[4][3].scopes).toEqual(["source.python","meta.function-call.arguments.python","constant.language.python"]);
719+
expect(tokens[4][4].value).toBe(",");
720+
expect(tokens[4][4].scopes).toEqual(["source.python","meta.function-call.arguments.python","punctuation.separator.arguments.python"]);
721+
expect(tokens[5][0].value).toBe(")");
722+
expect(tokens[5][0].scopes).toEqual(["source.python","punctuation.definition.arguments.end.python"]);
723+
});
724+
654725
it("test/calls/call2.py",
655726
function() {
656727
tokens = grammar.tokenizeLines("foo(from=1)")

test/calls/call11.py

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
id = Field[uuid.UUID] (
2+
uuid.UUID,
3+
inheritable=False,
4+
simpledelta=False,
5+
allow_ddl_set=True,
6+
)
7+
8+
9+
10+
11+
12+
id : source.python, support.function.builtin.python
13+
: source.python
14+
= : keyword.operator.assignment.python, source.python
15+
: source.python
16+
Field : meta.indexed-name.python, meta.item-access.python, source.python
17+
[ : meta.item-access.python, punctuation.definition.arguments.begin.python, source.python
18+
uuid : meta.item-access.arguments.python, meta.item-access.python, source.python
19+
. : meta.item-access.arguments.python, meta.item-access.python, meta.member.access.python, punctuation.separator.period.python, source.python
20+
UUID : constant.other.caps.python, meta.item-access.arguments.python, meta.item-access.python, meta.member.access.python, source.python
21+
] : meta.item-access.python, punctuation.definition.arguments.end.python, source.python
22+
: source.python
23+
( : punctuation.definition.arguments.begin.python, source.python
24+
: meta.function-call.arguments.python, source.python
25+
uuid : meta.function-call.arguments.python, source.python
26+
. : meta.function-call.arguments.python, meta.member.access.python, punctuation.separator.period.python, source.python
27+
UUID : constant.other.caps.python, meta.function-call.arguments.python, meta.member.access.python, source.python
28+
, : meta.function-call.arguments.python, punctuation.separator.arguments.python, source.python
29+
: meta.function-call.arguments.python, source.python
30+
inheritable : meta.function-call.arguments.python, source.python, variable.parameter.function-call.python
31+
= : keyword.operator.assignment.python, meta.function-call.arguments.python, source.python
32+
False : constant.language.python, meta.function-call.arguments.python, source.python
33+
, : meta.function-call.arguments.python, punctuation.separator.arguments.python, source.python
34+
: meta.function-call.arguments.python, source.python
35+
simpledelta : meta.function-call.arguments.python, source.python, variable.parameter.function-call.python
36+
= : keyword.operator.assignment.python, meta.function-call.arguments.python, source.python
37+
False : constant.language.python, meta.function-call.arguments.python, source.python
38+
, : meta.function-call.arguments.python, punctuation.separator.arguments.python, source.python
39+
: meta.function-call.arguments.python, source.python
40+
allow_ddl_set : meta.function-call.arguments.python, source.python, variable.parameter.function-call.python
41+
= : keyword.operator.assignment.python, meta.function-call.arguments.python, source.python
42+
True : constant.language.python, meta.function-call.arguments.python, source.python
43+
, : meta.function-call.arguments.python, punctuation.separator.arguments.python, source.python
44+
) : punctuation.definition.arguments.end.python, source.python

0 commit comments

Comments
 (0)