mirror of
https://github.com/microsoft/pyright.git
synced 2024-08-16 03:10:35 +03:00
Check completion item kind, non-property completion fast path (#1099)
This commit is contained in:
parent
97f8483392
commit
b45ce5b492
@ -3,7 +3,7 @@
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"postinstall": "npm run bootstrap",
|
||||
"bootstrap": "node ./build/skipBootstrap.js || lerna bootstrap",
|
||||
"bootstrap": "node ./build/skipBootstrap.js || lerna bootstrap --no-ci",
|
||||
"clean": "lerna run --no-bail --stream clean",
|
||||
"install:all": "npm install && lerna exec --no-bail npm install",
|
||||
"update:all": "node ./build/updateDeps.js",
|
||||
|
@ -20,7 +20,7 @@ import {
|
||||
|
||||
import { ImportLookup } from '../analyzer/analyzerFileInfo';
|
||||
import * as AnalyzerNodeInfo from '../analyzer/analyzerNodeInfo';
|
||||
import { Declaration, DeclarationType } from '../analyzer/declaration';
|
||||
import { Declaration, DeclarationType, FunctionDeclaration } from '../analyzer/declaration';
|
||||
import { convertDocStringToMarkdown, convertDocStringToPlainText } from '../analyzer/docStringConversion';
|
||||
import { ImportedModuleDescriptor, ImportResolver } from '../analyzer/importResolver';
|
||||
import * as ParseTreeUtils from '../analyzer/parseTreeUtils';
|
||||
@ -1567,9 +1567,11 @@ export class CompletionProvider {
|
||||
: CompletionItemKind.Variable;
|
||||
|
||||
case DeclarationType.Function: {
|
||||
const functionType = this._evaluator.getTypeOfFunction(resolvedDeclaration.node);
|
||||
if (functionType && isProperty(functionType.decoratedType)) {
|
||||
return CompletionItemKind.Property;
|
||||
if (this._isPossiblePropertyDeclaration(resolvedDeclaration)) {
|
||||
const functionType = this._evaluator.getTypeOfFunction(resolvedDeclaration.node);
|
||||
if (functionType && isProperty(functionType.decoratedType)) {
|
||||
return CompletionItemKind.Property;
|
||||
}
|
||||
}
|
||||
return resolvedDeclaration.isMethod ? CompletionItemKind.Method : CompletionItemKind.Function;
|
||||
}
|
||||
@ -1625,4 +1627,10 @@ export class CompletionProvider {
|
||||
|
||||
return { completionList };
|
||||
}
|
||||
|
||||
private _isPossiblePropertyDeclaration(decl: FunctionDeclaration) {
|
||||
// Do cheap check using only nodes that will cover 99.9% cases
|
||||
// before doing more expensive type evaluation.
|
||||
return decl.isMethod && decl.node.decorators.length > 0;
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ await helper.verifyCompletion('included', 'markdown', {
|
||||
completions: [
|
||||
{
|
||||
label: 'Test',
|
||||
kind: Consts.CompletionItemKind.Class,
|
||||
documentation: '```\nfrom testLib import Test\n```',
|
||||
detail: 'Auto-import',
|
||||
},
|
||||
|
@ -31,6 +31,7 @@ await helper.verifyCompletion('included', 'markdown', {
|
||||
completions: [
|
||||
{
|
||||
label: 'test1',
|
||||
kind: Consts.CompletionItemKind.Module,
|
||||
documentation: '```\nfrom testLib import test1\n```',
|
||||
detail: 'Auto-import',
|
||||
},
|
||||
|
@ -18,6 +18,7 @@ await helper.verifyCompletion('excluded', 'markdown', {
|
||||
completions: [
|
||||
{
|
||||
label: 'Test',
|
||||
kind: Consts.CompletionItemKind.Class,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -13,6 +13,7 @@ await helper.verifyCompletion('included', 'markdown', {
|
||||
completions: [
|
||||
{
|
||||
label: 'Test',
|
||||
kind: Consts.CompletionItemKind.Class,
|
||||
documentation: '```\nfrom test2 import Test\n```',
|
||||
detail: 'Auto-import',
|
||||
},
|
||||
|
@ -13,6 +13,7 @@ await helper.verifyCompletion('included', 'plaintext', {
|
||||
completions: [
|
||||
{
|
||||
label: 'Test',
|
||||
kind: Consts.CompletionItemKind.Class,
|
||||
documentation: 'from test2 import Test',
|
||||
detail: 'Auto-import',
|
||||
},
|
||||
|
@ -32,6 +32,7 @@ await helper.verifyCompletion('exact', 'markdown', {
|
||||
completions: [
|
||||
{
|
||||
label: 'MyShadow',
|
||||
kind: Consts.CompletionItemKind.Class,
|
||||
documentation: '```\nfrom testLib import MyShadow\n```',
|
||||
detail: 'Auto-import',
|
||||
},
|
||||
|
@ -20,6 +20,7 @@ await helper.verifyCompletion('included', 'markdown', {
|
||||
completions: [
|
||||
{
|
||||
label: 'os',
|
||||
kind: Consts.CompletionItemKind.Module,
|
||||
documentation: '```\nimport os\n```',
|
||||
detail: 'Auto-import',
|
||||
},
|
||||
@ -35,6 +36,7 @@ await helper.verifyCompletion('included', 'markdown', {
|
||||
completions: [
|
||||
{
|
||||
label: 'sys',
|
||||
kind: Consts.CompletionItemKind.Module,
|
||||
documentation: '```\nimport sys\n```',
|
||||
detail: 'Auto-import',
|
||||
},
|
||||
|
@ -7,6 +7,6 @@
|
||||
// @ts-ignore
|
||||
await helper.verifyCompletion('excluded', 'markdown', {
|
||||
marker1: {
|
||||
completions: [{ label: 'capitalize' }],
|
||||
completions: [{ label: 'capitalize', kind: undefined }],
|
||||
},
|
||||
});
|
||||
|
@ -15,16 +15,18 @@
|
||||
|
||||
// @ts-ignore
|
||||
await helper.verifyCompletion('exact', 'markdown', {
|
||||
marker1: { completions: [{ label: 'localtime' }] },
|
||||
marker2: { completions: [{ label: 'aaaaaa' }] },
|
||||
marker1: { completions: [{ label: 'localtime', kind: Consts.CompletionItemKind.Function }] },
|
||||
marker2: { completions: [{ label: 'aaaaaa', kind: Consts.CompletionItemKind.Variable }] },
|
||||
marker3: {
|
||||
completions: [
|
||||
{
|
||||
label: 'some_func1',
|
||||
kind: Consts.CompletionItemKind.Function,
|
||||
documentation: '```python\nsome_func1: (a: Unknown) -> None\n```\n---\nsome function docs',
|
||||
},
|
||||
{
|
||||
label: 'some_func2',
|
||||
kind: Consts.CompletionItemKind.Function,
|
||||
documentation: '```python\nsome_func2: (a: Unknown) -> None\n```\n---\nanother function docs',
|
||||
},
|
||||
],
|
||||
|
@ -7,6 +7,6 @@
|
||||
// @ts-ignore
|
||||
await helper.verifyCompletion('included', 'markdown', {
|
||||
marker1: {
|
||||
completions: [{ label: 'numerator' }],
|
||||
completions: [{ label: 'numerator', kind: Consts.CompletionItemKind.Property }],
|
||||
},
|
||||
});
|
||||
|
@ -47,6 +47,7 @@ await helper.verifyCompletion('included', 'markdown', {
|
||||
completions: [
|
||||
{
|
||||
label: 'Validator',
|
||||
kind: Consts.CompletionItemKind.Class,
|
||||
documentation: '```python\nclass Validator()\n```\n---\nThe validator class',
|
||||
},
|
||||
],
|
||||
@ -55,6 +56,7 @@ await helper.verifyCompletion('included', 'markdown', {
|
||||
completions: [
|
||||
{
|
||||
label: 'is_valid',
|
||||
kind: Consts.CompletionItemKind.Method,
|
||||
documentation:
|
||||
'```python\nis_valid: (text: str) -> bool\n```\n---\nChecks if the input string is valid.',
|
||||
},
|
||||
@ -64,10 +66,12 @@ await helper.verifyCompletion('included', 'markdown', {
|
||||
completions: [
|
||||
{
|
||||
label: 'read_only_prop',
|
||||
kind: Consts.CompletionItemKind.Property,
|
||||
documentation: '```python\nread_only_prop: bool (property)\n```\n---\nThe read-only property.',
|
||||
},
|
||||
{
|
||||
label: 'read_write_prop',
|
||||
kind: Consts.CompletionItemKind.Property,
|
||||
documentation: '```python\nread_write_prop: bool (property)\n```\n---\nThe read-write property.',
|
||||
},
|
||||
],
|
||||
|
@ -37,6 +37,7 @@ await helper.verifyCompletion('included', 'markdown', {
|
||||
completions: [
|
||||
{
|
||||
label: 'Validator',
|
||||
kind: Consts.CompletionItemKind.Class,
|
||||
documentation: '```python\nclass Validator()\n```\n---\nThe validator class',
|
||||
},
|
||||
],
|
||||
@ -45,6 +46,7 @@ await helper.verifyCompletion('included', 'markdown', {
|
||||
completions: [
|
||||
{
|
||||
label: 'is_valid',
|
||||
kind: Consts.CompletionItemKind.Method,
|
||||
documentation:
|
||||
'```python\nis_valid: (text: str) -> bool\n```\n---\nChecks if the input string is valid.',
|
||||
},
|
||||
@ -54,10 +56,12 @@ await helper.verifyCompletion('included', 'markdown', {
|
||||
completions: [
|
||||
{
|
||||
label: 'read_only_prop',
|
||||
kind: Consts.CompletionItemKind.Property,
|
||||
documentation: '```python\nread_only_prop: bool (property)\n```\n---\nThe read-only property.',
|
||||
},
|
||||
{
|
||||
label: 'read_write_prop',
|
||||
kind: Consts.CompletionItemKind.Property,
|
||||
documentation: '```python\nread_write_prop: bool (property)\n```\n---\nThe read-write property.',
|
||||
},
|
||||
],
|
||||
|
@ -37,6 +37,7 @@ await helper.verifyCompletion('included', 'markdown', {
|
||||
completions: [
|
||||
{
|
||||
label: 'Validator',
|
||||
kind: Consts.CompletionItemKind.Class,
|
||||
documentation: '```python\nclass Validator()\n```\n---\nThe validator class',
|
||||
},
|
||||
],
|
||||
@ -45,6 +46,7 @@ await helper.verifyCompletion('included', 'markdown', {
|
||||
completions: [
|
||||
{
|
||||
label: 'is_valid',
|
||||
kind: Consts.CompletionItemKind.Method,
|
||||
documentation:
|
||||
'```python\nis_valid: (text: str) -> bool\n```\n---\nChecks if the input string is valid.',
|
||||
},
|
||||
@ -54,10 +56,12 @@ await helper.verifyCompletion('included', 'markdown', {
|
||||
completions: [
|
||||
{
|
||||
label: 'read_only_prop',
|
||||
kind: Consts.CompletionItemKind.Property,
|
||||
documentation: '```python\nread_only_prop: bool (property)\n```\n---\nThe read-only property.',
|
||||
},
|
||||
{
|
||||
label: 'read_write_prop',
|
||||
kind: Consts.CompletionItemKind.Property,
|
||||
documentation: '```python\nread_write_prop: bool (property)\n```\n---\nThe read-write property.',
|
||||
},
|
||||
],
|
||||
|
@ -32,6 +32,7 @@ await helper.verifyCompletion('included', 'markdown', {
|
||||
completions: [
|
||||
{
|
||||
label: 'Validator',
|
||||
kind: Consts.CompletionItemKind.Class,
|
||||
documentation: '```python\nclass Validator()\n```\n---\nThe validator class',
|
||||
},
|
||||
],
|
||||
@ -40,6 +41,7 @@ await helper.verifyCompletion('included', 'markdown', {
|
||||
completions: [
|
||||
{
|
||||
label: 'is_valid',
|
||||
kind: Consts.CompletionItemKind.Method,
|
||||
documentation:
|
||||
'```python\nis_valid: (text: str) -> bool\n```\n---\nChecks if the input string is valid.',
|
||||
},
|
||||
@ -49,10 +51,12 @@ await helper.verifyCompletion('included', 'markdown', {
|
||||
completions: [
|
||||
{
|
||||
label: 'read_only_prop',
|
||||
kind: Consts.CompletionItemKind.Property,
|
||||
documentation: '```python\nread_only_prop: bool (property)\n```\n---\nThe read-only property.',
|
||||
},
|
||||
{
|
||||
label: 'read_write_prop',
|
||||
kind: Consts.CompletionItemKind.Property,
|
||||
documentation: '```python\nread_write_prop: bool (property)\n```\n---\nThe read-write property.',
|
||||
},
|
||||
],
|
||||
@ -61,6 +65,7 @@ await helper.verifyCompletion('included', 'markdown', {
|
||||
completions: [
|
||||
{
|
||||
label: 'is_valid',
|
||||
kind: Consts.CompletionItemKind.Method,
|
||||
documentation:
|
||||
'```python\nis_valid: (self: Validator, text: str) -> bool\n```\n---\nChecks if the input string is valid.',
|
||||
},
|
||||
|
@ -21,6 +21,7 @@ await helper.verifyCompletion('included', 'markdown', {
|
||||
completions: [
|
||||
{
|
||||
label: 'func',
|
||||
kind: Consts.CompletionItemKind.Function,
|
||||
documentation: '```python\nfunc(x: str) -> str\nfunc(x: int) -> int\n```\n---\nfunc docs',
|
||||
},
|
||||
],
|
||||
|
@ -9,16 +9,16 @@
|
||||
// @ts-ignore
|
||||
await helper.verifyCompletion('excluded', 'markdown', {
|
||||
marker1: {
|
||||
completions: [{ label: 'param1' }],
|
||||
completions: [{ label: 'param1', kind: undefined }],
|
||||
},
|
||||
marker2: {
|
||||
completions: [{ label: 'param1' }],
|
||||
completions: [{ label: 'param1', kind: undefined }],
|
||||
},
|
||||
});
|
||||
|
||||
// @ts-ignore
|
||||
await helper.verifyCompletion('included', 'markdown', {
|
||||
marker3: {
|
||||
completions: [{ label: 'param1=' }],
|
||||
completions: [{ label: 'param1=', kind: Consts.CompletionItemKind.Variable }],
|
||||
},
|
||||
});
|
||||
|
@ -15,16 +15,18 @@
|
||||
|
||||
// @ts-ignore
|
||||
await helper.verifyCompletion('exact', 'plaintext', {
|
||||
marker1: { completions: [{ label: 'localtime' }] },
|
||||
marker2: { completions: [{ label: 'aaaaaa' }] },
|
||||
marker1: { completions: [{ label: 'localtime', kind: Consts.CompletionItemKind.Function }] },
|
||||
marker2: { completions: [{ label: 'aaaaaa', kind: Consts.CompletionItemKind.Variable }] },
|
||||
marker3: {
|
||||
completions: [
|
||||
{
|
||||
label: 'some_func1',
|
||||
kind: Consts.CompletionItemKind.Function,
|
||||
documentation: 'some_func1: (a: Unknown) -> None\n\nsome function docs',
|
||||
},
|
||||
{
|
||||
label: 'some_func2',
|
||||
kind: Consts.CompletionItemKind.Function,
|
||||
documentation: 'some_func2: (a: Unknown) -> None\n\nanother function docs',
|
||||
},
|
||||
],
|
||||
|
@ -0,0 +1,28 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
// @filename: test.py
|
||||
//// class C:
|
||||
//// def __init__(self):
|
||||
//// self._x = None
|
||||
////
|
||||
//// @property
|
||||
//// def prop(self):
|
||||
//// pass
|
||||
////
|
||||
//// @prop.setter
|
||||
//// def prop(self, value):
|
||||
//// pass
|
||||
////
|
||||
//// C()./*marker*/prop
|
||||
|
||||
// @ts-ignore
|
||||
await helper.verifyCompletion('included', 'markdown', {
|
||||
marker: {
|
||||
completions: [
|
||||
{
|
||||
label: 'prop',
|
||||
kind: Consts.CompletionItemKind.Property,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
@ -20,18 +20,22 @@ await helper.verifyCompletion('included', 'markdown', {
|
||||
completions: [
|
||||
{
|
||||
label: 'method1',
|
||||
kind: Consts.CompletionItemKind.Method,
|
||||
documentation: '```python\nmethod1: () -> None\n```\n---\nMethod 1.',
|
||||
},
|
||||
{
|
||||
label: 'new_method',
|
||||
kind: Consts.CompletionItemKind.Method,
|
||||
documentation: '```python\nnew_method: () -> None\n```\n',
|
||||
},
|
||||
{
|
||||
label: 'prop1',
|
||||
kind: Consts.CompletionItemKind.Property,
|
||||
documentation: '```python\nprop1: Literal[2] (property)\n```\n---\nProperty 1.',
|
||||
},
|
||||
{
|
||||
label: 'var1',
|
||||
kind: Consts.CompletionItemKind.Variable,
|
||||
documentation: '```python\nvar1: int\n```\n',
|
||||
},
|
||||
],
|
||||
|
@ -23,9 +23,37 @@
|
||||
*/
|
||||
|
||||
declare namespace _ {
|
||||
type CompletionItemKind =
|
||||
| 1
|
||||
| 2
|
||||
| 3
|
||||
| 4
|
||||
| 5
|
||||
| 6
|
||||
| 7
|
||||
| 8
|
||||
| 9
|
||||
| 10
|
||||
| 11
|
||||
| 12
|
||||
| 13
|
||||
| 14
|
||||
| 15
|
||||
| 16
|
||||
| 17
|
||||
| 18
|
||||
| 19
|
||||
| 20
|
||||
| 21
|
||||
| 22
|
||||
| 23
|
||||
| 24
|
||||
| 25;
|
||||
|
||||
type FourSlashCompletionVerificationMode = 'exact' | 'included' | 'excluded';
|
||||
interface FourSlashCompletionItem {
|
||||
label: string;
|
||||
kind: CompletionItemKind | undefined;
|
||||
insertionText?: string;
|
||||
documentation?: string;
|
||||
detail?: string;
|
||||
@ -251,4 +279,32 @@ declare namespace Consts {
|
||||
*/
|
||||
const Write: 3;
|
||||
}
|
||||
|
||||
namespace CompletionItemKind {
|
||||
const Text: 1;
|
||||
const Method: 2;
|
||||
const Function: 3;
|
||||
const Constructor: 4;
|
||||
const Field: 5;
|
||||
const Variable: 6;
|
||||
const Class: 7;
|
||||
const Interface: 8;
|
||||
const Module: 9;
|
||||
const Property: 10;
|
||||
const Unit: 11;
|
||||
const Value: 12;
|
||||
const Enum: 13;
|
||||
const Keyword: 14;
|
||||
const Snippet: 15;
|
||||
const Color: 16;
|
||||
const File: 17;
|
||||
const Reference: 18;
|
||||
const Folder: 19;
|
||||
const EnumMember: 20;
|
||||
const Constant: 21;
|
||||
const Struct: 22;
|
||||
const Event: 23;
|
||||
const Operator: 24;
|
||||
const TypeParameter: 25;
|
||||
}
|
||||
}
|
||||
|
@ -50,21 +50,27 @@ await helper.verifyCompletion('exact', 'markdown', {
|
||||
completions: [
|
||||
{
|
||||
label: 'foofoofoo0',
|
||||
kind: Consts.CompletionItemKind.Variable,
|
||||
},
|
||||
{
|
||||
label: 'foofoofoo2',
|
||||
kind: Consts.CompletionItemKind.Variable,
|
||||
},
|
||||
{
|
||||
label: 'foofoofoo3',
|
||||
kind: Consts.CompletionItemKind.Variable,
|
||||
},
|
||||
{
|
||||
label: 'foofoofoo5',
|
||||
kind: Consts.CompletionItemKind.Variable,
|
||||
},
|
||||
{
|
||||
label: 'foofoofoo7',
|
||||
kind: Consts.CompletionItemKind.Variable,
|
||||
},
|
||||
{
|
||||
label: 'foofoofoo9',
|
||||
kind: Consts.CompletionItemKind.Variable,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -30,6 +30,7 @@ await helper.verifyCompletion('included', 'markdown', {
|
||||
completions: [
|
||||
{
|
||||
label: 'method1',
|
||||
kind: Consts.CompletionItemKind.Method,
|
||||
documentation: '```python\nmethod1: () -> None\n```\n---\nMethod docs',
|
||||
},
|
||||
],
|
||||
|
@ -23,4 +23,6 @@ export namespace Consts {
|
||||
orderImports = 'pyright.organizeimports',
|
||||
addMissingOptionalToParam = 'pyright.addoptionalforparam',
|
||||
}
|
||||
|
||||
export import CompletionItemKind = lsp.CompletionItemKind;
|
||||
}
|
||||
|
@ -868,6 +868,7 @@ export class TestState {
|
||||
const actual: CompletionItem = result.completionList.items[actualIndex];
|
||||
assert.equal(actual.label, expected.label);
|
||||
assert.equal(actual.detail, expected.detail);
|
||||
assert.equal(actual.kind, expected.kind);
|
||||
if (expectedCompletions[i].documentation !== undefined) {
|
||||
if (actual.documentation === undefined) {
|
||||
this.program.resolveCompletionItem(
|
||||
|
Loading…
Reference in New Issue
Block a user