-
Notifications
You must be signed in to change notification settings - Fork 591
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Python] Add support for type comments and annotations #3736
Conversation
This commit ... 1. uses `type-hint-body` context for variable type annotations 2. replaces the scope by the more general `meta.type.python`, which is used by type comments already. It is originally inspired by PHP's type hints, which also use `meta.type`. Python doesn't scope variables `meta.variable` in general. Hence former chosen `meta.variable.annotation` is a kind of compromise to follow the scheme of function definition scopes. A common `meta.type` scope should help color schemes to maintain consistent highlighting for all type hints.
This commit... 1. replaces `annotation` by `type` in scope names 2. scopes function return types `meta.function.return-type` which is used in most other syntaxes. The annotation character is specified via `meta.type`. The overall goal is to apply scope naming scheme for type hints, which is implemented already in PHP, TypeScript and TSX, using `meta.type`. Renamed contexts should clarify this syntax explicitly targets type hints in function/parameter/variable annotations.
This commit restricts `meta.type` to cover type expressions without leading or trailing whitespace. It results in better UX in case a background color is assigned by a color scheme.
This commit interprets brackets in types as lists of type members.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes look good in general, except that they also prevent other uses of annotations which are perfectly valid Python but now show as invalid
. I've provided a few examples below.
I'll see if I can try this out on some of my code over the next week.
AFAIK, annotations are basically just something like comments, thus nearly any content is valid, syntactically. Yes, this PR restricts annotations to type hints, as this is the most common use for them, these days. |
I agree that type hints are the most frequently used use case, but I don't agree with highlighting other uses as invalid. Invalid highlighting is very disruptive and should only be used when the lexer is confident that it is indeed invalid (syntax), which is not the case here. |
TBH, I don't want to add branching for that, as it overcomplicates things. The alternative is to just revert annotations to use I'd still scope them Ideally we would use |
This commit partly reverts restrictions to allow only type-hints in annotations. For sake of consistent highlighting brackets are scoped `meta.brackets` instead of `meta.item-access` and `meta.sequence.list.members`, so chances are lower for equally looking terms to be higlighted differently. Annotations are still scoped `meta.type` as this is the primary use case and the scope is to be used by color schemes for dimming type hints easily.
In the following, it would be good if
Similar to a previous change which was welcome: PR #3421 |
Ideally, yes. Not so easy as annotations are expected to support ordinary expressions, where the qualifier part could be anything (variable, module, class, ...). |
Sorry if this is not a question entirely relevant to this PR but how would one do that easily?
to my color scheme then it only grays out some of the types and not the other. Probably because of scope priorities. |
Your later scopes are coloring things overtop the gray applied by {
"name": "Python type annotation",
"scope": "source.python meta.function.parameters.annotation, source.python meta.function.annotation.return",
"background": "var(blue3)",
"foreground_adjust": "saturation(- 40%) lightness(- 20%)",
}, Obviously, you could desaturate all the way down or whatever, but I find that keeping a little color (but very de-emphasized) is nice. |
How specific a scope selector of a color scheme customization needs to be, depends on the underlying color scheme. I mainly use a (heavily) customized Brackets color scheme with following rules to make type hints stand out. Basically the same idea as Michaels. I just found it annoying to need to target all the different // Python type annotations
{
"name": "Annotation Background",
"scope": "meta.type",
"background": "color(var(textcolor) blend(var(background) 4%))",
},
{
"name": "Python Type Annotations: Types",
"scope": "meta.type & (meta.generic-name, support.class, support.type, storage)",
"foreground": "color(var(grey) blend(var(blue) 70%))",
},
{
"name": "Python Type Annotations: Constants",
"scope": "meta.type & (constant.language, constant.other, string)",
"foreground": "color(var(grey) blend(var(orange) 70%))",
},
This PR adds all exported classes/types from python 3.11's typing module to the globally applied list of predefined types, such as |
A scope like EDIT: Also in TS it doesn't even seem possible to override this region (the It's a |
@rchl Did you try Edit: Hmm. I don't know if it can override LSP extras. |
Doesn't help with overriding semantic regions. |
With the builtins from the typing module being scoped Packages/Python/Python.sublime-syntax Line 1962 in 7b6c099
|
Makes sense. |
With classes from typing module being scoped `support.class` it makes sense to scope exception classes this way, too. So all CamelCase types are organized under the same 2nd-level scope.
Scope naming guidelines request basic builtin types such as `int` to be scoped `storage.type` as `support` scope is dedicated for library or user defined types. This commit changes scope of builtins accordingly as a result of former changes of type scopes.
Question: Does it make sense to support highlighting type comments when they are already deprecated? microsoft/pyright#3557 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Used the wrong button earlier.
As TL;TR #1842 : Can you give any example? |
Yes. def stringify(x: int) -> str:
return str(x)
def shadow_update_dict(d1: dict, d2: dict) -> Mapping:
return ChainMap(d2, d1) In this example, That said, which scope guideline are you referring to in
https://www.sublimetext.com/docs/scope_naming.html#storage So, I assume you're referring to the TM ones, which I guess are still the most recent guidelines that have been written down and at least kind of make sense. I should really get SNG going at some point … |
Your excerpt of the guidelines is a bit unconventional as well, as it might suggest that the listed scopes were the headings, followed by a description. It makes more sense if you adjust the quoted region like it is actually meant to be read 😆 :
So I would say that |
Which is exactly how I read it – multiple times at that – but I see now that this is not the way they were inteded to be read. Still, I still thing the section is weird.
Yes, I didn't say it was wrong, it's just not something I personally agree with.
The same thing is already applied for function calls, as you mentiond, so it really shouldn't be that much of an issue. At this point, it's mostly the should part that needs to be discussed, not the could. |
The intent behind
Types being scoped the same in declarations and constructors is not introduced by this PR, but rather a long standing implementation detail as well as scoping tokens as builtins/keywords in locations they are not treated as such by the interpreter. What I'd be concerned about in general is trying to add too much semantic details to syntaxes or scoping keywords differntly depending on where or in which context they appear. It is easy for some syntaxes, but there are as many syntaxes it would require sophisticated context structures and rules if even doable at all, reliably - not even thinking about ambiguities, which can't be resolved by a static lexer. Actually instantiation expressions (e.g.: I am however uncertain whether scoping the same kind of instantiation expression in C++/Java (e.g.: Another aspect to consider are type casts such as |
Let's not stride too much into #1842 territory here. The only point I was trying to make with my comment is the following:
I don't have a strong opinion on it but I wanted to raise it regardless to hear your thoughts on the matter. (However, if you're strongly inclined to highlight types the same always, that would imply this to be the only necessary change, so I suppose you'd rather be in support of changing it now.) |
I don't want to introduce/enforce changes other members don't feel comfortable with. Just an ordinary contributor here as anyone else. It's probably not a big deal to stay with the old scopes - may proable even avoid unexpected visual changes. However the only other syntaxes which scope basic builtin types All other syntax definitions seem to follow the builtin = Code seems to look a bit inferior with Mariana color scheme as color for Are there other oppinions? |
This reverts commit fc93275.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would have been fine either way.
Reverting annotations to normal expressions breaks adjusted LSP-pyright syntax and has some unwanted side effects with regards to scoping Some more adjustments seem to be required to get things inline. |
This commit scopes `|` as normal arithmetic operator in type comments for consistency reasons, because type hints in annotations (variables, parameters, return-type) need to use normal expression syntax.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kind of icky, but okay.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can definitely iterate on type the union operator later if we discover a good solution.
This commit introduces some ...-annotation-content contexts to allow 3rd-party syntaxes to easily extend annotation expressions or replace them by type-hints, with loose coupling and without degrading context bailouts.
…ion was changed significantly REF: sublimehq/Packages#3736 REF: sublimehq/Packages#3799
Supersedes #1925
This PR proposes to add dedicated contexts for type hints.
It provides highlighting for type comments including feedback from #1925.
Existing type annotations are refactored to
make use offollow a common scope naming scheme for type hints. It is inspired by PHP, TS and TSX, which usetype-expressions
andmeta.type
to scope type hint expressions.Known type classes from typing module are scoped as
support.class.typing
.