From 350e338316404b3254e3102eda111fac71575012 Mon Sep 17 00:00:00 2001 From: deathaxe Date: Sat, 3 Feb 2024 16:56:46 +0100 Subject: [PATCH] [Python] Improve type alias definitions (#3917) Fixes #3902 This commit ensures to highlight `type` more context sensitively. It may have the following meanings: 1. built-in `type()` function 2. type alias declaration keyword: `type Alias` 3. ordinary variable used in many data classes The built-in function (1.) most likely appears in r-value expressions, such as `my_type = type(var)` At beginning of statements this commit prefers scoping `type` as keyword (2.) or variable (3.) as this is the most likely use case. The implementation ensures to start `meta` scope of alias declarations at bol as class or function declarations do. --- Python/Python.sublime-syntax | 27 ++++++++++++--- Python/tests/syntax_test_python.py | 53 ++++++++++++++++++++++++++++-- 2 files changed, 74 insertions(+), 6 deletions(-) diff --git a/Python/Python.sublime-syntax b/Python/Python.sublime-syntax index 5f4fdcacc9..6862024055 100644 --- a/Python/Python.sublime-syntax +++ b/Python/Python.sublime-syntax @@ -149,7 +149,7 @@ variables: | getattr | globals | hasattr | hash | help | hex | id | input | isinstance | issubclass | iter | len | locals | map | max | min | next | oct | open | ord | pow | property | range | repr | reversed | round | setattr | sorted - | staticmethod | sum | super | type | vars | zip + | staticmethod | sum | super | type(?=\s*\() | vars | zip # Python 2 functions | apply | cmp | coerce | execfile | intern | raw_input | reduce | reload | unichr | xrange @@ -1042,10 +1042,18 @@ contexts: ###[ TYPE DEFINITIONS ]####################################################### type-definitions: - - match: ^\s*(type)\b + - match: ^(?=\s*type\b) + branch_point: type-definitions + branch: + - type-definition + - type-definition-fallback + + type-definition: + - meta_include_prototype: false + - match: \s*(type)\b captures: 1: keyword.declaration.class.python - push: + set: - type-definition-meta - type-definition-value-assignment - type-parameter-list @@ -1061,7 +1069,9 @@ contexts: - match: '{{identifier}}' scope: entity.name.type.alias.python pop: 1 - - include: line-continuation-or-pop + - include: line-continuations + - match: (?=\S) + fail: type-definitions type-definition-value-assignment: - match: = @@ -1069,6 +1079,15 @@ contexts: set: variable-annotation - include: line-continuation-or-pop + type-definition-fallback: + # Fallback context, used, if `type` doesn't seem to start a type alias + - match: (?={{path}}\s*\() + set: + - function-call-argument-list + - function-call-wrapper + - qualified-name-until-leaf + - include: generic-name + ###[ TYPE PARAMETERS ]######################################################## type-parameter-lists: diff --git a/Python/tests/syntax_test_python.py b/Python/tests/syntax_test_python.py index a516d7e5c9..9926d03ed4 100644 --- a/Python/tests/syntax_test_python.py +++ b/Python/tests/syntax_test_python.py @@ -2248,8 +2248,8 @@ def method(arg: T): ################## type -# <- meta.type-alias.python keyword.declaration.class.python -#^^^ meta.type-alias.python keyword.declaration.class.python +# <- meta.generic-name - keyword +#^^^ meta.generic-name - keyword type Alias # [T: int] = list[T] # <- meta.type-alias.python keyword.declaration.class.python @@ -2320,6 +2320,55 @@ def method(arg: T): # ^ meta.generic-name.python # ^ punctuation.section.brackets.end.python + type Alias +# <- meta.type-alias.python +#^^^^^^^^^^^ meta.type-alias.python +# ^^^^ keyword.declaration.class.python +# ^^^^^ entity.name.type.alias.python + +type(data) +# <- meta.function-call.identifier.python support.function.builtin.python +#^^^ meta.function-call.identifier.python support.function.builtin.python +# ^^^^^^ meta.function-call.arguments.python +# ^ punctuation.section.arguments.begin.python +# ^^^^ meta.path.python meta.generic-name.python +# ^ punctuation.section.arguments.end.python + +type: Alias +# <- meta.generic-name.python +#^^^ meta.generic-name.python +# ^ punctuation.separator.annotation.python +# ^^^^^ meta.type.python meta.path.python meta.generic-name.python + +type = 10 +# <- meta.generic-name.python +#^^^ meta.generic-name.python +# ^ keyword.operator.assignment.python +# ^^ meta.number.integer.decimal.python constant.numeric.value.python + +class Foo: + type: Alias +# ^^^^ meta.generic-name.python +# ^ punctuation.separator.annotation.python +# ^^^^^ meta.type.python meta.path.python meta.generic-name.python + + type = 10 +# ^^^^ meta.generic-name.python +# ^ keyword.operator.assignment.python +# ^^ meta.number.integer.decimal.python constant.numeric.value.python + + def __init__(self, type: int): +# ^^^^ variable.parameter.python + self.type = type +# ^^^^ meta.path.python meta.generic-name.python +# ^^^^ meta.path.python meta.generic-name.python + + self.me = type(type) +# ^^^^ meta.function-call.identifier.python support.function.builtin.python +# ^^^^^^ meta.function-call.arguments.python +# ^ punctuation.section.arguments.begin.python +# ^^^^ meta.path.python meta.generic-name.python +# ^ punctuation.section.arguments.end.python ################## # Decorators