Skip to content

Commit

Permalink
[Python] Improve type alias definitions (#3917)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
deathaxe authored Feb 3, 2024
1 parent 7b10f9b commit 350e338
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 6 deletions.
27 changes: 23 additions & 4 deletions Python/Python.sublime-syntax
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -1061,14 +1069,25 @@ 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: =
scope: keyword.operator.assignment.python
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:
Expand Down
53 changes: 51 additions & 2 deletions Python/tests/syntax_test_python.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 350e338

Please sign in to comment.