@zzzen/pyright-internal 1.2.0-dev.20260222 → 1.2.0-dev.20260422
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analyzer/backgroundAnalysisProgram.d.ts +1 -1
- package/dist/analyzer/backgroundAnalysisProgram.js +9 -6
- package/dist/analyzer/backgroundAnalysisProgram.js.map +1 -1
- package/dist/analyzer/binder.d.ts +10 -1
- package/dist/analyzer/binder.js +258 -41
- package/dist/analyzer/binder.js.map +1 -1
- package/dist/analyzer/cellChainIndex.d.ts +34 -0
- package/dist/analyzer/cellChainIndex.js +126 -0
- package/dist/analyzer/cellChainIndex.js.map +1 -0
- package/dist/analyzer/checker.js +0 -1
- package/dist/analyzer/checker.js.map +1 -1
- package/dist/analyzer/codeFlowEngine.js +16 -1
- package/dist/analyzer/codeFlowEngine.js.map +1 -1
- package/dist/analyzer/constructors.js +9 -2
- package/dist/analyzer/constructors.js.map +1 -1
- package/dist/analyzer/importResolver.d.ts +3 -21
- package/dist/analyzer/importResolver.js +42 -316
- package/dist/analyzer/importResolver.js.map +1 -1
- package/dist/analyzer/importResolverFileSystem.d.ts +3 -0
- package/dist/analyzer/importResolverFileSystem.js +160 -0
- package/dist/analyzer/importResolverFileSystem.js.map +1 -0
- package/dist/analyzer/importResolverTypes.d.ts +24 -0
- package/dist/analyzer/importResolverTypes.js +8 -0
- package/dist/analyzer/importResolverTypes.js.map +1 -0
- package/dist/analyzer/importStatementUtils.js +9 -0
- package/dist/analyzer/importStatementUtils.js.map +1 -1
- package/dist/analyzer/parseTreeUtils.d.ts +1 -0
- package/dist/analyzer/parseTreeUtils.js +24 -7
- package/dist/analyzer/parseTreeUtils.js.map +1 -1
- package/dist/analyzer/patternMatching.js +14 -2
- package/dist/analyzer/patternMatching.js.map +1 -1
- package/dist/analyzer/program.d.ts +5 -3
- package/dist/analyzer/program.js +40 -51
- package/dist/analyzer/program.js.map +1 -1
- package/dist/analyzer/pythonPathUtils.d.ts +1 -1
- package/dist/analyzer/pythonPathUtils.js +3 -1
- package/dist/analyzer/pythonPathUtils.js.map +1 -1
- package/dist/analyzer/scope.d.ts +10 -1
- package/dist/analyzer/scope.js +14 -1
- package/dist/analyzer/scope.js.map +1 -1
- package/dist/analyzer/service.d.ts +11 -6
- package/dist/analyzer/service.js +82 -83
- package/dist/analyzer/service.js.map +1 -1
- package/dist/analyzer/sourceEnumerator.d.ts +3 -0
- package/dist/analyzer/sourceEnumerator.js +27 -1
- package/dist/analyzer/sourceEnumerator.js.map +1 -1
- package/dist/analyzer/sourceFile.d.ts +2 -1
- package/dist/analyzer/sourceFile.js +2 -2
- package/dist/analyzer/sourceFile.js.map +1 -1
- package/dist/analyzer/sourceFileInfo.d.ts +4 -0
- package/dist/analyzer/sourceFileInfo.js +9 -0
- package/dist/analyzer/sourceFileInfo.js.map +1 -1
- package/dist/analyzer/sourceMapper.d.ts +1 -0
- package/dist/analyzer/sourceMapper.js +44 -0
- package/dist/analyzer/sourceMapper.js.map +1 -1
- package/dist/analyzer/tuples.js +3 -1
- package/dist/analyzer/tuples.js.map +1 -1
- package/dist/analyzer/typeEvaluator.js +102 -51
- package/dist/analyzer/typeEvaluator.js.map +1 -1
- package/dist/analyzer/typeEvaluatorTypes.d.ts +2 -0
- package/dist/analyzer/typeEvaluatorTypes.js +4 -0
- package/dist/analyzer/typeEvaluatorTypes.js.map +1 -1
- package/dist/analyzer/typeGuards.js +28 -6
- package/dist/analyzer/typeGuards.js.map +1 -1
- package/dist/analyzer/typeStubWriter.d.ts +15 -50
- package/dist/analyzer/typeStubWriter.js +91 -9
- package/dist/analyzer/typeStubWriter.js.map +1 -1
- package/dist/analyzer/typeUtils.d.ts +1 -0
- package/dist/analyzer/typeUtils.js +27 -3
- package/dist/analyzer/typeUtils.js.map +1 -1
- package/dist/analyzer/typeshedInfoProvider.d.ts +2 -0
- package/dist/analyzer/typeshedInfoProvider.js +232 -0
- package/dist/analyzer/typeshedInfoProvider.js.map +1 -0
- package/dist/backgroundAnalysisBase.d.ts +3 -3
- package/dist/backgroundAnalysisBase.js +12 -9
- package/dist/backgroundAnalysisBase.js.map +1 -1
- package/dist/commands/createTypeStub.d.ts +16 -8
- package/dist/commands/createTypeStub.js +58 -36
- package/dist/commands/createTypeStub.js.map +1 -1
- package/dist/common/cancellationUtils.d.ts +7 -0
- package/dist/common/cancellationUtils.js +34 -0
- package/dist/common/cancellationUtils.js.map +1 -1
- package/dist/common/collectionUtils.d.ts +3 -3
- package/dist/common/collectionUtils.js.map +1 -1
- package/dist/common/core.d.ts +1 -1
- package/dist/common/core.js.map +1 -1
- package/dist/common/crypto.js +11 -0
- package/dist/common/crypto.js.map +1 -1
- package/dist/common/extensibility.d.ts +7 -0
- package/dist/common/extensibility.js.map +1 -1
- package/dist/common/fullAccessHost.js +4 -2
- package/dist/common/fullAccessHost.js.map +1 -1
- package/dist/common/pathUtils.d.ts +4 -1
- package/dist/common/pathUtils.js.map +1 -1
- package/dist/common/realFileSystem.js +42 -3
- package/dist/common/realFileSystem.js.map +1 -1
- package/dist/common/serviceKeys.d.ts +3 -0
- package/dist/common/serviceKeys.js +2 -0
- package/dist/common/serviceKeys.js.map +1 -1
- package/dist/common/serviceProviderExtensions.js.map +1 -1
- package/dist/common/uri/uriUtils.d.ts +4 -0
- package/dist/common/uri/uriUtils.js +19 -3
- package/dist/common/uri/uriUtils.js.map +1 -1
- package/dist/common/workspaceEditUtils.js +0 -2
- package/dist/common/workspaceEditUtils.js.map +1 -1
- package/dist/languageServerBase.d.ts +1 -0
- package/dist/languageServerBase.js +6 -0
- package/dist/languageServerBase.js.map +1 -1
- package/dist/languageService/completionProvider.d.ts +6 -0
- package/dist/languageService/completionProvider.js +252 -75
- package/dist/languageService/completionProvider.js.map +1 -1
- package/dist/languageService/definitionProvider.js +1 -1
- package/dist/languageService/definitionProvider.js.map +1 -1
- package/dist/languageService/documentSymbolCollector.js +34 -4
- package/dist/languageService/documentSymbolCollector.js.map +1 -1
- package/dist/languageService/dynamicFeature.d.ts +3 -0
- package/dist/languageService/dynamicFeature.js +5 -0
- package/dist/languageService/dynamicFeature.js.map +1 -1
- package/dist/languageService/hoverProvider.d.ts +2 -1
- package/dist/languageService/hoverProvider.js +13 -5
- package/dist/languageService/hoverProvider.js.map +1 -1
- package/dist/languageService/pullDiagnosticsDynamicFeature.d.ts +1 -0
- package/dist/languageService/pullDiagnosticsDynamicFeature.js +4 -0
- package/dist/languageService/pullDiagnosticsDynamicFeature.js.map +1 -1
- package/dist/languageService/referencesProvider.js +5 -4
- package/dist/languageService/referencesProvider.js.map +1 -1
- package/dist/languageService/signatureHelpProvider.d.ts +1 -0
- package/dist/languageService/signatureHelpProvider.js +76 -2
- package/dist/languageService/signatureHelpProvider.js.map +1 -1
- package/dist/languageService/symbolIndexer.d.ts +1 -0
- package/dist/languageService/symbolIndexer.js.map +1 -1
- package/dist/languageService/tooltipUtils.d.ts +11 -4
- package/dist/languageService/tooltipUtils.js +195 -7
- package/dist/languageService/tooltipUtils.js.map +1 -1
- package/dist/parser/tokenizer.js +6 -2
- package/dist/parser/tokenizer.js.map +1 -1
- package/dist/partialStubService.d.ts +11 -0
- package/dist/partialStubService.js +23 -1
- package/dist/partialStubService.js.map +1 -1
- package/dist/pyright.js +13 -2
- package/dist/pyright.js.map +1 -1
- package/dist/tests/chainedSourceFiles.test.js +138 -0
- package/dist/tests/chainedSourceFiles.test.js.map +1 -1
- package/dist/tests/checker.test.js +12 -0
- package/dist/tests/checker.test.js.map +1 -1
- package/dist/tests/completions.test.js +328 -0
- package/dist/tests/completions.test.js.map +1 -1
- package/dist/tests/config.test.js +54 -0
- package/dist/tests/config.test.js.map +1 -1
- package/dist/tests/filesystem.test.js +44 -0
- package/dist/tests/filesystem.test.js.map +1 -1
- package/dist/tests/fourSlashRunner.test.js +1 -1
- package/dist/tests/fourSlashRunner.test.js.map +1 -1
- package/dist/tests/fourslash/findDefinitions.definitionFilter.preferSource.fourslash.js +25 -1
- package/dist/tests/fourslash/findDefinitions.definitionFilter.preferSource.fourslash.js.map +1 -1
- package/dist/tests/fourslash/import.multipart3.fourslash.d.ts +1 -0
- package/dist/tests/fourslash/import.multipart3.fourslash.js +46 -0
- package/dist/tests/fourslash/import.multipart3.fourslash.js.map +1 -0
- package/dist/tests/fourslash/import.pytyped.unsupportedDunderAll.fourslash.d.ts +1 -0
- package/dist/tests/fourslash/import.pytyped.unsupportedDunderAll.fourslash.js +33 -0
- package/dist/tests/fourslash/import.pytyped.unsupportedDunderAll.fourslash.js.map +1 -0
- package/dist/tests/harness/fourslash/runner.d.ts +4 -4
- package/dist/tests/harness/fourslash/runner.js +5 -5
- package/dist/tests/harness/fourslash/runner.js.map +1 -1
- package/dist/tests/harness/fourslash/testState.d.ts +20 -5
- package/dist/tests/harness/fourslash/testState.js +11 -26
- package/dist/tests/harness/fourslash/testState.js.map +1 -1
- package/dist/tests/harness/fourslash/testStateUtils.js +2 -0
- package/dist/tests/harness/fourslash/testStateUtils.js.map +1 -1
- package/dist/tests/harness/testAccessHost.d.ts +3 -1
- package/dist/tests/harness/testAccessHost.js +6 -2
- package/dist/tests/harness/testAccessHost.js.map +1 -1
- package/dist/tests/harness/testHost.js +20 -18
- package/dist/tests/harness/testHost.js.map +1 -1
- package/dist/tests/harness/vfs/factory.js +4 -1
- package/dist/tests/harness/vfs/factory.js.map +1 -1
- package/dist/tests/harness/vfs/filesystem.d.ts +8 -1
- package/dist/tests/harness/vfs/filesystem.js +84 -30
- package/dist/tests/harness/vfs/filesystem.js.map +1 -1
- package/dist/tests/hoverProvider.test.js +290 -0
- package/dist/tests/hoverProvider.test.js.map +1 -1
- package/dist/tests/importResolverSupport.test.d.ts +1 -0
- package/dist/tests/importResolverSupport.test.js +319 -0
- package/dist/tests/importResolverSupport.test.js.map +1 -0
- package/dist/tests/importStatementUtils.test.js +66 -0
- package/dist/tests/importStatementUtils.test.js.map +1 -1
- package/dist/tests/lsp/{webpack.testserver.config.d.ts → rspack.testserver.config.d.ts} +1 -1
- package/dist/tests/lsp/{webpack.testserver.config.js → rspack.testserver.config.js} +4 -11
- package/dist/tests/lsp/rspack.testserver.config.js.map +1 -0
- package/dist/tests/realTempFile.test.d.ts +1 -0
- package/dist/tests/realTempFile.test.js +144 -0
- package/dist/tests/realTempFile.test.js.map +1 -0
- package/dist/tests/service.test.js +182 -3
- package/dist/tests/service.test.js.map +1 -1
- package/dist/tests/signatureHelp.test.js +391 -6
- package/dist/tests/signatureHelp.test.js.map +1 -1
- package/dist/tests/testState.test.js +19 -0
- package/dist/tests/testState.test.js.map +1 -1
- package/dist/tests/tokenizer.test.js +42 -0
- package/dist/tests/tokenizer.test.js.map +1 -1
- package/dist/tests/typeEvaluator1.test.js +4 -0
- package/dist/tests/typeEvaluator1.test.js.map +1 -1
- package/dist/tests/typeEvaluator2.test.js +12 -0
- package/dist/tests/typeEvaluator2.test.js.map +1 -1
- package/dist/tests/typeEvaluator3.test.js +8 -1
- package/dist/tests/typeEvaluator3.test.js.map +1 -1
- package/dist/tests/typeEvaluator6.test.js +7 -0
- package/dist/tests/typeEvaluator6.test.js.map +1 -1
- package/dist/tests/typeEvaluator8.test.js +13 -1
- package/dist/tests/typeEvaluator8.test.js.map +1 -1
- package/dist/tests/uri.test.js +29 -0
- package/dist/tests/uri.test.js.map +1 -1
- package/dist/tests/wildcardImportPackageMerge.test.d.ts +1 -0
- package/dist/tests/wildcardImportPackageMerge.test.js +97 -0
- package/dist/tests/wildcardImportPackageMerge.test.js.map +1 -0
- package/dist/tests/workspaceEditUtils.test.js +0 -1
- package/dist/tests/workspaceEditUtils.test.js.map +1 -1
- package/package.json +12 -11
- package/dist/tests/lsp/webpack.testserver.config.js.map +0 -1
|
@@ -264,6 +264,11 @@ class CompletionProvider {
|
|
|
264
264
|
getCompletionItemData(item) {
|
|
265
265
|
return (0, lspUtils_1.fromLSPAny)(item.data);
|
|
266
266
|
}
|
|
267
|
+
addAdditionalExpressionCompletions(parseNode, priorWord, completionMap) {
|
|
268
|
+
// Default implementation is a no-op.
|
|
269
|
+
// Subclasses can override to inject additional completion items that are not produced by the
|
|
270
|
+
// core completion algorithm (e.g. product-specific synthesized completions).
|
|
271
|
+
}
|
|
267
272
|
getMethodOverrideCompletions(priorWord, partialName, decorators) {
|
|
268
273
|
const enclosingClass = ParseTreeUtils.getEnclosingClass(partialName, /* stopAtFunction */ true);
|
|
269
274
|
if (!enclosingClass) {
|
|
@@ -441,7 +446,7 @@ class CompletionProvider {
|
|
|
441
446
|
}
|
|
442
447
|
// This call can be expensive to perform on every completion item
|
|
443
448
|
// that we return, so we do it lazily in the "resolve" callback.
|
|
444
|
-
const type = this.
|
|
449
|
+
const type = this._getTypeOfSymbol(symbol, detail, name);
|
|
445
450
|
if (!type) {
|
|
446
451
|
// Can't resolve. so bail out.
|
|
447
452
|
return;
|
|
@@ -737,6 +742,39 @@ class CompletionProvider {
|
|
|
737
742
|
get _fileContents() {
|
|
738
743
|
return this.parseResults?.text ?? '';
|
|
739
744
|
}
|
|
745
|
+
_getTypeOfSymbol(symbol, detail, memberName) {
|
|
746
|
+
const originalType = this.evaluator.getEffectiveTypeOfSymbol(symbol);
|
|
747
|
+
if (!originalType) {
|
|
748
|
+
return undefined;
|
|
749
|
+
}
|
|
750
|
+
// If this completion item came from a member access on an object
|
|
751
|
+
// (as opposed to a name completion), compute the accessed type
|
|
752
|
+
// so descriptors report the correct type via __get__.
|
|
753
|
+
//
|
|
754
|
+
// Note that we intentionally exclude `property` here. `getTypeDetail` already
|
|
755
|
+
// understands `property` and includes the `(property)` suffix in hover/docs.
|
|
756
|
+
if (!detail.boundObjectOrClass || !types_1.TypeBase.isInstance(detail.boundObjectOrClass)) {
|
|
757
|
+
return originalType;
|
|
758
|
+
}
|
|
759
|
+
if ((0, typeUtils_1.isProperty)(originalType) || !(0, typeUtils_1.isMaybeDescriptorInstance)(originalType, /* requireSetter */ false)) {
|
|
760
|
+
return originalType;
|
|
761
|
+
}
|
|
762
|
+
const offset = (0, positionUtils_1.convertPositionToOffset)(this.position, this.parseResults.tokenizerOutput.lines);
|
|
763
|
+
if (offset === undefined) {
|
|
764
|
+
return originalType;
|
|
765
|
+
}
|
|
766
|
+
const node = ParseTreeUtils.findNodeByOffset(this.parseResults.parserOutput.parseTree, offset);
|
|
767
|
+
const memberAccessNode = node
|
|
768
|
+
? ParseTreeUtils.getParentNodeOfType(node, 35 /* ParseNodeType.MemberAccess */)
|
|
769
|
+
: undefined;
|
|
770
|
+
if (!memberAccessNode || memberAccessNode.nodeType !== 35 /* ParseNodeType.MemberAccess */) {
|
|
771
|
+
return originalType;
|
|
772
|
+
}
|
|
773
|
+
const boundType = this.evaluator.getTypeOfBoundMember(memberAccessNode, detail.boundObjectOrClass, memberName,
|
|
774
|
+
/* usage */ undefined,
|
|
775
|
+
/* diag */ undefined, 0 /* MemberAccessFlags.Default */);
|
|
776
|
+
return boundType?.type ?? originalType;
|
|
777
|
+
}
|
|
740
778
|
_getCompletions() {
|
|
741
779
|
const offset = (0, positionUtils_1.convertPositionToOffset)(this.position, this.parseResults.tokenizerOutput.lines);
|
|
742
780
|
if (offset === undefined) {
|
|
@@ -779,6 +817,18 @@ class CompletionProvider {
|
|
|
779
817
|
}
|
|
780
818
|
const curNode = ParseTreeUtils.findNodeByOffset(this.parseResults.parserOutput.parseTree, curOffset);
|
|
781
819
|
if (curNode && curNode !== initialNode) {
|
|
820
|
+
if ((curNode.nodeType === 48 /* ParseNodeType.StringList */ ||
|
|
821
|
+
curNode.nodeType === 49 /* ParseNodeType.String */ ||
|
|
822
|
+
curNode.nodeType === 30 /* ParseNodeType.FormatString */) &&
|
|
823
|
+
!(textRange_1.TextRange.contains(curNode, offset) || textRange_1.TextRange.getEnd(curNode) === offset)) {
|
|
824
|
+
// When completing after something like a trailing comma, ParseTreeUtils may return the
|
|
825
|
+
// preceding string node even though the cursor is outside the string.
|
|
826
|
+
//
|
|
827
|
+
// In that case, intentionally stop scanning and keep the existing context node
|
|
828
|
+
// (typically a call). Continuing would only move further into the previous argument and
|
|
829
|
+
// could select an even more misleading context.
|
|
830
|
+
break;
|
|
831
|
+
}
|
|
782
832
|
if (ParseTreeUtils.getNodeDepth(curNode) > initialDepth) {
|
|
783
833
|
node = curNode;
|
|
784
834
|
// If we're at the end of a list with a hanging comma, handle the
|
|
@@ -1396,6 +1446,7 @@ class CompletionProvider {
|
|
|
1396
1446
|
/* atArgument */ false, completionMap);
|
|
1397
1447
|
// Add symbols that are in scope.
|
|
1398
1448
|
this._addSymbols(parseNode, priorWord, completionMap);
|
|
1449
|
+
this.addAdditionalExpressionCompletions(parseNode, priorWord, completionMap);
|
|
1399
1450
|
// Add keywords.
|
|
1400
1451
|
this._findMatchingKeywords(Keywords.forVersion(this.execEnv.pythonVersion), priorWord).map((keyword) => {
|
|
1401
1452
|
if (completionMap.has(keyword)) {
|
|
@@ -1441,7 +1492,6 @@ class CompletionProvider {
|
|
|
1441
1492
|
if (!atArgument) {
|
|
1442
1493
|
this._addNamedParameters(signatureInfo, priorWord, completionMap);
|
|
1443
1494
|
}
|
|
1444
|
-
// Add literals that apply to this parameter.
|
|
1445
1495
|
this._addLiteralValuesForArgument(signatureInfo, priorWord, priorText, postText, completionMap);
|
|
1446
1496
|
}
|
|
1447
1497
|
}
|
|
@@ -1640,48 +1690,9 @@ class CompletionProvider {
|
|
|
1640
1690
|
if (!parentAndChild) {
|
|
1641
1691
|
return false;
|
|
1642
1692
|
}
|
|
1643
|
-
// See if the type evaluator can determine the expected type for this node.
|
|
1644
|
-
// ex) a: Literal["str"] = /* here */
|
|
1645
|
-
const nodeForExpectedType = parentAndChild.parent.nodeType === 3 /* ParseNodeType.Assignment */
|
|
1646
|
-
? parentAndChild.parent.d.rightExpr === parentAndChild.child
|
|
1647
|
-
? parentAndChild.child
|
|
1648
|
-
: undefined
|
|
1649
|
-
: (0, parseNodes_1.isExpressionNode)(parentAndChild.child)
|
|
1650
|
-
? parentAndChild.child
|
|
1651
|
-
: undefined;
|
|
1652
|
-
const offset = (0, positionUtils_1.convertPositionToOffset)(this.position, this.parseResults.tokenizerOutput.lines);
|
|
1653
|
-
const inCallArg = !!(0, parseTreeUtils_1.getCallNodeAndActiveParamIndex)(parseNode, offset, this.parseResults.tokenizerOutput.tokens);
|
|
1654
|
-
if (nodeForExpectedType) {
|
|
1655
|
-
const expectedTypeResult = this.evaluator.getExpectedType(nodeForExpectedType);
|
|
1656
|
-
if (expectedTypeResult && (0, typeUtils_1.containsLiteralType)(expectedTypeResult.type)) {
|
|
1657
|
-
this._addLiteralValuesForTargetType(expectedTypeResult.type, priorWord, priorText, postText, completionMap);
|
|
1658
|
-
if (!inCallArg) {
|
|
1659
|
-
return true;
|
|
1660
|
-
}
|
|
1661
|
-
}
|
|
1662
|
-
}
|
|
1663
|
-
// ex) a: TypedDictType = { "/* here */" } or a: TypedDictType = { A/* here */ }
|
|
1664
|
-
const nodeForKey = parentAndChild.parent;
|
|
1665
|
-
if (nodeForKey) {
|
|
1666
|
-
// If the dictionary is not yet filled in, it will appear as though it's
|
|
1667
|
-
// a set initially.
|
|
1668
|
-
let dictOrSet;
|
|
1669
|
-
if (nodeForKey.nodeType === 20 /* ParseNodeType.DictionaryKeyEntry */ &&
|
|
1670
|
-
nodeForKey.d.keyExpr === parentAndChild.child &&
|
|
1671
|
-
nodeForKey.parent?.nodeType === 18 /* ParseNodeType.Dictionary */) {
|
|
1672
|
-
dictOrSet = nodeForKey.parent;
|
|
1673
|
-
}
|
|
1674
|
-
else if (nodeForKey?.nodeType === 45 /* ParseNodeType.Set */) {
|
|
1675
|
-
dictOrSet = nodeForKey;
|
|
1676
|
-
}
|
|
1677
|
-
if (dictOrSet) {
|
|
1678
|
-
if (this._tryAddTypedDictKeysFromDictionary(dictOrSet, parseNode.nodeType === 49 /* ParseNodeType.String */ ? parseNode : undefined, priorWord, priorText, postText, completionMap)) {
|
|
1679
|
-
return true;
|
|
1680
|
-
}
|
|
1681
|
-
}
|
|
1682
|
-
}
|
|
1683
1693
|
// a: DictType = { .... }
|
|
1684
1694
|
// a[/* here */] or a['/* here */'] or a[variable/*here*/]
|
|
1695
|
+
// Check subscript/index context BEFORE assignment context to prioritize TypedDict keys
|
|
1685
1696
|
const argument = parentAndChild.parent;
|
|
1686
1697
|
if (argument.nodeType === 1 /* ParseNodeType.Argument */ && argument.parent?.nodeType === 27 /* ParseNodeType.Index */) {
|
|
1687
1698
|
const priorTextInString = parseNode.nodeType === 49 /* ParseNodeType.String */ ? priorText : '';
|
|
@@ -1719,15 +1730,62 @@ class CompletionProvider {
|
|
|
1719
1730
|
return true;
|
|
1720
1731
|
}
|
|
1721
1732
|
}
|
|
1733
|
+
// See if the type evaluator can determine the expected type for this node.
|
|
1734
|
+
// ex) a: Literal["str"] = /* here */
|
|
1735
|
+
const nodeForExpectedType = parentAndChild.parent.nodeType === 3 /* ParseNodeType.Assignment */
|
|
1736
|
+
? parentAndChild.parent.d.rightExpr === parentAndChild.child
|
|
1737
|
+
? parentAndChild.child
|
|
1738
|
+
: undefined
|
|
1739
|
+
: (0, parseNodes_1.isExpressionNode)(parentAndChild.child)
|
|
1740
|
+
? parentAndChild.child
|
|
1741
|
+
: undefined;
|
|
1742
|
+
const offset = (0, positionUtils_1.convertPositionToOffset)(this.position, this.parseResults.tokenizerOutput.lines);
|
|
1743
|
+
const inCallArg = !!(0, parseTreeUtils_1.getCallNodeAndActiveParamIndex)(parseNode, offset, this.parseResults.tokenizerOutput.tokens);
|
|
1744
|
+
if (nodeForExpectedType) {
|
|
1745
|
+
const expectedTypeResult = this.evaluator.getExpectedType(nodeForExpectedType);
|
|
1746
|
+
if (expectedTypeResult &&
|
|
1747
|
+
this._addLiteralValuesForExpectedTypes(nodeForExpectedType, expectedTypeResult, priorWord, priorText, postText, completionMap)) {
|
|
1748
|
+
if (!inCallArg) {
|
|
1749
|
+
return true;
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
// ex) a: TypedDictType = { "/* here */" } or a: TypedDictType = { A/* here */ }
|
|
1754
|
+
const nodeForKey = parentAndChild.parent;
|
|
1755
|
+
if (nodeForKey) {
|
|
1756
|
+
// If the dictionary is not yet filled in, it will appear as though it's
|
|
1757
|
+
// a set initially.
|
|
1758
|
+
let dictOrSet;
|
|
1759
|
+
if (nodeForKey.nodeType === 20 /* ParseNodeType.DictionaryKeyEntry */ &&
|
|
1760
|
+
nodeForKey.d.keyExpr === parentAndChild.child &&
|
|
1761
|
+
nodeForKey.parent?.nodeType === 18 /* ParseNodeType.Dictionary */) {
|
|
1762
|
+
dictOrSet = nodeForKey.parent;
|
|
1763
|
+
}
|
|
1764
|
+
else if (nodeForKey?.nodeType === 45 /* ParseNodeType.Set */) {
|
|
1765
|
+
dictOrSet = nodeForKey;
|
|
1766
|
+
}
|
|
1767
|
+
if (dictOrSet) {
|
|
1768
|
+
if (this._tryAddTypedDictKeysFromDictionary(dictOrSet, parseNode.nodeType === 49 /* ParseNodeType.String */ ? parseNode : undefined, priorWord, priorText, postText, completionMap)) {
|
|
1769
|
+
return true;
|
|
1770
|
+
}
|
|
1771
|
+
}
|
|
1772
|
+
}
|
|
1722
1773
|
// if c == "/* here */"
|
|
1723
1774
|
const comparison = parentAndChild.parent;
|
|
1724
1775
|
const supportedOperators = [2 /* OperatorType.Assign */, 12 /* OperatorType.Equals */, 28 /* OperatorType.NotEquals */];
|
|
1725
1776
|
if (comparison.nodeType === 7 /* ParseNodeType.BinaryOperation */ &&
|
|
1726
1777
|
supportedOperators.includes(comparison.d.operator)) {
|
|
1727
1778
|
const type = this.evaluator.getType(comparison.d.leftExpr);
|
|
1728
|
-
if (type
|
|
1729
|
-
|
|
1730
|
-
|
|
1779
|
+
if (type) {
|
|
1780
|
+
if ((0, typeUtils_1.containsLiteralType)(type)) {
|
|
1781
|
+
this._addLiteralValuesForTargetType(type, priorWord, priorText, postText, completionMap);
|
|
1782
|
+
return true;
|
|
1783
|
+
}
|
|
1784
|
+
const enumValueLiteralType = getStringLiteralValueTypeFromEnumType(this.evaluator, type);
|
|
1785
|
+
if (enumValueLiteralType) {
|
|
1786
|
+
this._addLiteralValuesForTargetType(enumValueLiteralType, priorWord, priorText, postText, completionMap);
|
|
1787
|
+
return true;
|
|
1788
|
+
}
|
|
1731
1789
|
}
|
|
1732
1790
|
}
|
|
1733
1791
|
// if c := "/* here */"
|
|
@@ -1740,35 +1798,8 @@ class CompletionProvider {
|
|
|
1740
1798
|
return true;
|
|
1741
1799
|
}
|
|
1742
1800
|
}
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
// case /* here */
|
|
1746
|
-
const caseNode = parentAndChild.parent;
|
|
1747
|
-
if (caseNode.nodeType === 64 /* ParseNodeType.Case */ &&
|
|
1748
|
-
caseNode.d.pattern.nodeType === 0 /* ParseNodeType.Error */ &&
|
|
1749
|
-
caseNode.d.pattern.d.category === 11 /* ErrorExpressionCategory.MissingPattern */ &&
|
|
1750
|
-
caseNode.d.suite === parentAndChild.child &&
|
|
1751
|
-
caseNode.parent?.nodeType === 63 /* ParseNodeType.Match */) {
|
|
1752
|
-
const type = this.evaluator.getType(caseNode.parent.d.expr);
|
|
1753
|
-
if (type && (0, typeUtils_1.containsLiteralType)(type)) {
|
|
1754
|
-
this._addLiteralValuesForTargetType(type, priorWord, priorText, postText, completionMap);
|
|
1755
|
-
return true;
|
|
1756
|
-
}
|
|
1757
|
-
}
|
|
1758
|
-
// match c:
|
|
1759
|
-
// case "/* here */"
|
|
1760
|
-
// case Sym/*here*/
|
|
1761
|
-
const patternLiteral = parentAndChild.parent;
|
|
1762
|
-
if ((patternLiteral.nodeType === 67 /* ParseNodeType.PatternLiteral */ ||
|
|
1763
|
-
patternLiteral.nodeType === 69 /* ParseNodeType.PatternCapture */) &&
|
|
1764
|
-
patternLiteral.parent?.nodeType === 66 /* ParseNodeType.PatternAs */ &&
|
|
1765
|
-
patternLiteral.parent.parent?.nodeType === 64 /* ParseNodeType.Case */ &&
|
|
1766
|
-
patternLiteral.parent.parent.parent?.nodeType === 63 /* ParseNodeType.Match */) {
|
|
1767
|
-
const type = this.evaluator.getType(patternLiteral.parent.parent.parent.d.expr);
|
|
1768
|
-
if (type && (0, typeUtils_1.containsLiteralType)(type)) {
|
|
1769
|
-
this._addLiteralValuesForTargetType(type, priorWord, priorText, postText, completionMap);
|
|
1770
|
-
return true;
|
|
1771
|
-
}
|
|
1801
|
+
if (this._tryAddMatchCaseLiteralCompletions(parentAndChild, priorWord, priorText, postText, completionMap)) {
|
|
1802
|
+
return true;
|
|
1772
1803
|
}
|
|
1773
1804
|
if (parseNode.nodeType === 49 /* ParseNodeType.String */) {
|
|
1774
1805
|
const offset = (0, positionUtils_1.convertPositionToOffset)(this.position, this.parseResults.tokenizerOutput.lines);
|
|
@@ -1777,6 +1808,33 @@ class CompletionProvider {
|
|
|
1777
1808
|
return true;
|
|
1778
1809
|
}
|
|
1779
1810
|
return false;
|
|
1811
|
+
function getStringLiteralValueTypeFromEnumType(evaluator, type) {
|
|
1812
|
+
const enumValueTypes = [];
|
|
1813
|
+
(0, typeUtils_1.doForEachSubtype)(type, (subtype) => {
|
|
1814
|
+
if (!(0, types_1.isClassInstance)(subtype) || !types_1.ClassType.isEnumClass(subtype)) {
|
|
1815
|
+
return;
|
|
1816
|
+
}
|
|
1817
|
+
const enumClassType = types_1.ClassType.cloneAsInstantiable(subtype);
|
|
1818
|
+
const enumMemberSymbols = new Map();
|
|
1819
|
+
(0, typeUtils_1.getMembersForClass)(enumClassType, enumMemberSymbols, /* includeInstanceVars */ false);
|
|
1820
|
+
enumMemberSymbols.forEach((_, name) => {
|
|
1821
|
+
const enumMemberType = (0, enums_1.transformTypeForEnumMember)(evaluator, enumClassType, name);
|
|
1822
|
+
if (!enumMemberType || !(0, types_1.isClassInstance)(enumMemberType)) {
|
|
1823
|
+
return;
|
|
1824
|
+
}
|
|
1825
|
+
const literalValue = enumMemberType.priv.literalValue;
|
|
1826
|
+
if (!(literalValue instanceof types_1.EnumLiteral)) {
|
|
1827
|
+
return;
|
|
1828
|
+
}
|
|
1829
|
+
(0, typeUtils_1.doForEachSubtype)(literalValue.itemType, (valueSubtype) => {
|
|
1830
|
+
if ((0, types_1.isClassInstance)(valueSubtype) && typeof valueSubtype.priv.literalValue === 'string') {
|
|
1831
|
+
enumValueTypes.push(valueSubtype);
|
|
1832
|
+
}
|
|
1833
|
+
});
|
|
1834
|
+
});
|
|
1835
|
+
});
|
|
1836
|
+
return enumValueTypes.length > 0 ? (0, types_1.combineTypes)(enumValueTypes) : undefined;
|
|
1837
|
+
}
|
|
1780
1838
|
function getParentSkippingStringList(node) {
|
|
1781
1839
|
if (!node.parent) {
|
|
1782
1840
|
return undefined;
|
|
@@ -1793,6 +1851,122 @@ class CompletionProvider {
|
|
|
1793
1851
|
return { parent: node.parent.parent, child: node.parent };
|
|
1794
1852
|
}
|
|
1795
1853
|
}
|
|
1854
|
+
_tryAddMatchCaseLiteralCompletions(parentAndChild, priorWord, priorText, postText, completionMap) {
|
|
1855
|
+
// For now, we only support simple cases. no complex pattern matching.
|
|
1856
|
+
// match c:
|
|
1857
|
+
// case /* here */
|
|
1858
|
+
// and
|
|
1859
|
+
// match c:
|
|
1860
|
+
// case "/* here */"
|
|
1861
|
+
// case Sym/*here*/
|
|
1862
|
+
const parent = parentAndChild.parent;
|
|
1863
|
+
let matchNode;
|
|
1864
|
+
let caseNode;
|
|
1865
|
+
if (parent.nodeType === 64 /* ParseNodeType.Case */ &&
|
|
1866
|
+
parent.d.pattern.nodeType === 0 /* ParseNodeType.Error */ &&
|
|
1867
|
+
parent.d.pattern.d.category === 11 /* ErrorExpressionCategory.MissingPattern */ &&
|
|
1868
|
+
parent.d.suite === parentAndChild.child &&
|
|
1869
|
+
parent.parent?.nodeType === 63 /* ParseNodeType.Match */) {
|
|
1870
|
+
matchNode = parent.parent;
|
|
1871
|
+
caseNode = parent;
|
|
1872
|
+
}
|
|
1873
|
+
else if ((parent.nodeType === 67 /* ParseNodeType.PatternLiteral */ || parent.nodeType === 69 /* ParseNodeType.PatternCapture */) &&
|
|
1874
|
+
parent.parent?.nodeType === 66 /* ParseNodeType.PatternAs */ &&
|
|
1875
|
+
parent.parent.parent?.nodeType === 64 /* ParseNodeType.Case */ &&
|
|
1876
|
+
parent.parent.parent.parent?.nodeType === 63 /* ParseNodeType.Match */) {
|
|
1877
|
+
matchNode = parent.parent.parent.parent;
|
|
1878
|
+
caseNode = parent.parent.parent;
|
|
1879
|
+
}
|
|
1880
|
+
else {
|
|
1881
|
+
return false;
|
|
1882
|
+
}
|
|
1883
|
+
const type = this._getFilteredMatchSubjectTypeForCaseCompletions(matchNode, caseNode);
|
|
1884
|
+
if (type && (0, typeUtils_1.containsLiteralType)(type)) {
|
|
1885
|
+
this._addLiteralValuesForTargetType(type, priorWord, priorText, postText, completionMap);
|
|
1886
|
+
return true;
|
|
1887
|
+
}
|
|
1888
|
+
return false;
|
|
1889
|
+
}
|
|
1890
|
+
_addLiteralValuesForExpectedTypes(expressionNode, expectedTypeResult, priorWord, priorText, postText, completionMap) {
|
|
1891
|
+
if (!this._canUseExpectedTypeForLiteralCompletion(expressionNode, expectedTypeResult.node)) {
|
|
1892
|
+
return false;
|
|
1893
|
+
}
|
|
1894
|
+
let addedLiteralValues = false;
|
|
1895
|
+
for (const candidateType of expectedTypeResult.candidates) {
|
|
1896
|
+
if (!(0, typeUtils_1.containsLiteralType)(candidateType)) {
|
|
1897
|
+
continue;
|
|
1898
|
+
}
|
|
1899
|
+
this._addLiteralValuesForTargetType(candidateType, priorWord, priorText, postText, completionMap);
|
|
1900
|
+
addedLiteralValues = true;
|
|
1901
|
+
}
|
|
1902
|
+
return addedLiteralValues;
|
|
1903
|
+
}
|
|
1904
|
+
_canUseExpectedTypeForLiteralCompletion(expressionNode, expectedTypeNode) {
|
|
1905
|
+
return expressionNode === expectedTypeNode;
|
|
1906
|
+
}
|
|
1907
|
+
_getFilteredMatchSubjectTypeForCaseCompletions(matchNode, currentCaseNode) {
|
|
1908
|
+
const getPriorCaseStringLiteralValues = () => {
|
|
1909
|
+
const values = new Set();
|
|
1910
|
+
const currentIndex = matchNode.d.cases.findIndex((c) => c === currentCaseNode);
|
|
1911
|
+
if (currentIndex <= 0) {
|
|
1912
|
+
return values;
|
|
1913
|
+
}
|
|
1914
|
+
for (let i = 0; i < currentIndex; i++) {
|
|
1915
|
+
const caseNode = matchNode.d.cases[i];
|
|
1916
|
+
// Be conservative: a guard means the case may not actually match.
|
|
1917
|
+
if (caseNode.d.guardExpr) {
|
|
1918
|
+
continue;
|
|
1919
|
+
}
|
|
1920
|
+
addStringLiteralValuesFromPattern(caseNode.d.pattern, values);
|
|
1921
|
+
}
|
|
1922
|
+
return values;
|
|
1923
|
+
};
|
|
1924
|
+
const addStringLiteralValuesFromPattern = (pattern, values) => {
|
|
1925
|
+
if (pattern.nodeType === 67 /* ParseNodeType.PatternLiteral */) {
|
|
1926
|
+
addStringLiteralValuesFromExpression(pattern.d.expr, values);
|
|
1927
|
+
return;
|
|
1928
|
+
}
|
|
1929
|
+
if (pattern.nodeType === 66 /* ParseNodeType.PatternAs */) {
|
|
1930
|
+
pattern.d.orPatterns.forEach((orPattern) => {
|
|
1931
|
+
addStringLiteralValuesFromPattern(orPattern, values);
|
|
1932
|
+
});
|
|
1933
|
+
}
|
|
1934
|
+
};
|
|
1935
|
+
const addStringLiteralValuesFromExpression = (expr, values) => {
|
|
1936
|
+
if (expr.nodeType === 49 /* ParseNodeType.String */) {
|
|
1937
|
+
values.add(expr.d.value);
|
|
1938
|
+
return;
|
|
1939
|
+
}
|
|
1940
|
+
if (expr.nodeType === 48 /* ParseNodeType.StringList */) {
|
|
1941
|
+
// Be conservative: only treat it as covered if all pieces are plain string literals.
|
|
1942
|
+
if (expr.d.strings.every((s) => s.nodeType === 49 /* ParseNodeType.String */)) {
|
|
1943
|
+
values.add(expr.d.strings.map((s) => s.d.value).join(''));
|
|
1944
|
+
}
|
|
1945
|
+
}
|
|
1946
|
+
};
|
|
1947
|
+
const type = this.evaluator.getType(matchNode.d.expr);
|
|
1948
|
+
if (!type || !(0, typeUtils_1.containsLiteralType)(type)) {
|
|
1949
|
+
return type;
|
|
1950
|
+
}
|
|
1951
|
+
const priorCaseLiteralValues = getPriorCaseStringLiteralValues();
|
|
1952
|
+
if (priorCaseLiteralValues.size === 0) {
|
|
1953
|
+
return type;
|
|
1954
|
+
}
|
|
1955
|
+
const remainingSubtypes = [];
|
|
1956
|
+
(0, typeUtils_1.doForEachSubtype)(type, (subtype) => {
|
|
1957
|
+
if ((0, types_1.isClassInstance)(subtype) &&
|
|
1958
|
+
(0, typeUtils_1.isLiteralType)(subtype) &&
|
|
1959
|
+
types_1.ClassType.isBuiltIn(subtype, 'str') &&
|
|
1960
|
+
typeof subtype.priv.literalValue === 'string' &&
|
|
1961
|
+
priorCaseLiteralValues.has(subtype.priv.literalValue)) {
|
|
1962
|
+
return;
|
|
1963
|
+
}
|
|
1964
|
+
remainingSubtypes.push(subtype);
|
|
1965
|
+
});
|
|
1966
|
+
// If we've filtered everything out, don't offer any redundant literal completions.
|
|
1967
|
+
// Other (non-literal) completion behaviors can still contribute suggestions.
|
|
1968
|
+
return remainingSubtypes.length > 0 ? (0, types_1.combineTypes)(remainingSubtypes) : undefined;
|
|
1969
|
+
}
|
|
1796
1970
|
_tryAddTypedDictKeys(type, existingKeys, priorWord, priorText, postText, completionMap) {
|
|
1797
1971
|
let typedDicts = [];
|
|
1798
1972
|
(0, typeUtils_1.doForEachSubtype)(type, (subtype) => {
|
|
@@ -2241,8 +2415,11 @@ class CompletionProvider {
|
|
|
2241
2415
|
completionMap.set(completionItem);
|
|
2242
2416
|
}
|
|
2243
2417
|
completions.forEach((modulePath, completionName) => {
|
|
2418
|
+
const sortCategory = completionName.startsWith('_')
|
|
2419
|
+
? SortCategory.PrivateSymbol
|
|
2420
|
+
: SortCategory.ImportModuleName;
|
|
2244
2421
|
this.addNameToCompletions(completionName, vscode_languageserver_1.CompletionItemKind.Module, '', completionMap, {
|
|
2245
|
-
sortText: this._makeSortText(
|
|
2422
|
+
sortText: this._makeSortText(sortCategory, completionName),
|
|
2246
2423
|
moduleUri: modulePath,
|
|
2247
2424
|
});
|
|
2248
2425
|
});
|