Skip to content

Commit

Permalink
[Python] Introduce qualified-name-until-leaf ctx
Browse files Browse the repository at this point in the history
... and use it to match function calls less explicitly and more
magically. Usually you would think this is bad, but it's not because
it's not really less explicit. It just avoids repetition when scoping
the last (non-special) part of a qualified name with a name other than
"meta.generic-name".

This change triggers the bug described in
sublimehq/sublime_text#1190, where the
most-inner context in a multi-push operation *must* match at least one
character before it can be popped.

Due this, the tests are currently *not* passing.
  • Loading branch information
FichteFoll committed Dec 19, 2016
1 parent 63706ac commit 2483930
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 46 deletions.
87 changes: 53 additions & 34 deletions Python/Python.sublime-syntax
Original file line number Diff line number Diff line change
Expand Up @@ -548,41 +548,27 @@ contexts:
- include: expressions

function-calls:
- match: '(?=\.?{{path}}\s*\()'
- match: '(?=(\.\s*)?{{path}}\s*\()'
push: [function-call-wrapper, qualified-name-until-leaf]

function-call-wrapper:
- meta_scope: meta.function-call.python
- match: '{{identifier}}'
scope: meta.qualified-name.python variable.function.python
- match: \)
scope: punctuation.section.arguments.end.python
set: after-expression
- match: \(
scope: punctuation.section.arguments.begin.python
push:
- meta_scope: meta.function-call.python
- match: \)
scope: punctuation.section.arguments.end.python
set: after-expression
- match: '(?=\.?{{path}}\s*\()'
push:
- match: (?=\s*\()
pop: true
- match: ' *(\.) *(?={{identifier}})'
captures:
1: punctuation.accessor.dot.python
set:
- include: dotted-name-specials
- match: '{{identifier}}(?=\s*\()'
scope: variable.function.python
- include: generic-names
- match: '(?={{identifier}})'
push:
- include: name-specials
- match: '{{identifier}}(?=\s*\()'
scope: variable.function.python
- include: generic-names
- match: \(
scope: punctuation.section.arguments.begin.python
push:
- meta_content_scope: meta.function-call.arguments.python
- match: (?=\))
pop: true
- include: keyword-arguments
- match: ','
scope: punctuation.separator.arguments.python
- include: inline-for
- include: expressions
- meta_content_scope: meta.function-call.arguments.python
- match: (?=\))
pop: true
- include: keyword-arguments
- match: ','
scope: punctuation.separator.arguments.python
- include: inline-for
- include: expressions

lambda:
- match: \b(lambda)(?=\s|:|$)
Expand Down Expand Up @@ -704,6 +690,39 @@ contexts:
- match: ''
pop: true

qualified-name-until-leaf:
# Push this together with another context to match a qualified name
# until the last non-special identifier (if any).
# This allows the leaf to be scoped individually.
- meta_scope: meta.qualified-name.python
- include: name-specials
# If a line continuation follows, this may or may not be the last leaf (most likley not though)
- match: '{{identifier}}(?=\s*\\)'
scope: meta.generic-name.python
- match: (?={{identifier}}\s*\.)
push:
- include: name-specials
- include: generic-names
- match: ''
pop: true
- match: (\.)\s*(?={{identifier}}\s*\.)
captures:
1: punctuation.accessor.dot.python
push:
- include: dotted-name-specials
- include: generic-names
- match: ''
pop: true
- match: (\.)\s*(?={{identifier}})
captures:
1: punctuation.accessor.dot.python
set:
- include: dotted-name-specials
- match: ''
pop: true
- match: (?=\S|$)
pop: true

name-specials:
- include: builtin-functions
- include: builtin-types
Expand Down
63 changes: 51 additions & 12 deletions Python/syntax_test_python.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,54 @@
# ^^^^^^^^^ - support


##################
# Function Calls
##################

identifier()
#^^^^^^^^^^^ meta.function-call
#^^^^^^^^^ meta.qualified-name variable.function
# ^ punctuation.section.arguments.begin
# ^ punctuation.section.arguments.end

dotted.identifier(12, True)
#^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.function-call
# ^^^^^^^^ meta.function-call.arguments
#^^^^^^^^^^^^^^^^ meta.qualified-name
#^^^^^^ - variable.function
# ^ punctuation.accessor.dot
# ^^^^^^^^^^ variable.function

open.__new__(12, True)
#^^^^^^^^^^^^^^^^^^^^^ meta.function-call
#^^^ support.function.builtin
# ^ punctuation.accessor.dot
# ^^^^^^^ support.function.magic

TypeError()
#^^^^^^^^ support.type.exception
#
module.TypeError()
#^^^^^^^^^^^^^^^ meta.function-call
# ^^^^^^^^^ - support
# ^^^^^^^^^ variable.function

open.open.open()
#^^^ support.function.builtin
# ^ punctuation.accessor.dot
# ^^^^^^^^^ - support
# ^^^^ variable.function
#

if p.type not in ('NUMBER', 'INTEGER'):
# ^^ keyword.operator - meta.function-call invalid

call(from='no')
#^^^^^^^^^^^^^^ meta.function-call
# ^^^^ invalid.illegal.name
# ^ keyword.operator.assignment
# ^^^^ string

##################
# Expressions
##################
Expand Down Expand Up @@ -138,11 +186,6 @@ def _():
# ^^ invalid.illegal.name
# ^^ invalid.illegal.name

call(from='no')
# ^^^^^^^^^^^^^^^ meta.function-call
# ^^^^ invalid.illegal.name
# ^ keyword.operator.assignment
# ^^^^ string
lambda
# ^^^^^^ storage.type.function.inline

Expand All @@ -157,14 +200,10 @@ def _():
# ^^^^^^ variable.function
# ^ punctuation.accessor.dot

'foo'.upper()
# ^^^^^^^^ meta.function-call
'foo'. upper()
# ^^^^^^^^^ meta.function-call
# ^ punctuation.accessor.dot
# ^^^^^ variable.function

func()
#^^^^^ meta.function-call
#^^^ variable.function
# ^^^^^ variable.function

func()(1, 2)
# <- meta.function-call
Expand Down

0 comments on commit 2483930

Please sign in to comment.