@zzzen/pyright-internal 1.1.254 → 1.1.255
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/package.json +3 -2
- package/src/analyzer/aliasDeclarationUtils.ts +169 -0
- package/src/analyzer/analysis.ts +92 -0
- package/src/analyzer/analyzerFileInfo.ts +56 -0
- package/src/analyzer/analyzerNodeInfo.ts +198 -0
- package/src/analyzer/backgroundAnalysisProgram.ts +311 -0
- package/src/analyzer/binder.ts +4081 -0
- package/src/analyzer/checker.ts +5507 -0
- package/src/analyzer/circularDependency.ts +52 -0
- package/src/analyzer/codeFlowEngine.ts +1548 -0
- package/src/analyzer/codeFlowTypes.ts +266 -0
- package/src/analyzer/codeFlowUtils.ts +436 -0
- package/src/analyzer/commentUtils.ts +174 -0
- package/src/analyzer/constraintSolver.ts +926 -0
- package/src/analyzer/constructorTransform.ts +317 -0
- package/src/analyzer/dataClasses.ts +999 -0
- package/src/analyzer/declaration.ts +252 -0
- package/src/analyzer/declarationUtils.ts +238 -0
- package/src/analyzer/docStringConversion.ts +850 -0
- package/src/analyzer/docStringUtils.ts +112 -0
- package/src/analyzer/functionTransform.ts +137 -0
- package/src/analyzer/importResolver.ts +2308 -0
- package/src/analyzer/importResult.ts +98 -0
- package/src/analyzer/importStatementUtils.ts +834 -0
- package/src/analyzer/namedTuples.ts +422 -0
- package/src/analyzer/packageTypeReport.ts +108 -0
- package/src/analyzer/packageTypeVerifier.ts +1466 -0
- package/src/analyzer/parentDirectoryCache.ts +88 -0
- package/src/analyzer/parseTreeCleaner.ts +35 -0
- package/src/analyzer/parseTreeUtils.ts +2165 -0
- package/src/analyzer/parseTreeWalker.ts +663 -0
- package/src/analyzer/patternMatching.ts +1356 -0
- package/src/analyzer/program.ts +2778 -0
- package/src/analyzer/properties.ts +534 -0
- package/src/analyzer/protocols.ts +660 -0
- package/src/analyzer/pyTypedUtils.ts +52 -0
- package/src/analyzer/pythonPathUtils.ts +201 -0
- package/src/analyzer/scope.ts +202 -0
- package/src/analyzer/scopeUtils.ts +81 -0
- package/src/analyzer/service.ts +1679 -0
- package/src/analyzer/sourceFile.ts +1401 -0
- package/src/analyzer/sourceMapper.ts +717 -0
- package/src/analyzer/staticExpressions.ts +308 -0
- package/src/analyzer/symbol.ts +249 -0
- package/src/analyzer/symbolNameUtils.ts +50 -0
- package/src/analyzer/symbolUtils.ts +49 -0
- package/src/analyzer/testWalker.ts +101 -0
- package/src/analyzer/tracePrinter.ts +264 -0
- package/src/analyzer/typeCache.ts +181 -0
- package/src/analyzer/typeDocStringUtils.ts +371 -0
- package/src/analyzer/typeEvaluator.ts +23395 -0
- package/src/analyzer/typeEvaluatorTypes.ts +452 -0
- package/src/analyzer/typeEvaluatorWithTracker.ts +161 -0
- package/src/analyzer/typeGuards.ts +1828 -0
- package/src/analyzer/typePrinter.ts +807 -0
- package/src/analyzer/typeStubWriter.ts +727 -0
- package/src/analyzer/typeUtils.ts +3126 -0
- package/src/analyzer/typeVarContext.ts +330 -0
- package/src/analyzer/typedDicts.ts +950 -0
- package/src/analyzer/types.ts +2857 -0
- package/src/backgroundAnalysis.ts +49 -0
- package/src/backgroundAnalysisBase.ts +606 -0
- package/src/backgroundThreadBase.ts +143 -0
- package/src/commands/commandController.ts +62 -0
- package/src/commands/commandResult.ts +21 -0
- package/src/commands/commands.ts +16 -0
- package/src/commands/createTypeStub.ts +56 -0
- package/src/commands/quickActionCommand.ts +40 -0
- package/src/commands/restartServer.ts +20 -0
- package/src/common/cancellationUtils.ts +71 -0
- package/src/common/chokidarFileWatcherProvider.ts +74 -0
- package/src/common/collectionUtils.ts +379 -0
- package/src/common/commandLineOptions.ts +132 -0
- package/src/common/configOptions.ts +1291 -0
- package/src/common/console.ts +201 -0
- package/src/common/core.ts +152 -0
- package/src/common/crypto.ts +60 -0
- package/src/common/debug.ts +144 -0
- package/src/common/deferred.ts +78 -0
- package/src/common/diagnostic.ts +191 -0
- package/src/common/diagnosticRules.ts +80 -0
- package/src/common/diagnosticSink.ts +150 -0
- package/src/common/editAction.ts +46 -0
- package/src/common/extensibility.ts +35 -0
- package/src/common/extensions.ts +21 -0
- package/src/common/fileBasedCancellationUtils.ts +274 -0
- package/src/common/fileSystem.ts +152 -0
- package/src/common/fullAccessHost.ts +203 -0
- package/src/common/host.ts +49 -0
- package/src/common/logTracker.ts +157 -0
- package/src/common/lspUtils.ts +18 -0
- package/src/common/memUtils.ts +36 -0
- package/src/common/pathConsts.ts +16 -0
- package/src/common/pathUtils.ts +987 -0
- package/src/common/positionUtils.ts +78 -0
- package/src/common/progressReporter.ts +53 -0
- package/src/common/pythonVersion.ts +74 -0
- package/src/common/realFileSystem.ts +433 -0
- package/src/common/stringUtils.ts +161 -0
- package/src/common/textEditUtils.ts +31 -0
- package/src/common/textRange.ts +225 -0
- package/src/common/textRangeCollection.ts +122 -0
- package/src/common/timing.ts +105 -0
- package/src/common/uriParser.ts +26 -0
- package/src/common/workspaceEditUtils.ts +100 -0
- package/src/languageServerBase.ts +1556 -0
- package/src/languageService/analyzerServiceExecutor.ts +144 -0
- package/src/languageService/autoImporter.ts +926 -0
- package/src/languageService/callHierarchyProvider.ts +476 -0
- package/src/languageService/codeActionProvider.ts +85 -0
- package/src/languageService/completionProvider.ts +3103 -0
- package/src/languageService/definitionProvider.ts +235 -0
- package/src/languageService/documentHighlightProvider.ts +61 -0
- package/src/languageService/documentSymbolCollector.ts +466 -0
- package/src/languageService/documentSymbolProvider.ts +466 -0
- package/src/languageService/hoverProvider.ts +499 -0
- package/src/languageService/importAdder.ts +437 -0
- package/src/languageService/importSorter.ts +196 -0
- package/src/languageService/indentationUtils.ts +813 -0
- package/src/languageService/quickActions.ts +113 -0
- package/src/languageService/referencesProvider.ts +316 -0
- package/src/languageService/renameModuleProvider.ts +1400 -0
- package/src/languageService/signatureHelpProvider.ts +227 -0
- package/src/languageService/tooltipUtils.ts +147 -0
- package/src/localization/localize.ts +1272 -0
- package/src/localization/package.nls.de.json +3 -0
- package/src/localization/package.nls.en-us.json +636 -0
- package/src/localization/package.nls.es.json +3 -0
- package/src/localization/package.nls.fr.json +3 -0
- package/src/localization/package.nls.ja.json +3 -0
- package/src/localization/package.nls.ru.json +3 -0
- package/src/localization/package.nls.zh-cn.json +3 -0
- package/src/localization/package.nls.zh-tw.json +3 -0
- package/src/nodeMain.ts +21 -0
- package/src/nodeServer.ts +30 -0
- package/src/parser/characterStream.ts +145 -0
- package/src/parser/characters.ts +285 -0
- package/src/parser/parseNodes.ts +2338 -0
- package/src/parser/parser.ts +4859 -0
- package/src/parser/stringTokenUtils.ts +564 -0
- package/src/parser/tokenizer.ts +1379 -0
- package/src/parser/tokenizerTypes.ts +420 -0
- package/src/parser/unicode.ts +2917 -0
- package/src/pyright.ts +824 -0
- package/src/pyrightFileSystem.ts +237 -0
- package/src/readonlyAugmentedFileSystem.ts +204 -0
- package/src/server.ts +298 -0
- package/src/tests/chainedSourceFiles.test.ts +183 -0
- package/src/tests/checker.test.ts +445 -0
- package/src/tests/collectionUtils.test.ts +178 -0
- package/src/tests/common.test.ts +117 -0
- package/src/tests/config.test.ts +291 -0
- package/src/tests/debug.test.ts +120 -0
- package/src/tests/deferred.test.ts +54 -0
- package/src/tests/diagnosticOverrides.test.ts +104 -0
- package/src/tests/docStringConversion.test.ts +823 -0
- package/src/tests/docStringUtils.test.ts +57 -0
- package/src/tests/documentSymbolCollector.test.ts +735 -0
- package/src/tests/filesystem.test.ts +215 -0
- package/src/tests/fourSlashParser.test.ts +330 -0
- package/src/tests/fourSlashRunner.test.ts +36 -0
- package/src/tests/fourslash/completions.autoimport.Lib.Found.Type.fourslash.ts +33 -0
- package/src/tests/fourslash/completions.autoimport.Lib.Found.duplication.fourslash.ts +47 -0
- package/src/tests/fourslash/completions.autoimport.Lib.NotFound.fourslash.ts +14 -0
- package/src/tests/fourslash/completions.autoimport.disabled.fourslash.ts +25 -0
- package/src/tests/fourslash/completions.autoimport.duplicates.fourslash.ts +36 -0
- package/src/tests/fourslash/completions.autoimport.fourslash.ts +29 -0
- package/src/tests/fourslash/completions.autoimport.fromImport.fourslash.ts +130 -0
- package/src/tests/fourslash/completions.autoimport.plainText.fourslash.ts +29 -0
- package/src/tests/fourslash/completions.autoimport.shadow.fourslash.ts +48 -0
- package/src/tests/fourslash/completions.autoimport.submodule.fourslash.ts +31 -0
- package/src/tests/fourslash/completions.autoimport.topLevel.fourslash.ts +57 -0
- package/src/tests/fourslash/completions.builtinDocstrings.fourslash.ts +117 -0
- package/src/tests/fourslash/completions.builtinOverride.fourslash.ts +22 -0
- package/src/tests/fourslash/completions.call.stringLiteral.fourslash.ts +55 -0
- package/src/tests/fourslash/completions.call.typedDict.fourslash.ts +247 -0
- package/src/tests/fourslash/completions.call.typedDict.list.fourslash.ts +163 -0
- package/src/tests/fourslash/completions.call.typedDict.states.fourslash.ts +135 -0
- package/src/tests/fourslash/completions.classVariable.fourslash.ts +37 -0
- package/src/tests/fourslash/completions.comment.fourslash.ts +28 -0
- package/src/tests/fourslash/completions.declNames.class.fourslash.ts +35 -0
- package/src/tests/fourslash/completions.declNames.exception.fourslash.ts +18 -0
- package/src/tests/fourslash/completions.declNames.for.fourslash.ts +30 -0
- package/src/tests/fourslash/completions.declNames.importAlias.fourslash.ts +15 -0
- package/src/tests/fourslash/completions.declNames.lambda.fourslash.ts +45 -0
- package/src/tests/fourslash/completions.declNames.method.fourslash.ts +71 -0
- package/src/tests/fourslash/completions.declNames.overload.fourslash.ts +156 -0
- package/src/tests/fourslash/completions.declNames.topLevelOverload.fourslash.ts +141 -0
- package/src/tests/fourslash/completions.dictionary.keys.complex.fourslash.ts +76 -0
- package/src/tests/fourslash/completions.dictionary.keys.expression.fourslash.ts +63 -0
- package/src/tests/fourslash/completions.dictionary.keys.literalTypes.fourslash.ts +161 -0
- package/src/tests/fourslash/completions.dictionary.keys.simple.fourslash.ts +151 -0
- package/src/tests/fourslash/completions.dictionary.keys.stringLiterals.fourslash.ts +116 -0
- package/src/tests/fourslash/completions.dictionary.keys.symbols.fourslash.ts +53 -0
- package/src/tests/fourslash/completions.enums.members.fourslash.ts +44 -0
- package/src/tests/fourslash/completions.excluded.fourslash.ts +12 -0
- package/src/tests/fourslash/completions.fourslash.ts +51 -0
- package/src/tests/fourslash/completions.fstring.fourslash.ts +33 -0
- package/src/tests/fourslash/completions.fstring.stringLiteral.fourslash.ts +96 -0
- package/src/tests/fourslash/completions.fuzzyMatching.fourslash.ts +30 -0
- package/src/tests/fourslash/completions.importDunderNames.fourslash.ts +31 -0
- package/src/tests/fourslash/completions.importSubmodule.fourslash.ts +26 -0
- package/src/tests/fourslash/completions.importsDuplicates.fourslash.ts +23 -0
- package/src/tests/fourslash/completions.inList.fourslash.ts +33 -0
- package/src/tests/fourslash/completions.included.fourslash.ts +12 -0
- package/src/tests/fourslash/completions.indexer.keys.getitem.fourslash.ts +57 -0
- package/src/tests/fourslash/completions.inherited.function.docFromStub.fourslash.ts +28 -0
- package/src/tests/fourslash/completions.inherited.overload.docFromScrWithStub.fourslash.ts +52 -0
- package/src/tests/fourslash/completions.inherited.overload.docFromStub.fourslash.ts +53 -0
- package/src/tests/fourslash/completions.inherited.property.docFromSrc.fourslash.ts +104 -0
- package/src/tests/fourslash/completions.inherited.property.docFromStub.fourslash.ts +108 -0
- package/src/tests/fourslash/completions.keywords.pythonVersion.fourslash.ts +72 -0
- package/src/tests/fourslash/completions.libCodeAndStub.fourslash.ts +79 -0
- package/src/tests/fourslash/completions.libCodeNoStub.fourslash.ts +69 -0
- package/src/tests/fourslash/completions.libStub.fourslash.ts +69 -0
- package/src/tests/fourslash/completions.literals.fourslash.ts +33 -0
- package/src/tests/fourslash/completions.localCode.fourslash.ts +74 -0
- package/src/tests/fourslash/completions.moduleContext.UnknownMemberOnInstance.fourslash.ts +17 -0
- package/src/tests/fourslash/completions.moduleContext.UnknownStaticFunctionOnClass.fourslash.ts +57 -0
- package/src/tests/fourslash/completions.moduleContext.libCodeNoStub.fourslash.ts +30 -0
- package/src/tests/fourslash/completions.overloads.fourslash.ts +40 -0
- package/src/tests/fourslash/completions.override.default.fourslash.ts +47 -0
- package/src/tests/fourslash/completions.override.default.importStub.ts +50 -0
- package/src/tests/fourslash/completions.override.default.imported.fourslash.ts +61 -0
- package/src/tests/fourslash/completions.override.default.stub.fourslash.ts +47 -0
- package/src/tests/fourslash/completions.override.fourslash.ts +47 -0
- package/src/tests/fourslash/completions.override.property.fourslash.ts +31 -0
- package/src/tests/fourslash/completions.override.property.stub.fourslash.ts +31 -0
- package/src/tests/fourslash/completions.override.staticAndClassmethod.fourslash.ts +64 -0
- package/src/tests/fourslash/completions.override.stub.fourslash.ts +47 -0
- package/src/tests/fourslash/completions.override2.fourslash.ts +71 -0
- package/src/tests/fourslash/completions.parameters.fourslash.ts +23 -0
- package/src/tests/fourslash/completions.params.fourslash.ts +24 -0
- package/src/tests/fourslash/completions.parentFolder.fourslash.ts +17 -0
- package/src/tests/fourslash/completions.parentFolders.fourslash.ts +77 -0
- package/src/tests/fourslash/completions.plainText.fourslash.ts +34 -0
- package/src/tests/fourslash/completions.private.fourslash.ts +64 -0
- package/src/tests/fourslash/completions.property.fourslash.ts +28 -0
- package/src/tests/fourslash/completions.propertyDocStrings.fourslash.ts +64 -0
- package/src/tests/fourslash/completions.self.fourslash.ts +43 -0
- package/src/tests/fourslash/completions.stringLiteral.escape.fourslash.ts +71 -0
- package/src/tests/fourslash/completions.stringLiteral.fourslash.ts +79 -0
- package/src/tests/fourslash/completions.typeAlias.fourslash.ts +29 -0
- package/src/tests/fourslash/completions.typeshed.fourslash.ts +9 -0
- package/src/tests/fourslash/completions.vardecls.fourslash.ts +40 -0
- package/src/tests/fourslash/completions.variableDocStrings.fourslash.ts +69 -0
- package/src/tests/fourslash/completions.wildcardimports.fourslash.ts +116 -0
- package/src/tests/fourslash/completions.with.fourslash.ts +26 -0
- package/src/tests/fourslash/diagnostics.missingModuleSource.fourslash.ts +69 -0
- package/src/tests/fourslash/findDefinitions.builtinClass.fourslash.ts +29 -0
- package/src/tests/fourslash/findDefinitions.classes.fourslash.ts +101 -0
- package/src/tests/fourslash/findDefinitions.definitionFilter.preferSource.fourslash.ts +29 -0
- package/src/tests/fourslash/findDefinitions.definitionFilter.preferSource.onlyStubs.ts +24 -0
- package/src/tests/fourslash/findDefinitions.definitionFilter.preferStub.fourslash.ts +29 -0
- package/src/tests/fourslash/findDefinitions.definitionFilter.preferStub.onlySource.fourslash.ts +25 -0
- package/src/tests/fourslash/findDefinitions.fields.fourslash.ts +131 -0
- package/src/tests/fourslash/findDefinitions.functions.fourslash.ts +87 -0
- package/src/tests/fourslash/findDefinitions.methods.fourslash.ts +162 -0
- package/src/tests/fourslash/findDefinitions.modules.fourslash.ts +50 -0
- package/src/tests/fourslash/findDefinitions.namespaceImport.fourslash.ts +40 -0
- package/src/tests/fourslash/findDefinitions.overloads.fourslash.ts +223 -0
- package/src/tests/fourslash/findDefinitions.parameters.fourslash.ts +162 -0
- package/src/tests/fourslash/findDefinitions.sourceAndStub.function.fourslash.ts +26 -0
- package/src/tests/fourslash/findDefinitions.sourceAndStub.innerClass.fourslash.ts +32 -0
- package/src/tests/fourslash/findDefinitions.sourceAndStub.innerClassMethod.fourslash.ts +33 -0
- package/src/tests/fourslash/findDefinitions.sourceAndStub.outerClass.fourslash.ts +28 -0
- package/src/tests/fourslash/findDefinitions.sourceAndStub.outerClassMethod.fourslash.ts +29 -0
- package/src/tests/fourslash/findDefinitions.sourceAndStub.outerClassPropertyReadOnly.fourslash.ts +31 -0
- package/src/tests/fourslash/findDefinitions.sourceAndStub.outerClassPropertyReadWrite.fourslash.ts +36 -0
- package/src/tests/fourslash/findDefinitions.sourceOnly.class.fourslash.ts +29 -0
- package/src/tests/fourslash/findDefinitions.sourceOnly.function1.fourslash.ts +28 -0
- package/src/tests/fourslash/findDefinitions.sourceOnly.function2.fourslash.ts +28 -0
- package/src/tests/fourslash/findDefinitions.sourceOnly.relativeImport1.fourslash.ts +22 -0
- package/src/tests/fourslash/findDefinitions.sourceOnly.relativeImport2.fourslash.ts +22 -0
- package/src/tests/fourslash/findDefinitions.stubOnly.fourslash.ts +61 -0
- package/src/tests/fourslash/findDefinitions.stubPackages.fourslash.ts +71 -0
- package/src/tests/fourslash/findDefinitions.typedDict.keys.fourslash.ts +99 -0
- package/src/tests/fourslash/findDefinitions.variables.fourslash.ts +88 -0
- package/src/tests/fourslash/findDefinitions.wildcardimports.fourslash.ts +117 -0
- package/src/tests/fourslash/findTypeDefinitions.builtinClass.fourslash.ts +26 -0
- package/src/tests/fourslash/findTypeDefinitions.classes.fourslash.ts +72 -0
- package/src/tests/fourslash/findTypeDefinitions.unions.fourslash.ts +26 -0
- package/src/tests/fourslash/findallreferences.classPropertyReadWrite.ts +39 -0
- package/src/tests/fourslash/findallreferences.fourslash.ts +34 -0
- package/src/tests/fourslash/findallreferences.importalias.fourslash.ts +34 -0
- package/src/tests/fourslash/findallreferences.invokedFromLibrary.fourslash.ts +52 -0
- package/src/tests/fourslash/findallreferences.module.nested.fourslash.ts +67 -0
- package/src/tests/fourslash/findallreferences.modules.duplicated.fourslash.ts +59 -0
- package/src/tests/fourslash/findallreferences.modules.fourslash.ts +46 -0
- package/src/tests/fourslash/findallreferences.modules.shadow.fourslash.ts +95 -0
- package/src/tests/fourslash/findallreferences.openFiles.fourslash.ts +37 -0
- package/src/tests/fourslash/findallreferences.parameter.fourslash.ts +24 -0
- package/src/tests/fourslash/findallreferences.sourceAndStub.class.fourslash.ts +33 -0
- package/src/tests/fourslash/findallreferences.sourceAndStub.classMethod.fourslash.ts +37 -0
- package/src/tests/fourslash/findallreferences.sourceAndStub.classPropertyReadOnly.fourslash.ts +40 -0
- package/src/tests/fourslash/findallreferences.sourceAndStub.classPropertyReadWrite.fourslash.skip.ts +48 -0
- package/src/tests/fourslash/findallreferences.sourceAndStub.function.fourslash.ts +35 -0
- package/src/tests/fourslash/findallreferences.variable.fourslash.ts +24 -0
- package/src/tests/fourslash/fourslash.ts +411 -0
- package/src/tests/fourslash/highlightreferences.attributes.fourslash.ts +31 -0
- package/src/tests/fourslash/hover.builtinDocstrings.fourslash.ts +64 -0
- package/src/tests/fourslash/hover.classNoInit.fourslash.ts +14 -0
- package/src/tests/fourslash/hover.docFromScr.stringFormat.fourslash.ts +52 -0
- package/src/tests/fourslash/hover.docFromSrc.fourslash.ts +83 -0
- package/src/tests/fourslash/hover.docFromSrc.pkg-vs-module1.fourslash.ts +26 -0
- package/src/tests/fourslash/hover.docFromSrc.pkg-vs-module2.fourslash.ts +26 -0
- package/src/tests/fourslash/hover.docFromSrc.relativeImport1.fourslash.ts +23 -0
- package/src/tests/fourslash/hover.docFromSrc.relativeImport2.fourslash.ts +22 -0
- package/src/tests/fourslash/hover.docFromSrc.relativeImport3.fourslash.ts +46 -0
- package/src/tests/fourslash/hover.docFromSrc.stubs-package.fourslash.ts +29 -0
- package/src/tests/fourslash/hover.docFromSrc.typeshed.fourslash.ts +20 -0
- package/src/tests/fourslash/hover.docstring.links.fourslash.ts +12 -0
- package/src/tests/fourslash/hover.docstring.overloads.fourslash.ts +41 -0
- package/src/tests/fourslash/hover.docstring.split.fourslash.ts +24 -0
- package/src/tests/fourslash/hover.fourslash.ts +20 -0
- package/src/tests/fourslash/hover.import.django.view.fourslash.ts +27 -0
- package/src/tests/fourslash/hover.import.fourslash.ts +11 -0
- package/src/tests/fourslash/hover.inherited.docFromSrc.fourslash.ts +63 -0
- package/src/tests/fourslash/hover.inherited.docFromSrcWithStub.fourslash.ts +54 -0
- package/src/tests/fourslash/hover.inherited.docFromStub.fourslash.ts +42 -0
- package/src/tests/fourslash/hover.inherited.overload.docFromSrcWithStub.fourslash.ts +46 -0
- package/src/tests/fourslash/hover.inherited.overload.docFromStub.fourslash.ts +47 -0
- package/src/tests/fourslash/hover.inherited.property.docFromSrcWithStub.fourslash.ts +87 -0
- package/src/tests/fourslash/hover.inherited.property.docFromStub.fourslash.ts +91 -0
- package/src/tests/fourslash/hover.init.fourslash.ts +39 -0
- package/src/tests/fourslash/hover.libCodeAndStub.fourslash.ts +52 -0
- package/src/tests/fourslash/hover.libCodeNoStub.fourslash.ts +41 -0
- package/src/tests/fourslash/hover.libStub.fourslash.ts +41 -0
- package/src/tests/fourslash/hover.optionalAliasParameter.fourslash.ts +14 -0
- package/src/tests/fourslash/hover.plainText.fourslash.ts +21 -0
- package/src/tests/fourslash/hover.typedDict.key.fourslash.ts +51 -0
- package/src/tests/fourslash/hover.variable.docString.fourslash.ts +41 -0
- package/src/tests/fourslash/hover.wildcardimports.fourslash.ts +80 -0
- package/src/tests/fourslash/import.publicSymbols.fourslash.ts +65 -0
- package/src/tests/fourslash/import.pytyped.dunderAll.fourslash.ts +77 -0
- package/src/tests/fourslash/import.pytyped.privateSymbols.fourslash.ts +65 -0
- package/src/tests/fourslash/import.pytyped.typeCheckingBasic.fourslash.ts +38 -0
- package/src/tests/fourslash/import.pytyped.typeCheckingOff.fourslash.ts +38 -0
- package/src/tests/fourslash/import.wildcard.fourslash.ts +27 -0
- package/src/tests/fourslash/importnotresolved.fourslash.ts +13 -0
- package/src/tests/fourslash/missingModuleSource.disablingInStrictMode.fourslash.ts +20 -0
- package/src/tests/fourslash/missingModuleSource.fourslash.ts +14 -0
- package/src/tests/fourslash/missingTypeStub.codeAction.fourslash.ts +33 -0
- package/src/tests/fourslash/missingTypeStub.command.multipart.fourslash.ts +48 -0
- package/src/tests/fourslash/missingTypeStub.command.singlefile.fourslash.ts +38 -0
- package/src/tests/fourslash/missingTypeStub.command.singlepart.fourslash.ts +38 -0
- package/src/tests/fourslash/missingTypeStub.fourslash.ts +20 -0
- package/src/tests/fourslash/missingTypeStub.invokeCodeAction.fourslash.ts +36 -0
- package/src/tests/fourslash/noerrors.fourslash.ts +9 -0
- package/src/tests/fourslash/orderImports1.command.fourslash.ts +20 -0
- package/src/tests/fourslash/orderImports2.command.fourslash.ts +24 -0
- package/src/tests/fourslash/rename.externallyHidden.fourslash.ts +24 -0
- package/src/tests/fourslash/rename.externallyHidden.params.fourslash.ts +24 -0
- package/src/tests/fourslash/rename.fourslash.ts +29 -0
- package/src/tests/fourslash/rename.library.fourslash.ts +29 -0
- package/src/tests/fourslash/rename.library.sourceAndStub.fourslash.ts +33 -0
- package/src/tests/fourslash/rename.multipleDecl.fourslash.ts +21 -0
- package/src/tests/fourslash/rename.sourceAndStub.fourslash.ts +37 -0
- package/src/tests/fourslash/rename.string.excluded.fourslash.ts +43 -0
- package/src/tests/fourslash/rename.string.fourslash.ts +26 -0
- package/src/tests/fourslash/signature.builtinDocstrings.fourslash.ts +63 -0
- package/src/tests/fourslash/signature.complicated.fourslash.ts +100 -0
- package/src/tests/fourslash/signature.cornercases.fourslash.ts +23 -0
- package/src/tests/fourslash/signature.docstrings.fourslash.ts +43 -0
- package/src/tests/fourslash/signature.docstrings.overloaded.fourslash.ts +50 -0
- package/src/tests/fourslash/signature.docstrings.wildcardimports.fourslash.ts +122 -0
- package/src/tests/fourslash/signature.overload.fourslash.ts +64 -0
- package/src/tests/fourslash/signature.simple.fourslash.ts +104 -0
- package/src/tests/harness/fourslash/fourSlashParser.ts +441 -0
- package/src/tests/harness/fourslash/fourSlashTypes.ts +134 -0
- package/src/tests/harness/fourslash/runner.ts +99 -0
- package/src/tests/harness/fourslash/testLanguageService.ts +142 -0
- package/src/tests/harness/fourslash/testState.Consts.ts +29 -0
- package/src/tests/harness/fourslash/testState.ts +1993 -0
- package/src/tests/harness/testAccessHost.ts +23 -0
- package/src/tests/harness/testHost.ts +177 -0
- package/src/tests/harness/utils.ts +355 -0
- package/src/tests/harness/vfs/factory.ts +199 -0
- package/src/tests/harness/vfs/filesystem.ts +1893 -0
- package/src/tests/harness/vfs/pathValidation.ts +154 -0
- package/src/tests/importAdder.test.ts +1361 -0
- package/src/tests/importResolver.test.ts +534 -0
- package/src/tests/importStatementUtils.test.ts +526 -0
- package/src/tests/indentationUtils.ptvs.test.ts +388 -0
- package/src/tests/indentationUtils.reindent.test.ts +403 -0
- package/src/tests/indentationUtils.test.ts +455 -0
- package/src/tests/ipythonMode.test.ts +365 -0
- package/src/tests/localizer.test.ts +47 -0
- package/src/tests/parseTreeUtils.test.ts +281 -0
- package/src/tests/parser.test.ts +99 -0
- package/src/tests/pathUtils.test.ts +321 -0
- package/src/tests/pyrightFileSystem.test.ts +183 -0
- package/src/tests/renameModule.folder.test.ts +261 -0
- package/src/tests/renameModule.fromImports.test.ts +952 -0
- package/src/tests/renameModule.imports.test.ts +450 -0
- package/src/tests/renameModule.misc.test.ts +765 -0
- package/src/tests/renameModule.relativePath.test.ts +277 -0
- package/src/tests/renameModuleTestUtils.ts +210 -0
- package/src/tests/samples/abstractClass1.py +51 -0
- package/src/tests/samples/abstractClass2.py +25 -0
- package/src/tests/samples/abstractClass3.py +30 -0
- package/src/tests/samples/abstractClass4.py +30 -0
- package/src/tests/samples/abstractClass5.py +42 -0
- package/src/tests/samples/abstractClass6.py +25 -0
- package/src/tests/samples/abstractClass7.py +22 -0
- package/src/tests/samples/abstractClass8.py +27 -0
- package/src/tests/samples/annotated1.py +72 -0
- package/src/tests/samples/annotatedVar1.py +22 -0
- package/src/tests/samples/annotatedVar2.py +28 -0
- package/src/tests/samples/annotatedVar3.py +54 -0
- package/src/tests/samples/annotatedVar4.py +24 -0
- package/src/tests/samples/annotatedVar5.py +37 -0
- package/src/tests/samples/annotatedVar6.py +22 -0
- package/src/tests/samples/annotatedVar7.py +13 -0
- package/src/tests/samples/annotatedVar8.py +29 -0
- package/src/tests/samples/annotations1.py +98 -0
- package/src/tests/samples/annotations2.py +33 -0
- package/src/tests/samples/annotations3.py +43 -0
- package/src/tests/samples/annotations4.py +54 -0
- package/src/tests/samples/annotations5.py +9 -0
- package/src/tests/samples/annotations6.py +29 -0
- package/src/tests/samples/assert1.py +22 -0
- package/src/tests/samples/assertType1.py +46 -0
- package/src/tests/samples/assignment1.py +58 -0
- package/src/tests/samples/assignment10.py +14 -0
- package/src/tests/samples/assignment2.py +40 -0
- package/src/tests/samples/assignment3.py +46 -0
- package/src/tests/samples/assignment4.py +20 -0
- package/src/tests/samples/assignment5.py +16 -0
- package/src/tests/samples/assignment6.py +25 -0
- package/src/tests/samples/assignment7.py +13 -0
- package/src/tests/samples/assignment8.py +40 -0
- package/src/tests/samples/assignment9.py +25 -0
- package/src/tests/samples/assignmentExpr1.py +23 -0
- package/src/tests/samples/assignmentExpr2.py +49 -0
- package/src/tests/samples/assignmentExpr3.py +27 -0
- package/src/tests/samples/assignmentExpr4.py +49 -0
- package/src/tests/samples/assignmentExpr5.py +15 -0
- package/src/tests/samples/assignmentExpr6.py +10 -0
- package/src/tests/samples/assignmentExpr7.py +13 -0
- package/src/tests/samples/assignmentExpr8.py +11 -0
- package/src/tests/samples/assignmentExpr9.py +28 -0
- package/src/tests/samples/async1.py +49 -0
- package/src/tests/samples/augmentedAssignment1.py +62 -0
- package/src/tests/samples/augmentedAssignment2.py +23 -0
- package/src/tests/samples/augmentedAssignment3.py +8 -0
- package/src/tests/samples/await1.py +23 -0
- package/src/tests/samples/await2.py +25 -0
- package/src/tests/samples/badToken1.py +6 -0
- package/src/tests/samples/builtins1.py +2 -0
- package/src/tests/samples/call1.py +93 -0
- package/src/tests/samples/call2.py +118 -0
- package/src/tests/samples/call3.py +168 -0
- package/src/tests/samples/call4.py +13 -0
- package/src/tests/samples/call5.py +95 -0
- package/src/tests/samples/call6.py +35 -0
- package/src/tests/samples/call7.py +57 -0
- package/src/tests/samples/callSite1.py +6 -0
- package/src/tests/samples/callSite2.py +12 -0
- package/src/tests/samples/callable1.py +53 -0
- package/src/tests/samples/callable2.py +58 -0
- package/src/tests/samples/callable3.py +28 -0
- package/src/tests/samples/callable4.py +32 -0
- package/src/tests/samples/callable5.py +40 -0
- package/src/tests/samples/callable6.py +83 -0
- package/src/tests/samples/callbackProtocol1.py +119 -0
- package/src/tests/samples/callbackProtocol2.py +29 -0
- package/src/tests/samples/callbackProtocol3.py +23 -0
- package/src/tests/samples/callbackProtocol4.py +73 -0
- package/src/tests/samples/callbackProtocol5.py +66 -0
- package/src/tests/samples/callbackProtocol6.py +66 -0
- package/src/tests/samples/callbackProtocol7.py +16 -0
- package/src/tests/samples/callbackProtocol8.py +16 -0
- package/src/tests/samples/capturedVariable1.py +106 -0
- package/src/tests/samples/circular1.py +16 -0
- package/src/tests/samples/circular2.py +38 -0
- package/src/tests/samples/circularBaseClass.py +17 -0
- package/src/tests/samples/classGetItem1.py +30 -0
- package/src/tests/samples/classVar1.py +41 -0
- package/src/tests/samples/classVar2.py +29 -0
- package/src/tests/samples/classVar3.py +46 -0
- package/src/tests/samples/classVar4.py +36 -0
- package/src/tests/samples/classes1.py +50 -0
- package/src/tests/samples/classes3.py +48 -0
- package/src/tests/samples/classes4.py +15 -0
- package/src/tests/samples/classes5.py +260 -0
- package/src/tests/samples/classes6.py +16 -0
- package/src/tests/samples/classes7.py +18 -0
- package/src/tests/samples/classes8.py +47 -0
- package/src/tests/samples/codeFlow1.py +65 -0
- package/src/tests/samples/codeFlow2.py +26 -0
- package/src/tests/samples/codeFlow3.py +8 -0
- package/src/tests/samples/codeFlow4.py +133 -0
- package/src/tests/samples/codeFlow5.py +10 -0
- package/src/tests/samples/codeFlow6.py +35 -0
- package/src/tests/samples/codeFlow7.py +35 -0
- package/src/tests/samples/comparison1.py +77 -0
- package/src/tests/samples/comparison2.py +37 -0
- package/src/tests/samples/complex1.py +17 -0
- package/src/tests/samples/constant1.py +40 -0
- package/src/tests/samples/constants1.py +64 -0
- package/src/tests/samples/constructor1.py +30 -0
- package/src/tests/samples/constructor10.py +19 -0
- package/src/tests/samples/constructor11.py +32 -0
- package/src/tests/samples/constructor12.py +20 -0
- package/src/tests/samples/constructor13.py +15 -0
- package/src/tests/samples/constructor2.py +180 -0
- package/src/tests/samples/constructor3.py +18 -0
- package/src/tests/samples/constructor4.py +25 -0
- package/src/tests/samples/constructor5.py +25 -0
- package/src/tests/samples/constructor6.py +70 -0
- package/src/tests/samples/constructor7.py +11 -0
- package/src/tests/samples/constructor8.py +99 -0
- package/src/tests/samples/constructor9.py +19 -0
- package/src/tests/samples/coroutines1.py +60 -0
- package/src/tests/samples/coroutines2.py +20 -0
- package/src/tests/samples/coroutines3.py +37 -0
- package/src/tests/samples/dataclass1.py +44 -0
- package/src/tests/samples/dataclass10.py +45 -0
- package/src/tests/samples/dataclass11.py +53 -0
- package/src/tests/samples/dataclass12.py +32 -0
- package/src/tests/samples/dataclass13.py +42 -0
- package/src/tests/samples/dataclass14.py +38 -0
- package/src/tests/samples/dataclass15.py +58 -0
- package/src/tests/samples/dataclass16.py +21 -0
- package/src/tests/samples/dataclass17.py +46 -0
- package/src/tests/samples/dataclass18.py +57 -0
- package/src/tests/samples/dataclass19.py +44 -0
- package/src/tests/samples/dataclass2.py +30 -0
- package/src/tests/samples/dataclass20.py +71 -0
- package/src/tests/samples/dataclass21.py +13 -0
- package/src/tests/samples/dataclass3.py +18 -0
- package/src/tests/samples/dataclass4.py +64 -0
- package/src/tests/samples/dataclass5.py +81 -0
- package/src/tests/samples/dataclass6.py +29 -0
- package/src/tests/samples/dataclass7.py +93 -0
- package/src/tests/samples/dataclass8.py +22 -0
- package/src/tests/samples/dataclass9.py +24 -0
- package/src/tests/samples/dataclassPostInit1.py +61 -0
- package/src/tests/samples/dataclassTransform1.py +71 -0
- package/src/tests/samples/dataclassTransform2.py +78 -0
- package/src/tests/samples/dataclassTransform3.py +83 -0
- package/src/tests/samples/dataclassTransform4.py +87 -0
- package/src/tests/samples/decorator1.py +20 -0
- package/src/tests/samples/decorator2.py +31 -0
- package/src/tests/samples/decorator3.py +27 -0
- package/src/tests/samples/decorator4.py +37 -0
- package/src/tests/samples/decorator5.py +29 -0
- package/src/tests/samples/decorator6.py +34 -0
- package/src/tests/samples/defaultInitializer1.py +26 -0
- package/src/tests/samples/deprecated1.py +37 -0
- package/src/tests/samples/descriptor1.py +134 -0
- package/src/tests/samples/descriptor2.py +29 -0
- package/src/tests/samples/dictionary1.py +42 -0
- package/src/tests/samples/dictionary2.py +14 -0
- package/src/tests/samples/dictionary3.py +30 -0
- package/src/tests/samples/dictionary4.py +106 -0
- package/src/tests/samples/dunderAll1.py +32 -0
- package/src/tests/samples/dunderAll2.py +16 -0
- package/src/tests/samples/dunderAll3.pyi +16 -0
- package/src/tests/samples/duplicateDeclaration1.py +115 -0
- package/src/tests/samples/duplicateDeclaration2.py +45 -0
- package/src/tests/samples/duplicateImports1.py +13 -0
- package/src/tests/samples/ellipsis1.pyi +48 -0
- package/src/tests/samples/emptyContainers1.py +89 -0
- package/src/tests/samples/enums1.py +52 -0
- package/src/tests/samples/enums2.py +15 -0
- package/src/tests/samples/enums3.py +24 -0
- package/src/tests/samples/enums4.py +23 -0
- package/src/tests/samples/enums5.py +16 -0
- package/src/tests/samples/enums6.py +33 -0
- package/src/tests/samples/enums7.py +54 -0
- package/src/tests/samples/enums8.py +14 -0
- package/src/tests/samples/expressions1.py +54 -0
- package/src/tests/samples/expressions2.py +29 -0
- package/src/tests/samples/expressions3.py +26 -0
- package/src/tests/samples/expressions4.py +23 -0
- package/src/tests/samples/expressions5.py +70 -0
- package/src/tests/samples/expressions6.py +14 -0
- package/src/tests/samples/expressions7.py +40 -0
- package/src/tests/samples/expressions8.py +26 -0
- package/src/tests/samples/expressions9.py +14 -0
- package/src/tests/samples/final1.py +14 -0
- package/src/tests/samples/final2.py +86 -0
- package/src/tests/samples/final3.py +179 -0
- package/src/tests/samples/final4.pyi +21 -0
- package/src/tests/samples/final5.py +18 -0
- package/src/tests/samples/forLoop1.py +88 -0
- package/src/tests/samples/forLoop2.py +48 -0
- package/src/tests/samples/fstring1.py +66 -0
- package/src/tests/samples/fstring2.py +12 -0
- package/src/tests/samples/fstring3.py +35 -0
- package/src/tests/samples/fstring4.py +17 -0
- package/src/tests/samples/fstring5.py +17 -0
- package/src/tests/samples/fstring6.py +14 -0
- package/src/tests/samples/function1.py +12 -0
- package/src/tests/samples/function10.py +20 -0
- package/src/tests/samples/function11.py +36 -0
- package/src/tests/samples/function2.py +7 -0
- package/src/tests/samples/function3.py +82 -0
- package/src/tests/samples/function4.py +13 -0
- package/src/tests/samples/function6.py +24 -0
- package/src/tests/samples/function7.py +13 -0
- package/src/tests/samples/function8.py +38 -0
- package/src/tests/samples/function9.py +75 -0
- package/src/tests/samples/functionAnnotation1.py +61 -0
- package/src/tests/samples/functionAnnotation2.py +26 -0
- package/src/tests/samples/functionAnnotation3.py +37 -0
- package/src/tests/samples/functionAnnotation4.py +22 -0
- package/src/tests/samples/functionMember1.py +18 -0
- package/src/tests/samples/functionMember2.py +45 -0
- package/src/tests/samples/generators1.py +122 -0
- package/src/tests/samples/generators10.py +18 -0
- package/src/tests/samples/generators11.py +27 -0
- package/src/tests/samples/generators12.py +25 -0
- package/src/tests/samples/generators13.py +65 -0
- package/src/tests/samples/generators14.py +19 -0
- package/src/tests/samples/generators15.py +26 -0
- package/src/tests/samples/generators2.py +31 -0
- package/src/tests/samples/generators3.py +42 -0
- package/src/tests/samples/generators4.py +33 -0
- package/src/tests/samples/generators5.py +24 -0
- package/src/tests/samples/generators6.py +14 -0
- package/src/tests/samples/generators7.py +18 -0
- package/src/tests/samples/generators8.py +12 -0
- package/src/tests/samples/generators9.py +19 -0
- package/src/tests/samples/generic1.py +41 -0
- package/src/tests/samples/genericTypes1.py +12 -0
- package/src/tests/samples/genericTypes10.py +38 -0
- package/src/tests/samples/genericTypes11.py +26 -0
- package/src/tests/samples/genericTypes12.py +14 -0
- package/src/tests/samples/genericTypes13.py +27 -0
- package/src/tests/samples/genericTypes14.py +22 -0
- package/src/tests/samples/genericTypes15.py +13 -0
- package/src/tests/samples/genericTypes16.py +15 -0
- package/src/tests/samples/genericTypes17.py +24 -0
- package/src/tests/samples/genericTypes18.py +135 -0
- package/src/tests/samples/genericTypes19.py +32 -0
- package/src/tests/samples/genericTypes2.py +40 -0
- package/src/tests/samples/genericTypes20.py +44 -0
- package/src/tests/samples/genericTypes21.py +29 -0
- package/src/tests/samples/genericTypes22.py +23 -0
- package/src/tests/samples/genericTypes23.py +27 -0
- package/src/tests/samples/genericTypes24.py +32 -0
- package/src/tests/samples/genericTypes25.py +37 -0
- package/src/tests/samples/genericTypes26.py +31 -0
- package/src/tests/samples/genericTypes27.py +14 -0
- package/src/tests/samples/genericTypes28.py +51 -0
- package/src/tests/samples/genericTypes29.py +24 -0
- package/src/tests/samples/genericTypes3.py +13 -0
- package/src/tests/samples/genericTypes30.py +32 -0
- package/src/tests/samples/genericTypes31.py +30 -0
- package/src/tests/samples/genericTypes32.py +25 -0
- package/src/tests/samples/genericTypes33.py +46 -0
- package/src/tests/samples/genericTypes34.py +54 -0
- package/src/tests/samples/genericTypes35.py +45 -0
- package/src/tests/samples/genericTypes36.py +35 -0
- package/src/tests/samples/genericTypes37.py +26 -0
- package/src/tests/samples/genericTypes38.py +15 -0
- package/src/tests/samples/genericTypes39.py +82 -0
- package/src/tests/samples/genericTypes4.py +37 -0
- package/src/tests/samples/genericTypes40.py +38 -0
- package/src/tests/samples/genericTypes41.py +16 -0
- package/src/tests/samples/genericTypes42.py +32 -0
- package/src/tests/samples/genericTypes43.py +24 -0
- package/src/tests/samples/genericTypes44.py +33 -0
- package/src/tests/samples/genericTypes45.py +43 -0
- package/src/tests/samples/genericTypes46.py +66 -0
- package/src/tests/samples/genericTypes47.py +39 -0
- package/src/tests/samples/genericTypes48.py +18 -0
- package/src/tests/samples/genericTypes49.py +41 -0
- package/src/tests/samples/genericTypes5.py +42 -0
- package/src/tests/samples/genericTypes50.py +62 -0
- package/src/tests/samples/genericTypes51.py +55 -0
- package/src/tests/samples/genericTypes52.py +34 -0
- package/src/tests/samples/genericTypes53.py +42 -0
- package/src/tests/samples/genericTypes54.py +31 -0
- package/src/tests/samples/genericTypes55.py +61 -0
- package/src/tests/samples/genericTypes56.py +19 -0
- package/src/tests/samples/genericTypes57.py +30 -0
- package/src/tests/samples/genericTypes58.py +52 -0
- package/src/tests/samples/genericTypes59.py +71 -0
- package/src/tests/samples/genericTypes6.py +49 -0
- package/src/tests/samples/genericTypes60.py +27 -0
- package/src/tests/samples/genericTypes61.py +34 -0
- package/src/tests/samples/genericTypes62.py +26 -0
- package/src/tests/samples/genericTypes63.py +32 -0
- package/src/tests/samples/genericTypes64.py +16 -0
- package/src/tests/samples/genericTypes65.py +15 -0
- package/src/tests/samples/genericTypes66.py +30 -0
- package/src/tests/samples/genericTypes67.py +57 -0
- package/src/tests/samples/genericTypes68.py +14 -0
- package/src/tests/samples/genericTypes69.py +45 -0
- package/src/tests/samples/genericTypes7.py +24 -0
- package/src/tests/samples/genericTypes70.py +31 -0
- package/src/tests/samples/genericTypes71.py +72 -0
- package/src/tests/samples/genericTypes72.py +24 -0
- package/src/tests/samples/genericTypes73.py +14 -0
- package/src/tests/samples/genericTypes74.py +23 -0
- package/src/tests/samples/genericTypes75.py +45 -0
- package/src/tests/samples/genericTypes76.py +107 -0
- package/src/tests/samples/genericTypes77.py +26 -0
- package/src/tests/samples/genericTypes78.py +23 -0
- package/src/tests/samples/genericTypes79.py +37 -0
- package/src/tests/samples/genericTypes8.py +26 -0
- package/src/tests/samples/genericTypes80.py +10 -0
- package/src/tests/samples/genericTypes81.py +32 -0
- package/src/tests/samples/genericTypes82.py +19 -0
- package/src/tests/samples/genericTypes83.py +28 -0
- package/src/tests/samples/genericTypes84.py +11 -0
- package/src/tests/samples/genericTypes85.py +20 -0
- package/src/tests/samples/genericTypes86.py +15 -0
- package/src/tests/samples/genericTypes87.py +21 -0
- package/src/tests/samples/genericTypes88.py +25 -0
- package/src/tests/samples/genericTypes89.py +17 -0
- package/src/tests/samples/genericTypes9.py +109 -0
- package/src/tests/samples/genericTypes90.py +12 -0
- package/src/tests/samples/genericTypes91.py +20 -0
- package/src/tests/samples/import1.py +7 -0
- package/src/tests/samples/import10.py +11 -0
- package/src/tests/samples/import11.py +11 -0
- package/src/tests/samples/import12.py +5 -0
- package/src/tests/samples/import13.py +6 -0
- package/src/tests/samples/import14.py +10 -0
- package/src/tests/samples/import2.py +27 -0
- package/src/tests/samples/import3.py +8 -0
- package/src/tests/samples/import4.py +15 -0
- package/src/tests/samples/import5.py +6 -0
- package/src/tests/samples/import6.py +17 -0
- package/src/tests/samples/import7.py +14 -0
- package/src/tests/samples/import8.py +7 -0
- package/src/tests/samples/import9.py +7 -0
- package/src/tests/samples/inconsistentConstructor1.py +23 -0
- package/src/tests/samples/inconsistentSpaceTab1.py +9 -0
- package/src/tests/samples/inconsistentSpaceTab2.py +10 -0
- package/src/tests/samples/index1.py +97 -0
- package/src/tests/samples/inferredTypes1.py +25 -0
- package/src/tests/samples/initVar1.py +23 -0
- package/src/tests/samples/initsubclass1.py +46 -0
- package/src/tests/samples/initsubclass2.py +16 -0
- package/src/tests/samples/isinstance1.py +57 -0
- package/src/tests/samples/isinstance10.py +15 -0
- package/src/tests/samples/isinstance2.py +28 -0
- package/src/tests/samples/isinstance3.py +59 -0
- package/src/tests/samples/isinstance4.py +57 -0
- package/src/tests/samples/isinstance5.py +8 -0
- package/src/tests/samples/isinstance6.py +19 -0
- package/src/tests/samples/isinstance7.py +42 -0
- package/src/tests/samples/isinstance9.py +26 -0
- package/src/tests/samples/kwargsUnpack1.py +116 -0
- package/src/tests/samples/lambda1.py +77 -0
- package/src/tests/samples/lambda2.py +26 -0
- package/src/tests/samples/lambda3.py +34 -0
- package/src/tests/samples/lambda4.py +70 -0
- package/src/tests/samples/lambda5.py +23 -0
- package/src/tests/samples/lambda6.py +15 -0
- package/src/tests/samples/lines1.py +14 -0
- package/src/tests/samples/list1.py +90 -0
- package/src/tests/samples/listComprehension1.py +45 -0
- package/src/tests/samples/listComprehension2.py +17 -0
- package/src/tests/samples/listComprehension3.py +12 -0
- package/src/tests/samples/listComprehension4.py +15 -0
- package/src/tests/samples/listComprehension5.py +20 -0
- package/src/tests/samples/listComprehension6.py +14 -0
- package/src/tests/samples/listComprehension7.py +15 -0
- package/src/tests/samples/listComprehension8.py +15 -0
- package/src/tests/samples/literalString1.py +43 -0
- package/src/tests/samples/literals1.py +48 -0
- package/src/tests/samples/literals2.py +30 -0
- package/src/tests/samples/literals3.py +40 -0
- package/src/tests/samples/literals4.py +10 -0
- package/src/tests/samples/literals5.py +28 -0
- package/src/tests/samples/literals6.py +90 -0
- package/src/tests/samples/literals7.py +38 -0
- package/src/tests/samples/loops1.py +45 -0
- package/src/tests/samples/loops10.py +11 -0
- package/src/tests/samples/loops11.py +22 -0
- package/src/tests/samples/loops12.py +18 -0
- package/src/tests/samples/loops13.py +13 -0
- package/src/tests/samples/loops14.py +22 -0
- package/src/tests/samples/loops15.py +22 -0
- package/src/tests/samples/loops16.py +322 -0
- package/src/tests/samples/loops17.py +9 -0
- package/src/tests/samples/loops18.py +23 -0
- package/src/tests/samples/loops19.py +14 -0
- package/src/tests/samples/loops2.py +25 -0
- package/src/tests/samples/loops20.py +41 -0
- package/src/tests/samples/loops21.py +18 -0
- package/src/tests/samples/loops22.py +21 -0
- package/src/tests/samples/loops23.py +16 -0
- package/src/tests/samples/loops24.py +12 -0
- package/src/tests/samples/loops25.py +45 -0
- package/src/tests/samples/loops26.py +12 -0
- package/src/tests/samples/loops3.py +11 -0
- package/src/tests/samples/loops4.py +17 -0
- package/src/tests/samples/loops5.py +14 -0
- package/src/tests/samples/loops6.py +25 -0
- package/src/tests/samples/loops7.py +14 -0
- package/src/tests/samples/loops8.py +17 -0
- package/src/tests/samples/loops9.py +25 -0
- package/src/tests/samples/match1.py +190 -0
- package/src/tests/samples/match10.py +67 -0
- package/src/tests/samples/match2.py +340 -0
- package/src/tests/samples/match3.py +364 -0
- package/src/tests/samples/match4.py +100 -0
- package/src/tests/samples/match5.py +70 -0
- package/src/tests/samples/match6.py +64 -0
- package/src/tests/samples/match7.py +65 -0
- package/src/tests/samples/match8.py +19 -0
- package/src/tests/samples/match9.py +53 -0
- package/src/tests/samples/maxParseDepth1.py +499 -0
- package/src/tests/samples/maxParseDepth2.py +16 -0
- package/src/tests/samples/memberAccess1.py +70 -0
- package/src/tests/samples/memberAccess10.py +65 -0
- package/src/tests/samples/memberAccess11.py +37 -0
- package/src/tests/samples/memberAccess12.py +36 -0
- package/src/tests/samples/memberAccess13.py +17 -0
- package/src/tests/samples/memberAccess14.py +63 -0
- package/src/tests/samples/memberAccess15.py +20 -0
- package/src/tests/samples/memberAccess16.py +12 -0
- package/src/tests/samples/memberAccess17.py +31 -0
- package/src/tests/samples/memberAccess18.py +31 -0
- package/src/tests/samples/memberAccess2.py +45 -0
- package/src/tests/samples/memberAccess3.py +64 -0
- package/src/tests/samples/memberAccess4.py +91 -0
- package/src/tests/samples/memberAccess5.py +26 -0
- package/src/tests/samples/memberAccess6.py +52 -0
- package/src/tests/samples/memberAccess7.py +36 -0
- package/src/tests/samples/memberAccess8.py +75 -0
- package/src/tests/samples/memberAccess9.py +11 -0
- package/src/tests/samples/metaclass1.py +7 -0
- package/src/tests/samples/metaclass2.py +35 -0
- package/src/tests/samples/metaclass3.py +43 -0
- package/src/tests/samples/metaclass4.py +26 -0
- package/src/tests/samples/metaclass5.py +33 -0
- package/src/tests/samples/metaclass6.py +15 -0
- package/src/tests/samples/metaclass7.py +38 -0
- package/src/tests/samples/metaclass8.py +20 -0
- package/src/tests/samples/metaclass9.py +77 -0
- package/src/tests/samples/methodOverride1.py +507 -0
- package/src/tests/samples/methodOverride2.py +74 -0
- package/src/tests/samples/methodOverride3.py +111 -0
- package/src/tests/samples/methodOverride4.py +36 -0
- package/src/tests/samples/missingSuper1.py +73 -0
- package/src/tests/samples/module1.py +13 -0
- package/src/tests/samples/module2.py +7 -0
- package/src/tests/samples/mro1.py +16 -0
- package/src/tests/samples/mro2.py +45 -0
- package/src/tests/samples/mro3.py +30 -0
- package/src/tests/samples/mro4.py +30 -0
- package/src/tests/samples/nameBindings1.py +48 -0
- package/src/tests/samples/nameBindings2.py +9 -0
- package/src/tests/samples/nameBindings3.py +36 -0
- package/src/tests/samples/nameBindings4.py +10 -0
- package/src/tests/samples/nameBindings5.py +53 -0
- package/src/tests/samples/namedTuples1.py +103 -0
- package/src/tests/samples/namedTuples2.py +56 -0
- package/src/tests/samples/namedTuples3.py +15 -0
- package/src/tests/samples/namedTuples4.py +24 -0
- package/src/tests/samples/namedTuples5.py +15 -0
- package/src/tests/samples/namedTuples6.py +31 -0
- package/src/tests/samples/namedTuples7.py +27 -0
- package/src/tests/samples/never1.py +12 -0
- package/src/tests/samples/never2.py +43 -0
- package/src/tests/samples/newType1.py +34 -0
- package/src/tests/samples/newType2.py +25 -0
- package/src/tests/samples/newType3.py +34 -0
- package/src/tests/samples/newType4.py +8 -0
- package/src/tests/samples/none1.py +29 -0
- package/src/tests/samples/none2.py +22 -0
- package/src/tests/samples/noreturn1.py +78 -0
- package/src/tests/samples/noreturn2.py +37 -0
- package/src/tests/samples/noreturn3.py +16 -0
- package/src/tests/samples/noreturn4.py +29 -0
- package/src/tests/samples/operators1.py +101 -0
- package/src/tests/samples/operators2.py +30 -0
- package/src/tests/samples/operators3.py +8 -0
- package/src/tests/samples/operators4.py +22 -0
- package/src/tests/samples/operators5.py +5 -0
- package/src/tests/samples/operators6.py +10 -0
- package/src/tests/samples/operators7.py +24 -0
- package/src/tests/samples/operators8.py +125 -0
- package/src/tests/samples/optional1.py +77 -0
- package/src/tests/samples/optional2.py +23 -0
- package/src/tests/samples/overload1.py +50 -0
- package/src/tests/samples/overload10.py +48 -0
- package/src/tests/samples/overload2.py +37 -0
- package/src/tests/samples/overload3.py +29 -0
- package/src/tests/samples/overload4.py +46 -0
- package/src/tests/samples/overload5.py +333 -0
- package/src/tests/samples/overload6.py +64 -0
- package/src/tests/samples/overload7.py +376 -0
- package/src/tests/samples/overload8.py +89 -0
- package/src/tests/samples/overload9.py +19 -0
- package/src/tests/samples/package1/__init__.py +3 -0
- package/src/tests/samples/package1/psyche/pysche.py +4 -0
- package/src/tests/samples/package1/psyche.py +4 -0
- package/src/tests/samples/package1/sub/__init__.py +5 -0
- package/src/tests/samples/package1/sub.py +4 -0
- package/src/tests/samples/package1/sub.pyi +2 -0
- package/src/tests/samples/paramInference1.py +27 -0
- package/src/tests/samples/paramNames1.py +39 -0
- package/src/tests/samples/paramSpec1.py +64 -0
- package/src/tests/samples/paramSpec10.py +57 -0
- package/src/tests/samples/paramSpec11.py +36 -0
- package/src/tests/samples/paramSpec12.py +88 -0
- package/src/tests/samples/paramSpec13.py +112 -0
- package/src/tests/samples/paramSpec14.py +30 -0
- package/src/tests/samples/paramSpec15.py +28 -0
- package/src/tests/samples/paramSpec16.py +28 -0
- package/src/tests/samples/paramSpec17.py +34 -0
- package/src/tests/samples/paramSpec18.py +43 -0
- package/src/tests/samples/paramSpec19.py +93 -0
- package/src/tests/samples/paramSpec2.py +29 -0
- package/src/tests/samples/paramSpec20.py +87 -0
- package/src/tests/samples/paramSpec21.py +58 -0
- package/src/tests/samples/paramSpec22.py +26 -0
- package/src/tests/samples/paramSpec23.py +21 -0
- package/src/tests/samples/paramSpec24.py +67 -0
- package/src/tests/samples/paramSpec25.py +36 -0
- package/src/tests/samples/paramSpec26.py +25 -0
- package/src/tests/samples/paramSpec27.py +57 -0
- package/src/tests/samples/paramSpec28.py +39 -0
- package/src/tests/samples/paramSpec29.py +37 -0
- package/src/tests/samples/paramSpec3.py +71 -0
- package/src/tests/samples/paramSpec30.py +49 -0
- package/src/tests/samples/paramSpec31.py +16 -0
- package/src/tests/samples/paramSpec32.py +57 -0
- package/src/tests/samples/paramSpec33.py +29 -0
- package/src/tests/samples/paramSpec34.py +29 -0
- package/src/tests/samples/paramSpec35.py +24 -0
- package/src/tests/samples/paramSpec36.py +43 -0
- package/src/tests/samples/paramSpec37.py +25 -0
- package/src/tests/samples/paramSpec4.py +109 -0
- package/src/tests/samples/paramSpec5.py +29 -0
- package/src/tests/samples/paramSpec6.py +17 -0
- package/src/tests/samples/paramSpec7.py +22 -0
- package/src/tests/samples/paramSpec8.py +45 -0
- package/src/tests/samples/paramSpec9.py +57 -0
- package/src/tests/samples/paramType1.py +71 -0
- package/src/tests/samples/parameters1.py +16 -0
- package/src/tests/samples/partial1.py +163 -0
- package/src/tests/samples/partial2.py +31 -0
- package/src/tests/samples/private1.py +55 -0
- package/src/tests/samples/private2.py +11 -0
- package/src/tests/samples/project1/pyrightconfig.json +5 -0
- package/src/tests/samples/project1/sample1.py +0 -0
- package/src/tests/samples/project1/subfolder1/sample2.py +0 -0
- package/src/tests/samples/project1/subfolder1/subfolder1-1/sample3.py +0 -0
- package/src/tests/samples/project2/pyrightconfig.json +3 -0
- package/src/tests/samples/project3/pyrightconfig.json +7 -0
- package/src/tests/samples/project4/presentfile.py +0 -0
- package/src/tests/samples/project4/pyrightconfig.json +11 -0
- package/src/tests/samples/project4/subfolder/presentfile2.py +0 -0
- package/src/tests/samples/project4/subfolder/presentfile3.py +0 -0
- package/src/tests/samples/project5/pyrightconfig.json +4 -0
- package/src/tests/samples/project6/app1.py +0 -0
- package/src/tests/samples/project6/app2.py +0 -0
- package/src/tests/samples/project6/projectA/foo/__init__.py +0 -0
- package/src/tests/samples/project6/projectA/foo/bar/__init__.py +0 -0
- package/src/tests/samples/project6/projectB/foo/__init__.py +0 -0
- package/src/tests/samples/project6/projectB/foo/baz/__init__.py +0 -0
- package/src/tests/samples/project_src/src/module1.py +0 -0
- package/src/tests/samples/project_src_is_pkg/src/__init__.py +0 -0
- package/src/tests/samples/project_src_is_pkg/src/module1.py +0 -0
- package/src/tests/samples/project_src_with_config_extra_paths/pyrightconfig.json +3 -0
- package/src/tests/samples/project_src_with_config_extra_paths/src/module1.py +0 -0
- package/src/tests/samples/project_src_with_config_no_extra_paths/pyrightconfig.json +2 -0
- package/src/tests/samples/project_src_with_config_no_extra_paths/src/module1.py +0 -0
- package/src/tests/samples/project_src_with_extra_paths/src/_vendored/vendored1.py +1 -0
- package/src/tests/samples/project_src_with_extra_paths/src/module1.py +2 -0
- package/src/tests/samples/project_with_pyproject_toml/pyproject.toml +7 -0
- package/src/tests/samples/project_with_venv_auto_detect_exclude/myvenv/Lib/site-packages/library1.py +0 -0
- package/src/tests/samples/project_with_venv_auto_detect_exclude/myvenv/pyvenv.cfg +0 -0
- package/src/tests/samples/project_with_venv_auto_detect_exclude/pyrightconfig.json +2 -0
- package/src/tests/samples/project_with_venv_auto_detect_exclude/sample1.py +0 -0
- package/src/tests/samples/project_with_venv_auto_detect_exclude/subfolder1/sample2.py +0 -0
- package/src/tests/samples/project_with_venv_auto_detect_exclude/subfolder1/subfolder1-1/sample3.py +0 -0
- package/src/tests/samples/project_with_venv_auto_detect_include/excluded/excluded1.py +0 -0
- package/src/tests/samples/project_with_venv_auto_detect_include/myvenv/Lib/site-packages/library1.py +0 -0
- package/src/tests/samples/project_with_venv_auto_detect_include/myvenv/pyvenv.cfg +0 -0
- package/src/tests/samples/project_with_venv_auto_detect_include/pyrightconfig.json +3 -0
- package/src/tests/samples/project_with_venv_auto_detect_include/sample1.py +0 -0
- package/src/tests/samples/project_with_venv_auto_detect_include/subfolder1/sample2.py +0 -0
- package/src/tests/samples/project_with_venv_auto_detect_include/subfolder1/subfolder1-1/sample3.py +0 -0
- package/src/tests/samples/properties1.py +64 -0
- package/src/tests/samples/properties10.py +19 -0
- package/src/tests/samples/properties11.py +45 -0
- package/src/tests/samples/properties12.py +23 -0
- package/src/tests/samples/properties13.py +15 -0
- package/src/tests/samples/properties2.py +34 -0
- package/src/tests/samples/properties3.py +93 -0
- package/src/tests/samples/properties4.py +17 -0
- package/src/tests/samples/properties5.py +29 -0
- package/src/tests/samples/properties6.py +35 -0
- package/src/tests/samples/properties7.py +30 -0
- package/src/tests/samples/properties8.py +26 -0
- package/src/tests/samples/properties9.py +24 -0
- package/src/tests/samples/protocol1.py +132 -0
- package/src/tests/samples/protocol10.py +36 -0
- package/src/tests/samples/protocol11.py +32 -0
- package/src/tests/samples/protocol12.py +12 -0
- package/src/tests/samples/protocol13.py +26 -0
- package/src/tests/samples/protocol14.py +27 -0
- package/src/tests/samples/protocol15.py +27 -0
- package/src/tests/samples/protocol16.py +22 -0
- package/src/tests/samples/protocol17.py +94 -0
- package/src/tests/samples/protocol18.py +27 -0
- package/src/tests/samples/protocol19.py +39 -0
- package/src/tests/samples/protocol2.py +38 -0
- package/src/tests/samples/protocol20.py +22 -0
- package/src/tests/samples/protocol21.py +26 -0
- package/src/tests/samples/protocol22.py +43 -0
- package/src/tests/samples/protocol23.py +41 -0
- package/src/tests/samples/protocol24.py +74 -0
- package/src/tests/samples/protocol25.py +31 -0
- package/src/tests/samples/protocol26.py +40 -0
- package/src/tests/samples/protocol27.py +76 -0
- package/src/tests/samples/protocol28.py +32 -0
- package/src/tests/samples/protocol29.py +26 -0
- package/src/tests/samples/protocol3.py +110 -0
- package/src/tests/samples/protocol30.py +30 -0
- package/src/tests/samples/protocol31.py +22 -0
- package/src/tests/samples/protocol32.py +67 -0
- package/src/tests/samples/protocol33.py +39 -0
- package/src/tests/samples/protocol34.py +21 -0
- package/src/tests/samples/protocol4.py +22 -0
- package/src/tests/samples/protocol5.py +25 -0
- package/src/tests/samples/protocol6.py +65 -0
- package/src/tests/samples/protocol7.py +24 -0
- package/src/tests/samples/protocol8.py +34 -0
- package/src/tests/samples/protocol9.py +35 -0
- package/src/tests/samples/protocolModule1.py +15 -0
- package/src/tests/samples/protocolModule2.py +83 -0
- package/src/tests/samples/protocolModule3.py +14 -0
- package/src/tests/samples/protocolModule4.py +26 -0
- package/src/tests/samples/pseudoGeneric1.py +20 -0
- package/src/tests/samples/pyrightIgnore1.py +11 -0
- package/src/tests/samples/pyrightIgnore2.py +24 -0
- package/src/tests/samples/python2.py +31 -0
- package/src/tests/samples/recursiveTypeAlias1.py +79 -0
- package/src/tests/samples/recursiveTypeAlias2.py +32 -0
- package/src/tests/samples/recursiveTypeAlias3.py +26 -0
- package/src/tests/samples/recursiveTypeAlias4.py +55 -0
- package/src/tests/samples/recursiveTypeAlias5.pyi +10 -0
- package/src/tests/samples/recursiveTypeAlias6.py +25 -0
- package/src/tests/samples/recursiveTypeAlias7.py +15 -0
- package/src/tests/samples/recursiveTypeAlias8.py +38 -0
- package/src/tests/samples/recursiveTypeAlias9.py +22 -0
- package/src/tests/samples/required1.py +47 -0
- package/src/tests/samples/required2.py +56 -0
- package/src/tests/samples/required3.py +22 -0
- package/src/tests/samples/returnTypes1.py +26 -0
- package/src/tests/samples/revealedType1.py +30 -0
- package/src/tests/samples/sample1.py +6 -0
- package/src/tests/samples/self1.py +93 -0
- package/src/tests/samples/self2.py +195 -0
- package/src/tests/samples/self3.py +9 -0
- package/src/tests/samples/self4.py +18 -0
- package/src/tests/samples/self5.py +26 -0
- package/src/tests/samples/setComprehension1.py +34 -0
- package/src/tests/samples/slots1.py +63 -0
- package/src/tests/samples/slots2.py +38 -0
- package/src/tests/samples/slots3.py +35 -0
- package/src/tests/samples/specialization1.py +78 -0
- package/src/tests/samples/specialization2.py +51 -0
- package/src/tests/samples/staticExpressions1.py +52 -0
- package/src/tests/samples/strings1.py +22 -0
- package/src/tests/samples/subscript1.py +74 -0
- package/src/tests/samples/subscript2.py +55 -0
- package/src/tests/samples/subscript3.py +135 -0
- package/src/tests/samples/suiteExpectedColon1.py +4 -0
- package/src/tests/samples/suiteExpectedColon2.py +2 -0
- package/src/tests/samples/suiteExpectedColon3.py +2 -0
- package/src/tests/samples/super1.py +57 -0
- package/src/tests/samples/super2.py +29 -0
- package/src/tests/samples/super3.py +10 -0
- package/src/tests/samples/super4.py +24 -0
- package/src/tests/samples/super5.py +28 -0
- package/src/tests/samples/super6.py +17 -0
- package/src/tests/samples/super7.py +52 -0
- package/src/tests/samples/super8.py +7 -0
- package/src/tests/samples/super9.py +36 -0
- package/src/tests/samples/test_file1.py +0 -0
- package/src/tests/samples/threePartVersion1.py +33 -0
- package/src/tests/samples/totalOrdering1.py +52 -0
- package/src/tests/samples/tryExcept1.py +39 -0
- package/src/tests/samples/tryExcept10.py +12 -0
- package/src/tests/samples/tryExcept2.py +16 -0
- package/src/tests/samples/tryExcept3.py +12 -0
- package/src/tests/samples/tryExcept4.py +28 -0
- package/src/tests/samples/tryExcept5.py +30 -0
- package/src/tests/samples/tryExcept6.py +27 -0
- package/src/tests/samples/tryExcept7.py +17 -0
- package/src/tests/samples/tryExcept8.py +69 -0
- package/src/tests/samples/tryExcept9.py +42 -0
- package/src/tests/samples/tupleUnpack1.py +63 -0
- package/src/tests/samples/tupleUnpack2.py +56 -0
- package/src/tests/samples/tupleUnpack3.py +28 -0
- package/src/tests/samples/tuples1.py +185 -0
- package/src/tests/samples/tuples10.py +30 -0
- package/src/tests/samples/tuples11.py +21 -0
- package/src/tests/samples/tuples12.py +31 -0
- package/src/tests/samples/tuples13.py +26 -0
- package/src/tests/samples/tuples15.py +16 -0
- package/src/tests/samples/tuples16.py +14 -0
- package/src/tests/samples/tuples2.py +23 -0
- package/src/tests/samples/tuples3.py +15 -0
- package/src/tests/samples/tuples4.py +21 -0
- package/src/tests/samples/tuples5.py +16 -0
- package/src/tests/samples/tuples6.py +56 -0
- package/src/tests/samples/tuples7.py +61 -0
- package/src/tests/samples/tuples8.py +98 -0
- package/src/tests/samples/tuples9.py +17 -0
- package/src/tests/samples/typeAlias1.py +37 -0
- package/src/tests/samples/typeAlias10.py +45 -0
- package/src/tests/samples/typeAlias11.py +37 -0
- package/src/tests/samples/typeAlias12.py +20 -0
- package/src/tests/samples/typeAlias13.py +53 -0
- package/src/tests/samples/typeAlias14.py +29 -0
- package/src/tests/samples/typeAlias15.py +24 -0
- package/src/tests/samples/typeAlias16.py +24 -0
- package/src/tests/samples/typeAlias2.py +26 -0
- package/src/tests/samples/typeAlias3.py +35 -0
- package/src/tests/samples/typeAlias4.py +68 -0
- package/src/tests/samples/typeAlias5.py +56 -0
- package/src/tests/samples/typeAlias6.py +51 -0
- package/src/tests/samples/typeAlias7.py +50 -0
- package/src/tests/samples/typeAlias8.py +24 -0
- package/src/tests/samples/typeAlias9.py +35 -0
- package/src/tests/samples/typeGuard1.py +68 -0
- package/src/tests/samples/typeGuard2.py +58 -0
- package/src/tests/samples/typeGuard3.py +98 -0
- package/src/tests/samples/typeIgnore1.py +10 -0
- package/src/tests/samples/typeIgnore2.py +20 -0
- package/src/tests/samples/typeIgnore3.py +22 -0
- package/src/tests/samples/typeIgnore4.py +10 -0
- package/src/tests/samples/typeIgnore5.py +7 -0
- package/src/tests/samples/typeNarrowing1.py +56 -0
- package/src/tests/samples/typeNarrowing2.py +14 -0
- package/src/tests/samples/typeNarrowing3.py +47 -0
- package/src/tests/samples/typeNarrowing4.py +24 -0
- package/src/tests/samples/typeNarrowing5.py +19 -0
- package/src/tests/samples/typeNarrowing6.py +27 -0
- package/src/tests/samples/typeNarrowing7.py +71 -0
- package/src/tests/samples/typeNarrowingAssert1.py +24 -0
- package/src/tests/samples/typeNarrowingCallable1.py +78 -0
- package/src/tests/samples/typeNarrowingEnum1.py +58 -0
- package/src/tests/samples/typeNarrowingEnum2.py +71 -0
- package/src/tests/samples/typeNarrowingFalsy1.py +50 -0
- package/src/tests/samples/typeNarrowingIn1.py +97 -0
- package/src/tests/samples/typeNarrowingIsNone1.py +56 -0
- package/src/tests/samples/typeNarrowingIsNone2.py +8 -0
- package/src/tests/samples/typeNarrowingIsNoneTuple1.py +42 -0
- package/src/tests/samples/typeNarrowingIsNoneTuple2.py +35 -0
- package/src/tests/samples/typeNarrowingIsinstance1.py +162 -0
- package/src/tests/samples/typeNarrowingIsinstance2.py +14 -0
- package/src/tests/samples/typeNarrowingIsinstance3.py +78 -0
- package/src/tests/samples/typeNarrowingIsinstance4.py +50 -0
- package/src/tests/samples/typeNarrowingIsinstance5.py +39 -0
- package/src/tests/samples/typeNarrowingIsinstance6.py +77 -0
- package/src/tests/samples/typeNarrowingIsinstance7.py +19 -0
- package/src/tests/samples/typeNarrowingIsinstance8.py +19 -0
- package/src/tests/samples/typeNarrowingLiteral1.py +35 -0
- package/src/tests/samples/typeNarrowingLiteral2.py +63 -0
- package/src/tests/samples/typeNarrowingLiteralMember1.py +140 -0
- package/src/tests/samples/typeNarrowingLocalConst1.py +136 -0
- package/src/tests/samples/typeNarrowingNoneMember1.py +102 -0
- package/src/tests/samples/typeNarrowingTuple1.py +23 -0
- package/src/tests/samples/typeNarrowingTupleLength1.py +47 -0
- package/src/tests/samples/typeNarrowingTypeIs1.py +95 -0
- package/src/tests/samples/typeNarrowingTypedDict1.py +99 -0
- package/src/tests/samples/typeNarrowingTypedDict2.py +35 -0
- package/src/tests/samples/typeNarrowingTypedDict3.py +45 -0
- package/src/tests/samples/typePromotions1.py +30 -0
- package/src/tests/samples/typeVar1.py +23 -0
- package/src/tests/samples/typeVar10.py +21 -0
- package/src/tests/samples/typeVar11.py +12 -0
- package/src/tests/samples/typeVar2.py +26 -0
- package/src/tests/samples/typeVar3.py +73 -0
- package/src/tests/samples/typeVar4.py +45 -0
- package/src/tests/samples/typeVar5.py +75 -0
- package/src/tests/samples/typeVar6.py +115 -0
- package/src/tests/samples/typeVar7.py +171 -0
- package/src/tests/samples/typeVar8.py +30 -0
- package/src/tests/samples/typeVar9.py +118 -0
- package/src/tests/samples/typedDict1.py +63 -0
- package/src/tests/samples/typedDict10.py +34 -0
- package/src/tests/samples/typedDict11.py +12 -0
- package/src/tests/samples/typedDict12.py +103 -0
- package/src/tests/samples/typedDict13.py +14 -0
- package/src/tests/samples/typedDict14.py +25 -0
- package/src/tests/samples/typedDict15.py +53 -0
- package/src/tests/samples/typedDict16.py +103 -0
- package/src/tests/samples/typedDict17.py +24 -0
- package/src/tests/samples/typedDict18.py +43 -0
- package/src/tests/samples/typedDict2.py +56 -0
- package/src/tests/samples/typedDict3.py +40 -0
- package/src/tests/samples/typedDict4.py +68 -0
- package/src/tests/samples/typedDict5.py +50 -0
- package/src/tests/samples/typedDict6.py +77 -0
- package/src/tests/samples/typedDict7.py +22 -0
- package/src/tests/samples/typedDict8.py +19 -0
- package/src/tests/samples/typedDict9.py +22 -0
- package/src/tests/samples/unbound1.py +18 -0
- package/src/tests/samples/unbound2.py +12 -0
- package/src/tests/samples/unbound3.py +13 -0
- package/src/tests/samples/unbound4.py +25 -0
- package/src/tests/samples/unicode1.py +39 -0
- package/src/tests/samples/uninitializedVariable1.py +27 -0
- package/src/tests/samples/unions1.py +79 -0
- package/src/tests/samples/unions2.py +15 -0
- package/src/tests/samples/unions3.py +48 -0
- package/src/tests/samples/unions4.py +20 -0
- package/src/tests/samples/unions5.py +43 -0
- package/src/tests/samples/unnecessaryCast1.py +13 -0
- package/src/tests/samples/unnecessaryIsInstance1.py +91 -0
- package/src/tests/samples/unnecessaryIsSubclass1.py +22 -0
- package/src/tests/samples/unpack1.py +56 -0
- package/src/tests/samples/unpack2.py +27 -0
- package/src/tests/samples/unpack3.py +16 -0
- package/src/tests/samples/unpack4.py +15 -0
- package/src/tests/samples/unreachable1.py +112 -0
- package/src/tests/samples/unusedCallResult1.py +67 -0
- package/src/tests/samples/unusedCoroutine1.py +23 -0
- package/src/tests/samples/unusedExpression1.py +34 -0
- package/src/tests/samples/unusedVariable1.py +21 -0
- package/src/tests/samples/variadicTypeVar1.py +51 -0
- package/src/tests/samples/variadicTypeVar10.py +65 -0
- package/src/tests/samples/variadicTypeVar11.py +72 -0
- package/src/tests/samples/variadicTypeVar12.py +26 -0
- package/src/tests/samples/variadicTypeVar13.py +35 -0
- package/src/tests/samples/variadicTypeVar14.py +72 -0
- package/src/tests/samples/variadicTypeVar2.py +63 -0
- package/src/tests/samples/variadicTypeVar3.py +86 -0
- package/src/tests/samples/variadicTypeVar4.py +71 -0
- package/src/tests/samples/variadicTypeVar5.py +131 -0
- package/src/tests/samples/variadicTypeVar6.py +78 -0
- package/src/tests/samples/variadicTypeVar7.py +59 -0
- package/src/tests/samples/variadicTypeVar8.py +116 -0
- package/src/tests/samples/variadicTypeVar9.py +38 -0
- package/src/tests/samples/with1.py +117 -0
- package/src/tests/samples/with2.py +63 -0
- package/src/tests/samples/with3.py +66 -0
- package/src/tests/samples/with4.py +24 -0
- package/src/tests/samples/with5.py +33 -0
- package/src/tests/samples/zipfs/bad.egg +1 -0
- package/src/tests/samples/zipfs/bad.zip +1 -0
- package/src/tests/samples/zipfs/basic.egg +0 -0
- package/src/tests/samples/zipfs/basic.zip +0 -0
- package/src/tests/samples/zipfs/corrupt.egg +0 -0
- package/src/tests/samples/zipfs/corrupt.zip +0 -0
- package/src/tests/sourceFile.test.ts +25 -0
- package/src/tests/stringUtils.test.ts +63 -0
- package/src/tests/symbolNameUtils.test.ts +77 -0
- package/src/tests/testState.test.ts +579 -0
- package/src/tests/testUtils.ts +251 -0
- package/src/tests/tokenizer.test.ts +1534 -0
- package/src/tests/typeEvaluator1.test.ts +1372 -0
- package/src/tests/typeEvaluator2.test.ts +1253 -0
- package/src/tests/typeEvaluator3.test.ts +1279 -0
- package/src/tests/typeEvaluator4.test.ts +1178 -0
- package/src/tests/updateSymbolReference.test.ts +1107 -0
- package/src/tests/zipfs.test.ts +116 -0
- package/src/workspaceMap.ts +76 -0
@@ -0,0 +1,3103 @@
|
|
1
|
+
/*
|
2
|
+
* completionProvider.ts
|
3
|
+
* Copyright (c) Microsoft Corporation.
|
4
|
+
* Licensed under the MIT license.
|
5
|
+
* Author: Eric Traut
|
6
|
+
*
|
7
|
+
* Logic that maps a position within a Python program file into
|
8
|
+
* a list of zero or more text completions that apply in the context.
|
9
|
+
*/
|
10
|
+
|
11
|
+
import {
|
12
|
+
CancellationToken,
|
13
|
+
CompletionItem,
|
14
|
+
CompletionItemKind,
|
15
|
+
CompletionList,
|
16
|
+
InsertTextFormat,
|
17
|
+
MarkupKind,
|
18
|
+
Range,
|
19
|
+
TextEdit,
|
20
|
+
} from 'vscode-languageserver';
|
21
|
+
|
22
|
+
import { ImportLookup } from '../analyzer/analyzerFileInfo';
|
23
|
+
import * as AnalyzerNodeInfo from '../analyzer/analyzerNodeInfo';
|
24
|
+
import {
|
25
|
+
Declaration,
|
26
|
+
DeclarationType,
|
27
|
+
FunctionDeclaration,
|
28
|
+
isFunctionDeclaration,
|
29
|
+
isIntrinsicDeclaration,
|
30
|
+
isVariableDeclaration,
|
31
|
+
VariableDeclaration,
|
32
|
+
} from '../analyzer/declaration';
|
33
|
+
import { isDefinedInFile } from '../analyzer/declarationUtils';
|
34
|
+
import { convertDocStringToMarkdown, convertDocStringToPlainText } from '../analyzer/docStringConversion';
|
35
|
+
import { ImportedModuleDescriptor, ImportResolver } from '../analyzer/importResolver';
|
36
|
+
import * as ParseTreeUtils from '../analyzer/parseTreeUtils';
|
37
|
+
import { getCallNodeAndActiveParameterIndex } from '../analyzer/parseTreeUtils';
|
38
|
+
import { getScopeForNode } from '../analyzer/scopeUtils';
|
39
|
+
import { isStubFile, SourceMapper } from '../analyzer/sourceMapper';
|
40
|
+
import { Symbol, SymbolTable } from '../analyzer/symbol';
|
41
|
+
import * as SymbolNameUtils from '../analyzer/symbolNameUtils';
|
42
|
+
import { getLastTypedDeclaredForSymbol } from '../analyzer/symbolUtils';
|
43
|
+
import { getTypedDictMembersForClass } from '../analyzer/typedDicts';
|
44
|
+
import {
|
45
|
+
getClassDocString,
|
46
|
+
getModuleDocString,
|
47
|
+
getPropertyDocStringInherited,
|
48
|
+
getVariableDocString,
|
49
|
+
} from '../analyzer/typeDocStringUtils';
|
50
|
+
import { CallSignatureInfo, TypeEvaluator } from '../analyzer/typeEvaluatorTypes';
|
51
|
+
import { printLiteralValue } from '../analyzer/typePrinter';
|
52
|
+
import {
|
53
|
+
ClassType,
|
54
|
+
FunctionType,
|
55
|
+
getTypeAliasInfo,
|
56
|
+
isClass,
|
57
|
+
isClassInstance,
|
58
|
+
isFunction,
|
59
|
+
isInstantiableClass,
|
60
|
+
isModule,
|
61
|
+
isNoneInstance,
|
62
|
+
isOverloadedFunction,
|
63
|
+
isUnbound,
|
64
|
+
isUnknown,
|
65
|
+
Type,
|
66
|
+
TypeBase,
|
67
|
+
UnknownType,
|
68
|
+
} from '../analyzer/types';
|
69
|
+
import {
|
70
|
+
doForEachSubtype,
|
71
|
+
getDeclaringModulesForType,
|
72
|
+
getMembersForClass,
|
73
|
+
getMembersForModule,
|
74
|
+
isLiteralType,
|
75
|
+
isLiteralTypeOrUnion,
|
76
|
+
isProperty,
|
77
|
+
lookUpObjectMember,
|
78
|
+
} from '../analyzer/typeUtils';
|
79
|
+
import { throwIfCancellationRequested } from '../common/cancellationUtils';
|
80
|
+
import { appendArray } from '../common/collectionUtils';
|
81
|
+
import { ConfigOptions, ExecutionEnvironment } from '../common/configOptions';
|
82
|
+
import * as debug from '../common/debug';
|
83
|
+
import { fail } from '../common/debug';
|
84
|
+
import { TextEditAction } from '../common/editAction';
|
85
|
+
import { fromLSPAny, toLSPAny } from '../common/lspUtils';
|
86
|
+
import { convertOffsetToPosition, convertPositionToOffset } from '../common/positionUtils';
|
87
|
+
import { PythonVersion } from '../common/pythonVersion';
|
88
|
+
import * as StringUtils from '../common/stringUtils';
|
89
|
+
import { comparePositions, Position } from '../common/textRange';
|
90
|
+
import { TextRange } from '../common/textRange';
|
91
|
+
import { TextRangeCollection } from '../common/textRangeCollection';
|
92
|
+
import { Duration } from '../common/timing';
|
93
|
+
import {
|
94
|
+
ArgumentCategory,
|
95
|
+
DecoratorNode,
|
96
|
+
DictionaryKeyEntryNode,
|
97
|
+
DictionaryNode,
|
98
|
+
ErrorExpressionCategory,
|
99
|
+
ErrorNode,
|
100
|
+
ExpressionNode,
|
101
|
+
ImportFromNode,
|
102
|
+
IndexNode,
|
103
|
+
isExpressionNode,
|
104
|
+
ModuleNameNode,
|
105
|
+
NameNode,
|
106
|
+
ParameterCategory,
|
107
|
+
ParameterNode,
|
108
|
+
ParseNode,
|
109
|
+
ParseNodeType,
|
110
|
+
SetNode,
|
111
|
+
StringNode,
|
112
|
+
} from '../parser/parseNodes';
|
113
|
+
import { ParseResults } from '../parser/parser';
|
114
|
+
import { StringToken, StringTokenFlags, Token, TokenType } from '../parser/tokenizerTypes';
|
115
|
+
import { AbbreviationInfo, AutoImporter, AutoImportResult, ModuleSymbolMap } from './autoImporter';
|
116
|
+
import { DocumentSymbolCollector } from './documentSymbolCollector';
|
117
|
+
import { IndexResults } from './documentSymbolProvider';
|
118
|
+
import {
|
119
|
+
getAutoImportText,
|
120
|
+
getFunctionDocStringFromType,
|
121
|
+
getOverloadedFunctionDocStringsFromType,
|
122
|
+
getOverloadedFunctionTooltip,
|
123
|
+
} from './tooltipUtils';
|
124
|
+
|
125
|
+
namespace Keywords {
|
126
|
+
const base: string[] = [
|
127
|
+
// Expression keywords
|
128
|
+
'True',
|
129
|
+
'False',
|
130
|
+
'None',
|
131
|
+
'and',
|
132
|
+
'or',
|
133
|
+
'not',
|
134
|
+
'is',
|
135
|
+
'lambda',
|
136
|
+
'yield',
|
137
|
+
|
138
|
+
// Statement keywords
|
139
|
+
'assert',
|
140
|
+
'break',
|
141
|
+
'class',
|
142
|
+
'continue',
|
143
|
+
'def',
|
144
|
+
'del',
|
145
|
+
'elif',
|
146
|
+
'else',
|
147
|
+
'except',
|
148
|
+
'finally',
|
149
|
+
'for',
|
150
|
+
'from',
|
151
|
+
'global',
|
152
|
+
'if',
|
153
|
+
'import',
|
154
|
+
'in',
|
155
|
+
'nonlocal',
|
156
|
+
'pass',
|
157
|
+
'raise',
|
158
|
+
'return',
|
159
|
+
'try',
|
160
|
+
'while',
|
161
|
+
'with',
|
162
|
+
];
|
163
|
+
|
164
|
+
const python3_5: string[] = [...base, 'async', 'await'];
|
165
|
+
|
166
|
+
const python3_10: string[] = [...python3_5, 'case', 'match'];
|
167
|
+
|
168
|
+
export function forVersion(version: PythonVersion): string[] {
|
169
|
+
if (version >= PythonVersion.V3_10) {
|
170
|
+
return python3_10;
|
171
|
+
}
|
172
|
+
if (version >= PythonVersion.V3_5) {
|
173
|
+
return python3_5;
|
174
|
+
}
|
175
|
+
return base;
|
176
|
+
}
|
177
|
+
}
|
178
|
+
|
179
|
+
enum SortCategory {
|
180
|
+
// The order of the following is important. We use
|
181
|
+
// this to order the completion suggestions.
|
182
|
+
|
183
|
+
// A keyword that must be entered for the syntax to be correct.
|
184
|
+
LikelyKeyword,
|
185
|
+
|
186
|
+
// A module name recently used in an import statement.
|
187
|
+
RecentImportModuleName,
|
188
|
+
|
189
|
+
// A module name used in an import statement.
|
190
|
+
ImportModuleName,
|
191
|
+
|
192
|
+
// A literal string.
|
193
|
+
LiteralValue,
|
194
|
+
|
195
|
+
// A named parameter in a call expression.
|
196
|
+
NamedParameter,
|
197
|
+
|
198
|
+
// A keyword or symbol that was recently used for completion.
|
199
|
+
RecentKeywordOrSymbol,
|
200
|
+
|
201
|
+
// An auto-import symbol that was recently used for completion.
|
202
|
+
RecentAutoImport,
|
203
|
+
|
204
|
+
// A keyword in the python syntax.
|
205
|
+
Keyword,
|
206
|
+
|
207
|
+
// An enum member.
|
208
|
+
EnumMember,
|
209
|
+
|
210
|
+
// A normal symbol.
|
211
|
+
NormalSymbol,
|
212
|
+
|
213
|
+
// A symbol that starts with _ or __ (used only when there is
|
214
|
+
// no matching filter).
|
215
|
+
PrivateSymbol,
|
216
|
+
|
217
|
+
// A symbol with a dunder name (e.g. __init__).
|
218
|
+
DunderSymbol,
|
219
|
+
|
220
|
+
// An auto-import symbol.
|
221
|
+
AutoImport,
|
222
|
+
}
|
223
|
+
|
224
|
+
// Completion items can have arbitrary data hanging off them.
|
225
|
+
// This data allows the resolve handling to disambiguate
|
226
|
+
// which item was selected.
|
227
|
+
export interface CompletionItemData {
|
228
|
+
filePath: string;
|
229
|
+
workspacePath: string;
|
230
|
+
position: Position;
|
231
|
+
autoImportText?: string | undefined;
|
232
|
+
symbolLabel?: string | undefined;
|
233
|
+
funcParensDisabled?: boolean | undefined;
|
234
|
+
}
|
235
|
+
|
236
|
+
// MemberAccessInfo attempts to gather info for unknown types
|
237
|
+
export interface MemberAccessInfo {
|
238
|
+
lastKnownModule?: string | undefined;
|
239
|
+
lastKnownMemberName?: string | undefined;
|
240
|
+
unknownMemberName?: string | undefined;
|
241
|
+
}
|
242
|
+
|
243
|
+
export interface AutoImportInfo {
|
244
|
+
indexUsed: boolean;
|
245
|
+
totalTimeInMS: number;
|
246
|
+
|
247
|
+
moduleTimeInMS: number;
|
248
|
+
indexTimeInMS: number;
|
249
|
+
importAliasTimeInMS: number;
|
250
|
+
|
251
|
+
itemCount: number;
|
252
|
+
symbolCount: number;
|
253
|
+
indexCount: number;
|
254
|
+
importAliasCount: number;
|
255
|
+
|
256
|
+
additionTimeInMS: number;
|
257
|
+
}
|
258
|
+
|
259
|
+
export interface ExtensionInfo {
|
260
|
+
correlationId: string;
|
261
|
+
selectedItemTelemetryTimeInMS: number;
|
262
|
+
itemTelemetryTimeInMS: number;
|
263
|
+
totalTimeInMS: number;
|
264
|
+
}
|
265
|
+
|
266
|
+
interface CompletionResultsBase {
|
267
|
+
memberAccessInfo?: MemberAccessInfo | undefined;
|
268
|
+
autoImportInfo?: AutoImportInfo | undefined;
|
269
|
+
extensionInfo?: ExtensionInfo | undefined;
|
270
|
+
}
|
271
|
+
export interface CompletionResultsList extends CompletionResultsBase {
|
272
|
+
completionList: CompletionList | undefined;
|
273
|
+
}
|
274
|
+
export interface CompletionResults extends CompletionResultsBase {
|
275
|
+
completionMap: CompletionMap | undefined;
|
276
|
+
}
|
277
|
+
|
278
|
+
export interface CompletionOptions {
|
279
|
+
format: MarkupKind;
|
280
|
+
snippet: boolean;
|
281
|
+
lazyEdit: boolean;
|
282
|
+
autoImport: boolean;
|
283
|
+
}
|
284
|
+
|
285
|
+
export type AbbreviationMap = Map<string, AbbreviationInfo>;
|
286
|
+
|
287
|
+
export interface AutoImportMaps {
|
288
|
+
nameMap?: AbbreviationMap | undefined;
|
289
|
+
libraryMap?: Map<string, IndexResults> | undefined;
|
290
|
+
getModuleSymbolsMap: () => ModuleSymbolMap;
|
291
|
+
}
|
292
|
+
|
293
|
+
interface RecentCompletionInfo {
|
294
|
+
label: string;
|
295
|
+
autoImportText: string;
|
296
|
+
}
|
297
|
+
|
298
|
+
interface Edits {
|
299
|
+
format?: InsertTextFormat | undefined;
|
300
|
+
textEdit?: TextEdit | undefined;
|
301
|
+
additionalTextEdits?: TextEditAction[] | undefined;
|
302
|
+
}
|
303
|
+
|
304
|
+
interface SymbolDetail {
|
305
|
+
funcParensDisabled?: boolean | undefined;
|
306
|
+
autoImportSource?: string | undefined;
|
307
|
+
autoImportAlias?: string | undefined;
|
308
|
+
boundObjectOrClass?: ClassType | undefined;
|
309
|
+
edits?: Edits | undefined;
|
310
|
+
}
|
311
|
+
|
312
|
+
interface CompletionDetail {
|
313
|
+
funcParensDisabled?: boolean | undefined;
|
314
|
+
typeDetail?: string | undefined;
|
315
|
+
documentation?: string | undefined;
|
316
|
+
autoImportText?: {
|
317
|
+
source: string;
|
318
|
+
importText: string;
|
319
|
+
};
|
320
|
+
edits?: Edits | undefined;
|
321
|
+
sortText?: string | undefined;
|
322
|
+
itemDetail?: string | undefined;
|
323
|
+
}
|
324
|
+
|
325
|
+
export const autoImportDetail = 'Auto-import';
|
326
|
+
export const dictionaryKeyDetail = 'Dictionary key';
|
327
|
+
|
328
|
+
// We'll use a somewhat-arbitrary cutoff value here to determine
|
329
|
+
// whether it's sufficiently similar.
|
330
|
+
const similarityLimit = 0.25;
|
331
|
+
|
332
|
+
// We'll remember this many completions in the MRU list.
|
333
|
+
const maxRecentCompletions = 128;
|
334
|
+
|
335
|
+
export class CompletionProvider {
|
336
|
+
private static _mostRecentCompletions: RecentCompletionInfo[] = [];
|
337
|
+
|
338
|
+
// If we're being asked to resolve a completion item, we run the
|
339
|
+
// original completion algorithm and look for this symbol.
|
340
|
+
private _itemToResolve: CompletionItem | undefined;
|
341
|
+
|
342
|
+
private _execEnv: ExecutionEnvironment;
|
343
|
+
|
344
|
+
// Indicate whether invocation is inside of string literal.
|
345
|
+
private _insideStringLiteral: StringToken | undefined = undefined;
|
346
|
+
|
347
|
+
constructor(
|
348
|
+
private _workspacePath: string,
|
349
|
+
private _parseResults: ParseResults,
|
350
|
+
private _fileContents: string,
|
351
|
+
private _importResolver: ImportResolver,
|
352
|
+
private _position: Position,
|
353
|
+
private _filePath: string,
|
354
|
+
private _configOptions: ConfigOptions,
|
355
|
+
private _importLookup: ImportLookup,
|
356
|
+
private _evaluator: TypeEvaluator,
|
357
|
+
private _options: CompletionOptions,
|
358
|
+
private _sourceMapper: SourceMapper,
|
359
|
+
private _autoImportMaps: AutoImportMaps,
|
360
|
+
private _cancellationToken: CancellationToken
|
361
|
+
) {
|
362
|
+
this._execEnv = this._configOptions.findExecEnvironment(this._filePath);
|
363
|
+
}
|
364
|
+
|
365
|
+
getCompletionsForPosition(): CompletionResults | undefined {
|
366
|
+
const offset = convertPositionToOffset(this._position, this._parseResults.tokenizerOutput.lines);
|
367
|
+
if (offset === undefined) {
|
368
|
+
return undefined;
|
369
|
+
}
|
370
|
+
|
371
|
+
const token = ParseTreeUtils.getTokenOverlapping(this._parseResults.tokenizerOutput.tokens, offset);
|
372
|
+
if (token?.type === TokenType.String) {
|
373
|
+
const stringToken = token as StringToken;
|
374
|
+
this._insideStringLiteral = TextRange.contains(stringToken, offset)
|
375
|
+
? stringToken
|
376
|
+
: stringToken.flags & StringTokenFlags.Unterminated
|
377
|
+
? stringToken
|
378
|
+
: undefined;
|
379
|
+
}
|
380
|
+
|
381
|
+
let node = ParseTreeUtils.findNodeByOffset(this._parseResults.parseTree, offset);
|
382
|
+
|
383
|
+
// See if we can get to a "better" node by backing up a few columns.
|
384
|
+
// A "better" node is defined as one that's deeper than the current
|
385
|
+
// node.
|
386
|
+
const initialNode = node;
|
387
|
+
const initialDepth = node ? ParseTreeUtils.getNodeDepth(node) : 0;
|
388
|
+
|
389
|
+
if (!initialNode || initialNode.nodeType !== ParseNodeType.Name) {
|
390
|
+
let curOffset = offset;
|
391
|
+
let sawComma = false;
|
392
|
+
|
393
|
+
while (curOffset >= 0) {
|
394
|
+
curOffset--;
|
395
|
+
|
396
|
+
// Stop scanning backward if we hit certain stop characters.
|
397
|
+
const curChar = this._fileContents.substr(curOffset, 1);
|
398
|
+
if (curChar === '(' || curChar === '\n' || curChar === '}') {
|
399
|
+
break;
|
400
|
+
}
|
401
|
+
if (curChar === ',') {
|
402
|
+
sawComma = true;
|
403
|
+
}
|
404
|
+
|
405
|
+
const curNode = ParseTreeUtils.findNodeByOffset(this._parseResults.parseTree, curOffset);
|
406
|
+
if (curNode && curNode !== initialNode) {
|
407
|
+
if (ParseTreeUtils.getNodeDepth(curNode) > initialDepth) {
|
408
|
+
node = curNode;
|
409
|
+
|
410
|
+
// If we're at the end of a list with a hanging comma, handle the
|
411
|
+
// special case of "from x import y, ".
|
412
|
+
if (sawComma && node.parent?.nodeType === ParseNodeType.ImportFromAs) {
|
413
|
+
node = node.parent;
|
414
|
+
}
|
415
|
+
}
|
416
|
+
break;
|
417
|
+
}
|
418
|
+
}
|
419
|
+
}
|
420
|
+
|
421
|
+
if (node === undefined) {
|
422
|
+
return undefined;
|
423
|
+
}
|
424
|
+
|
425
|
+
// Get the text on that line prior to the insertion point.
|
426
|
+
const lineTextRange = this._parseResults.tokenizerOutput.lines.getItemAt(this._position.line);
|
427
|
+
const textOnLine = this._fileContents.substr(lineTextRange.start, lineTextRange.length);
|
428
|
+
const priorText = textOnLine.substr(0, this._position.character);
|
429
|
+
const postText = textOnLine.substr(this._position.character);
|
430
|
+
const priorWordIndex = priorText.search(/\w+$/);
|
431
|
+
const priorWord = priorWordIndex >= 0 ? priorText.substr(priorWordIndex) : '';
|
432
|
+
|
433
|
+
// Don't offer completions if we're within a comment.
|
434
|
+
if (this._isWithinComment(offset)) {
|
435
|
+
return undefined;
|
436
|
+
}
|
437
|
+
|
438
|
+
// See if the node is part of an error node. If so, that takes
|
439
|
+
// precedence.
|
440
|
+
let errorNode: ParseNode | undefined = node;
|
441
|
+
while (errorNode) {
|
442
|
+
if (errorNode.nodeType === ParseNodeType.Error) {
|
443
|
+
break;
|
444
|
+
}
|
445
|
+
|
446
|
+
errorNode = errorNode.parent;
|
447
|
+
}
|
448
|
+
|
449
|
+
// Determine the context based on the parse node's type and
|
450
|
+
// that of its ancestors.
|
451
|
+
let curNode = errorNode || node;
|
452
|
+
while (true) {
|
453
|
+
throwIfCancellationRequested(this._cancellationToken);
|
454
|
+
|
455
|
+
if (curNode.nodeType === ParseNodeType.String) {
|
456
|
+
return this._getLiteralCompletions(curNode, priorWord, priorText, postText);
|
457
|
+
}
|
458
|
+
|
459
|
+
if (curNode.nodeType === ParseNodeType.StringList || curNode.nodeType === ParseNodeType.FormatString) {
|
460
|
+
return undefined;
|
461
|
+
}
|
462
|
+
|
463
|
+
if (curNode.nodeType === ParseNodeType.ModuleName) {
|
464
|
+
return this._getImportModuleCompletions(curNode);
|
465
|
+
}
|
466
|
+
|
467
|
+
if (curNode.nodeType === ParseNodeType.Error) {
|
468
|
+
return this._getExpressionErrorCompletions(curNode, priorWord, priorText, postText);
|
469
|
+
}
|
470
|
+
|
471
|
+
if (curNode.nodeType === ParseNodeType.MemberAccess) {
|
472
|
+
return this._getMemberAccessCompletions(curNode.leftExpression, priorWord);
|
473
|
+
}
|
474
|
+
|
475
|
+
if (curNode.nodeType === ParseNodeType.Dictionary) {
|
476
|
+
const completionMap = new CompletionMap();
|
477
|
+
if (this._addTypedDictKeys(curNode, /* stringNode */ undefined, priorText, postText, completionMap)) {
|
478
|
+
return { completionMap };
|
479
|
+
}
|
480
|
+
}
|
481
|
+
|
482
|
+
const dictionaryEntry = ParseTreeUtils.getFirstAncestorOrSelfOfKind(
|
483
|
+
curNode,
|
484
|
+
ParseNodeType.DictionaryKeyEntry
|
485
|
+
);
|
486
|
+
if (dictionaryEntry) {
|
487
|
+
if (dictionaryEntry.parent?.nodeType === ParseNodeType.Dictionary) {
|
488
|
+
const dictionaryNode = dictionaryEntry.parent;
|
489
|
+
if (dictionaryNode.trailingCommaToken && dictionaryNode.trailingCommaToken.start < offset) {
|
490
|
+
const completionMap = new CompletionMap();
|
491
|
+
if (
|
492
|
+
this._addTypedDictKeys(
|
493
|
+
dictionaryNode,
|
494
|
+
/* stringNode */ undefined,
|
495
|
+
priorText,
|
496
|
+
postText,
|
497
|
+
completionMap
|
498
|
+
)
|
499
|
+
) {
|
500
|
+
return { completionMap };
|
501
|
+
}
|
502
|
+
}
|
503
|
+
}
|
504
|
+
}
|
505
|
+
|
506
|
+
if (curNode.nodeType === ParseNodeType.Name) {
|
507
|
+
// This condition is little different than others since it does its own
|
508
|
+
// tree walk up to find context and let outer tree walk up to proceed if it can't find
|
509
|
+
// one to show completion.
|
510
|
+
const result = this._tryGetNameCompletions(curNode, offset, priorWord, priorText, postText);
|
511
|
+
if (result || result === undefined) {
|
512
|
+
return result;
|
513
|
+
}
|
514
|
+
}
|
515
|
+
|
516
|
+
if (curNode.nodeType === ParseNodeType.ImportFrom) {
|
517
|
+
return this._getImportFromCompletions(curNode, priorWord);
|
518
|
+
}
|
519
|
+
|
520
|
+
if (isExpressionNode(curNode)) {
|
521
|
+
return this._getExpressionCompletions(curNode, priorWord, priorText, postText);
|
522
|
+
}
|
523
|
+
|
524
|
+
if (curNode.nodeType === ParseNodeType.Suite) {
|
525
|
+
if (
|
526
|
+
curNode.parent &&
|
527
|
+
curNode.parent.nodeType === ParseNodeType.Except &&
|
528
|
+
!curNode.parent.name &&
|
529
|
+
curNode.parent.typeExpression &&
|
530
|
+
TextRange.getEnd(curNode.parent.typeExpression) < offset &&
|
531
|
+
offset <= curNode.parent.exceptSuite.start
|
532
|
+
) {
|
533
|
+
// except Exception as [<empty>]
|
534
|
+
return undefined;
|
535
|
+
}
|
536
|
+
|
537
|
+
if (
|
538
|
+
curNode.parent &&
|
539
|
+
curNode.parent.nodeType === ParseNodeType.Class &&
|
540
|
+
(!curNode.parent.name || !curNode.parent.name.value) &&
|
541
|
+
curNode.parent.arguments.length === 0 &&
|
542
|
+
offset <= curNode.parent.suite.start
|
543
|
+
) {
|
544
|
+
// class [<empty>]
|
545
|
+
return undefined;
|
546
|
+
}
|
547
|
+
|
548
|
+
return this._getStatementCompletions(curNode, priorWord, priorText, postText);
|
549
|
+
}
|
550
|
+
|
551
|
+
if (curNode.nodeType === ParseNodeType.Module) {
|
552
|
+
return this._getStatementCompletions(curNode, priorWord, priorText, postText);
|
553
|
+
}
|
554
|
+
|
555
|
+
if (
|
556
|
+
curNode.nodeType === ParseNodeType.Parameter &&
|
557
|
+
curNode.length === 0 &&
|
558
|
+
curNode.parent &&
|
559
|
+
curNode.parent.nodeType === ParseNodeType.Lambda
|
560
|
+
) {
|
561
|
+
// lambda [<empty>] or lambda x, [<empty>]
|
562
|
+
return undefined;
|
563
|
+
}
|
564
|
+
|
565
|
+
if (!curNode.parent) {
|
566
|
+
break;
|
567
|
+
}
|
568
|
+
|
569
|
+
curNode = curNode.parent;
|
570
|
+
}
|
571
|
+
|
572
|
+
return undefined;
|
573
|
+
}
|
574
|
+
|
575
|
+
// When the user selects a completion, this callback is invoked,
|
576
|
+
// allowing us to record what was selected. This allows us to
|
577
|
+
// build our MRU cache so we can better predict entries.
|
578
|
+
resolveCompletionItem(completionItem: CompletionItem) {
|
579
|
+
throwIfCancellationRequested(this._cancellationToken);
|
580
|
+
|
581
|
+
const completionItemData = fromLSPAny<CompletionItemData>(completionItem.data);
|
582
|
+
|
583
|
+
const label = completionItem.label;
|
584
|
+
let autoImportText = '';
|
585
|
+
if (completionItemData.autoImportText) {
|
586
|
+
autoImportText = completionItemData.autoImportText;
|
587
|
+
}
|
588
|
+
|
589
|
+
const curIndex = CompletionProvider._mostRecentCompletions.findIndex(
|
590
|
+
(item) => item.label === label && item.autoImportText === autoImportText
|
591
|
+
);
|
592
|
+
|
593
|
+
if (curIndex > 0) {
|
594
|
+
// If there's an existing entry with the same name that's not at the
|
595
|
+
// beginning of the array, remove it.
|
596
|
+
CompletionProvider._mostRecentCompletions = CompletionProvider._mostRecentCompletions.splice(curIndex, 1);
|
597
|
+
}
|
598
|
+
|
599
|
+
if (curIndex !== 0) {
|
600
|
+
// Add to the start of the array.
|
601
|
+
CompletionProvider._mostRecentCompletions.unshift({ label, autoImportText });
|
602
|
+
}
|
603
|
+
|
604
|
+
if (CompletionProvider._mostRecentCompletions.length > maxRecentCompletions) {
|
605
|
+
// Prevent the MRU list from growing indefinitely.
|
606
|
+
CompletionProvider._mostRecentCompletions.pop();
|
607
|
+
}
|
608
|
+
|
609
|
+
if (completionItemData.symbolLabel) {
|
610
|
+
this._itemToResolve = completionItem;
|
611
|
+
|
612
|
+
if (!completionItemData.autoImportText) {
|
613
|
+
// Rerun the completion lookup. It will fill in additional information
|
614
|
+
// about the item to be resolved. We'll ignore the rest of the returned
|
615
|
+
// list. This is a bit wasteful, but all of that information should be
|
616
|
+
// cached, so it's not as bad as it might seem.
|
617
|
+
this.getCompletionsForPosition();
|
618
|
+
} else if (!completionItem.additionalTextEdits) {
|
619
|
+
const completionMap = new CompletionMap();
|
620
|
+
const completionResults = { completionMap };
|
621
|
+
|
622
|
+
this._addAutoImportCompletions(
|
623
|
+
completionItemData.symbolLabel,
|
624
|
+
/* similarityLimit */ 1,
|
625
|
+
/* lazyEdit */ false,
|
626
|
+
completionResults
|
627
|
+
);
|
628
|
+
}
|
629
|
+
}
|
630
|
+
}
|
631
|
+
|
632
|
+
// This method will return false if it wants
|
633
|
+
// caller to walk up the tree. it will return
|
634
|
+
// CompletionResults or undefined if it wants caller
|
635
|
+
// to return.
|
636
|
+
private _tryGetNameCompletions(
|
637
|
+
curNode: NameNode,
|
638
|
+
offset: number,
|
639
|
+
priorWord: string,
|
640
|
+
priorText: string,
|
641
|
+
postText: string
|
642
|
+
): false | CompletionResults | undefined {
|
643
|
+
if (!curNode.parent) {
|
644
|
+
return false;
|
645
|
+
}
|
646
|
+
|
647
|
+
if (curNode.parent.nodeType === ParseNodeType.ImportAs && curNode.parent.alias === curNode) {
|
648
|
+
// Are we within a "import Y as [Z]"?
|
649
|
+
return undefined;
|
650
|
+
}
|
651
|
+
|
652
|
+
if (curNode.parent.nodeType === ParseNodeType.ModuleName) {
|
653
|
+
// Are we within a "import Y as [<empty>]"?
|
654
|
+
if (
|
655
|
+
curNode.parent.parent &&
|
656
|
+
curNode.parent.parent.nodeType === ParseNodeType.ImportAs &&
|
657
|
+
!curNode.parent.parent.alias &&
|
658
|
+
TextRange.getEnd(curNode.parent.parent) < offset
|
659
|
+
) {
|
660
|
+
return undefined;
|
661
|
+
}
|
662
|
+
|
663
|
+
// Are we within a "from X import Y as Z" statement and
|
664
|
+
// more specifically within the "Y"?
|
665
|
+
return this._getImportModuleCompletions(curNode.parent);
|
666
|
+
}
|
667
|
+
|
668
|
+
if (curNode.parent.nodeType === ParseNodeType.ImportFromAs) {
|
669
|
+
if (curNode.parent.alias === curNode) {
|
670
|
+
// Are we within a "from X import Y as [Z]"?
|
671
|
+
return undefined;
|
672
|
+
}
|
673
|
+
|
674
|
+
const parentNode = curNode.parent.parent;
|
675
|
+
if (parentNode && parentNode.nodeType === ParseNodeType.ImportFrom) {
|
676
|
+
// Are we within a "from X import Y as [<empty>]"?
|
677
|
+
if (!curNode.parent.alias && TextRange.getEnd(curNode.parent) < offset) {
|
678
|
+
return undefined;
|
679
|
+
}
|
680
|
+
|
681
|
+
if (curNode.parent.name === curNode) {
|
682
|
+
return this._getImportFromCompletions(parentNode, priorWord);
|
683
|
+
}
|
684
|
+
|
685
|
+
return this._getImportFromCompletions(parentNode, '');
|
686
|
+
}
|
687
|
+
|
688
|
+
return false;
|
689
|
+
}
|
690
|
+
|
691
|
+
if (curNode.parent.nodeType === ParseNodeType.MemberAccess && curNode === curNode.parent.memberName) {
|
692
|
+
return this._getMemberAccessCompletions(curNode.parent.leftExpression, priorWord);
|
693
|
+
}
|
694
|
+
|
695
|
+
if (curNode.parent.nodeType === ParseNodeType.Except && curNode === curNode.parent.name) {
|
696
|
+
return undefined;
|
697
|
+
}
|
698
|
+
|
699
|
+
if (curNode.parent.nodeType === ParseNodeType.Function && curNode === curNode.parent.name) {
|
700
|
+
if (curNode.parent.decorators?.some((d) => this._isOverload(d))) {
|
701
|
+
return this._getMethodOverloadsCompletions(priorWord, curNode);
|
702
|
+
}
|
703
|
+
|
704
|
+
return undefined;
|
705
|
+
}
|
706
|
+
|
707
|
+
if (curNode.parent.nodeType === ParseNodeType.Parameter && curNode === curNode.parent.name) {
|
708
|
+
return undefined;
|
709
|
+
}
|
710
|
+
|
711
|
+
if (curNode.parent.nodeType === ParseNodeType.Class && curNode === curNode.parent.name) {
|
712
|
+
return undefined;
|
713
|
+
}
|
714
|
+
|
715
|
+
if (
|
716
|
+
curNode.parent.nodeType === ParseNodeType.For &&
|
717
|
+
TextRange.contains(curNode.parent.targetExpression, curNode.start)
|
718
|
+
) {
|
719
|
+
return undefined;
|
720
|
+
}
|
721
|
+
|
722
|
+
if (
|
723
|
+
curNode.parent.nodeType === ParseNodeType.ListComprehensionFor &&
|
724
|
+
TextRange.contains(curNode.parent.targetExpression, curNode.start)
|
725
|
+
) {
|
726
|
+
return undefined;
|
727
|
+
}
|
728
|
+
|
729
|
+
// For assignments that implicitly declare variables, remove itself (var decl) from completion.
|
730
|
+
if (
|
731
|
+
curNode.parent.nodeType === ParseNodeType.Assignment ||
|
732
|
+
curNode.parent.nodeType === ParseNodeType.AssignmentExpression
|
733
|
+
) {
|
734
|
+
const leftNode =
|
735
|
+
curNode.parent.nodeType === ParseNodeType.AssignmentExpression
|
736
|
+
? curNode.parent.name
|
737
|
+
: curNode.parent.leftExpression;
|
738
|
+
|
739
|
+
if (leftNode !== curNode || priorWord.length === 0) {
|
740
|
+
return false;
|
741
|
+
}
|
742
|
+
|
743
|
+
const decls = this._evaluator.getDeclarationsForNameNode(curNode);
|
744
|
+
if (decls?.length !== 1 || !isVariableDeclaration(decls[0]) || decls[0].node !== curNode) {
|
745
|
+
return false;
|
746
|
+
}
|
747
|
+
|
748
|
+
const completionList = this._getExpressionCompletions(curNode, priorWord, priorText, postText);
|
749
|
+
if (completionList?.completionMap) {
|
750
|
+
completionList.completionMap.delete(curNode.value);
|
751
|
+
}
|
752
|
+
|
753
|
+
return completionList;
|
754
|
+
}
|
755
|
+
|
756
|
+
// Defining class variables.
|
757
|
+
// ex) class A:
|
758
|
+
// variable = 1
|
759
|
+
if (
|
760
|
+
curNode.parent.nodeType === ParseNodeType.StatementList &&
|
761
|
+
curNode.parent.parent?.nodeType === ParseNodeType.Suite &&
|
762
|
+
curNode.parent.parent.parent?.nodeType === ParseNodeType.Class
|
763
|
+
) {
|
764
|
+
const completionList = this._getClassVariableCompletions(priorWord, curNode);
|
765
|
+
if (completionList) {
|
766
|
+
return completionList;
|
767
|
+
}
|
768
|
+
}
|
769
|
+
|
770
|
+
return false;
|
771
|
+
}
|
772
|
+
|
773
|
+
private _isWithinComment(offset: number): boolean {
|
774
|
+
const token = getTokenAfter(offset, this._parseResults.tokenizerOutput.tokens);
|
775
|
+
if (!token) {
|
776
|
+
// If we're in the middle of a token, we're not in a comment.
|
777
|
+
return false;
|
778
|
+
}
|
779
|
+
|
780
|
+
return token.comments?.some((c) => TextRange.overlaps(c, offset)) ?? false;
|
781
|
+
|
782
|
+
function getTokenAfter(offset: number, tokens: TextRangeCollection<Token>) {
|
783
|
+
const tokenIndex = tokens.getItemAtPosition(offset);
|
784
|
+
if (tokenIndex < 0) {
|
785
|
+
return undefined;
|
786
|
+
}
|
787
|
+
|
788
|
+
let token = tokens.getItemAt(tokenIndex);
|
789
|
+
// If we're in the middle of a token, we can't be within a comment.
|
790
|
+
if (offset > token.start && offset < token.start + token.length) {
|
791
|
+
return undefined;
|
792
|
+
}
|
793
|
+
|
794
|
+
// Multiple zero length tokens can occupy same position.
|
795
|
+
// But comment is associated with the first one. loop
|
796
|
+
// backward to find the first token if position is same.
|
797
|
+
for (let i = tokenIndex - 1; i >= 0; i--) {
|
798
|
+
const prevToken = tokens.getItemAt(i);
|
799
|
+
if (token.start !== prevToken.start) {
|
800
|
+
break;
|
801
|
+
}
|
802
|
+
|
803
|
+
token = prevToken;
|
804
|
+
}
|
805
|
+
|
806
|
+
if (offset <= token.start) {
|
807
|
+
return token;
|
808
|
+
}
|
809
|
+
|
810
|
+
// If offset > token.start, tokenIndex + 1 < tokens.length
|
811
|
+
// should be always true.
|
812
|
+
debug.assert(tokenIndex + 1 < tokens.length);
|
813
|
+
return tokens.getItemAt(tokenIndex + 1);
|
814
|
+
}
|
815
|
+
}
|
816
|
+
|
817
|
+
private _getExpressionErrorCompletions(
|
818
|
+
node: ErrorNode,
|
819
|
+
priorWord: string,
|
820
|
+
priorText: string,
|
821
|
+
postText: string
|
822
|
+
): CompletionResults | undefined {
|
823
|
+
// Is the error due to a missing member access name? If so,
|
824
|
+
// we can evaluate the left side of the member access expression
|
825
|
+
// to determine its type and offer suggestions based on it.
|
826
|
+
switch (node.category) {
|
827
|
+
case ErrorExpressionCategory.MissingIn: {
|
828
|
+
return this._createSingleKeywordCompletion('in');
|
829
|
+
}
|
830
|
+
|
831
|
+
case ErrorExpressionCategory.MissingElse: {
|
832
|
+
return this._createSingleKeywordCompletion('else');
|
833
|
+
}
|
834
|
+
|
835
|
+
case ErrorExpressionCategory.MissingExpression:
|
836
|
+
case ErrorExpressionCategory.MissingDecoratorCallName: {
|
837
|
+
return this._getExpressionCompletions(node, priorWord, priorText, postText);
|
838
|
+
}
|
839
|
+
|
840
|
+
case ErrorExpressionCategory.MissingIndexOrSlice: {
|
841
|
+
let completionResults = this._getLiteralCompletions(node, priorWord, priorText, postText);
|
842
|
+
|
843
|
+
if (!completionResults || !completionResults.completionMap) {
|
844
|
+
completionResults = this._getExpressionCompletions(node, priorWord, priorText, postText);
|
845
|
+
}
|
846
|
+
|
847
|
+
return completionResults;
|
848
|
+
}
|
849
|
+
|
850
|
+
case ErrorExpressionCategory.MissingMemberAccessName: {
|
851
|
+
if (node.child && isExpressionNode(node.child)) {
|
852
|
+
return this._getMemberAccessCompletions(node.child, priorWord);
|
853
|
+
}
|
854
|
+
break;
|
855
|
+
}
|
856
|
+
|
857
|
+
case ErrorExpressionCategory.MissingFunctionParameterList: {
|
858
|
+
if (node.child && node.child.nodeType === ParseNodeType.Name) {
|
859
|
+
if (node.decorators?.some((d) => this._isOverload(d))) {
|
860
|
+
return this._getMethodOverloadsCompletions(priorWord, node.child);
|
861
|
+
}
|
862
|
+
|
863
|
+
// Determine if the partial name is a method that's overriding
|
864
|
+
// a method in a base class.
|
865
|
+
return this._getMethodOverrideCompletions(priorWord, node.child, node.decorators);
|
866
|
+
}
|
867
|
+
break;
|
868
|
+
}
|
869
|
+
}
|
870
|
+
|
871
|
+
return undefined;
|
872
|
+
}
|
873
|
+
|
874
|
+
private _isOverload(node: DecoratorNode): boolean {
|
875
|
+
return this._checkDecorator(node, 'overload');
|
876
|
+
}
|
877
|
+
|
878
|
+
private _checkDecorator(node: DecoratorNode, value: string): boolean {
|
879
|
+
return node.expression.nodeType === ParseNodeType.Name && node.expression.value === value;
|
880
|
+
}
|
881
|
+
|
882
|
+
private _createSingleKeywordCompletion(keyword: string): CompletionResults {
|
883
|
+
const completionItem = CompletionItem.create(keyword);
|
884
|
+
completionItem.kind = CompletionItemKind.Keyword;
|
885
|
+
completionItem.sortText = this._makeSortText(SortCategory.LikelyKeyword, keyword);
|
886
|
+
const completionMap = new CompletionMap();
|
887
|
+
completionMap.set(completionItem);
|
888
|
+
return { completionMap };
|
889
|
+
}
|
890
|
+
|
891
|
+
private _getClassVariableCompletions(priorWord: string, partialName: NameNode): CompletionResults | undefined {
|
892
|
+
const enclosingClass = ParseTreeUtils.getEnclosingClass(partialName, false);
|
893
|
+
if (!enclosingClass) {
|
894
|
+
return undefined;
|
895
|
+
}
|
896
|
+
|
897
|
+
const classResults = this._evaluator.getTypeOfClass(enclosingClass);
|
898
|
+
if (!classResults) {
|
899
|
+
return undefined;
|
900
|
+
}
|
901
|
+
|
902
|
+
const symbolTable = new Map<string, Symbol>();
|
903
|
+
for (const mroClass of classResults.classType.details.mro) {
|
904
|
+
if (isInstantiableClass(mroClass)) {
|
905
|
+
getMembersForClass(mroClass, symbolTable, /* includeInstanceVars */ false);
|
906
|
+
}
|
907
|
+
}
|
908
|
+
|
909
|
+
const printFlags = isStubFile(this._filePath)
|
910
|
+
? ParseTreeUtils.PrintExpressionFlags.ForwardDeclarations |
|
911
|
+
ParseTreeUtils.PrintExpressionFlags.DoNotLimitStringLength
|
912
|
+
: ParseTreeUtils.PrintExpressionFlags.DoNotLimitStringLength;
|
913
|
+
|
914
|
+
const completionMap = new CompletionMap();
|
915
|
+
symbolTable.forEach((symbol, name) => {
|
916
|
+
if (
|
917
|
+
SymbolNameUtils.isPrivateName(name) ||
|
918
|
+
symbol.isPrivateMember() ||
|
919
|
+
symbol.isExternallyHidden() ||
|
920
|
+
!StringUtils.isPatternInSymbol(partialName.value, name)
|
921
|
+
) {
|
922
|
+
return;
|
923
|
+
}
|
924
|
+
|
925
|
+
const decls = symbol
|
926
|
+
.getDeclarations()
|
927
|
+
.filter((d) => isVariableDeclaration(d) && d.moduleName !== 'builtins') as VariableDeclaration[];
|
928
|
+
|
929
|
+
// Skip any symbols invalid such as defined in the same class.
|
930
|
+
if (
|
931
|
+
decls.length === 0 ||
|
932
|
+
decls.some((d) => d.node && ParseTreeUtils.getEnclosingClass(d.node, false) === enclosingClass)
|
933
|
+
) {
|
934
|
+
return;
|
935
|
+
}
|
936
|
+
|
937
|
+
let edits: Edits | undefined;
|
938
|
+
const declWithTypeAnnotations = decls.filter((d) => d.typeAnnotationNode);
|
939
|
+
if (declWithTypeAnnotations.length > 0) {
|
940
|
+
const text = `${name}: ${ParseTreeUtils.printExpression(
|
941
|
+
declWithTypeAnnotations[declWithTypeAnnotations.length - 1].typeAnnotationNode!,
|
942
|
+
printFlags
|
943
|
+
)}`;
|
944
|
+
edits = {
|
945
|
+
textEdit: this._createReplaceEdits(priorWord, partialName, text),
|
946
|
+
};
|
947
|
+
}
|
948
|
+
|
949
|
+
this._addSymbol(name, symbol, partialName.value, completionMap, { edits });
|
950
|
+
});
|
951
|
+
|
952
|
+
return completionMap.size > 0 ? { completionMap } : undefined;
|
953
|
+
}
|
954
|
+
|
955
|
+
private _getMethodOverloadsCompletions(priorWord: string, partialName: NameNode): CompletionResults | undefined {
|
956
|
+
const symbolTable = getSymbolTable(this._evaluator, partialName);
|
957
|
+
if (!symbolTable) {
|
958
|
+
return undefined;
|
959
|
+
}
|
960
|
+
|
961
|
+
const funcParensDisabled = partialName.parent?.nodeType === ParseNodeType.Function ? true : undefined;
|
962
|
+
const completionMap = new CompletionMap();
|
963
|
+
|
964
|
+
const enclosingFunc = ParseTreeUtils.getEnclosingFunction(partialName);
|
965
|
+
symbolTable.forEach((symbol, name) => {
|
966
|
+
const decl = getLastTypedDeclaredForSymbol(symbol);
|
967
|
+
if (!decl || decl.type !== DeclarationType.Function) {
|
968
|
+
return;
|
969
|
+
}
|
970
|
+
|
971
|
+
if (!decl.node.decorators.some((d) => this._isOverload(d))) {
|
972
|
+
// Only consider ones that have overload decorator.
|
973
|
+
return;
|
974
|
+
}
|
975
|
+
|
976
|
+
const decls = symbol.getDeclarations();
|
977
|
+
if (decls.length === 1 && decls.some((d) => d.node === enclosingFunc)) {
|
978
|
+
// Don't show itself.
|
979
|
+
return;
|
980
|
+
}
|
981
|
+
|
982
|
+
if (StringUtils.isPatternInSymbol(partialName.value, name)) {
|
983
|
+
const textEdit = this._createReplaceEdits(priorWord, partialName, decl.node.name.value);
|
984
|
+
this._addSymbol(name, symbol, partialName.value, completionMap, {
|
985
|
+
funcParensDisabled,
|
986
|
+
edits: { textEdit },
|
987
|
+
});
|
988
|
+
}
|
989
|
+
});
|
990
|
+
|
991
|
+
return { completionMap };
|
992
|
+
|
993
|
+
function getSymbolTable(evaluator: TypeEvaluator, partialName: NameNode) {
|
994
|
+
const enclosingClass = ParseTreeUtils.getEnclosingClass(partialName, false);
|
995
|
+
if (enclosingClass) {
|
996
|
+
const classResults = evaluator.getTypeOfClass(enclosingClass);
|
997
|
+
if (!classResults) {
|
998
|
+
return undefined;
|
999
|
+
}
|
1000
|
+
|
1001
|
+
const symbolTable = new Map<string, Symbol>();
|
1002
|
+
for (const mroClass of classResults.classType.details.mro) {
|
1003
|
+
if (isInstantiableClass(mroClass)) {
|
1004
|
+
getMembersForClass(mroClass, symbolTable, /* includeInstanceVars */ false);
|
1005
|
+
}
|
1006
|
+
}
|
1007
|
+
|
1008
|
+
return symbolTable;
|
1009
|
+
}
|
1010
|
+
|
1011
|
+
// For function overload, we only care about top level functions
|
1012
|
+
const moduleNode = ParseTreeUtils.getEnclosingModule(partialName);
|
1013
|
+
if (moduleNode) {
|
1014
|
+
const moduleScope = AnalyzerNodeInfo.getScope(moduleNode);
|
1015
|
+
return moduleScope?.symbolTable;
|
1016
|
+
}
|
1017
|
+
|
1018
|
+
return undefined;
|
1019
|
+
}
|
1020
|
+
}
|
1021
|
+
|
1022
|
+
private _getMethodOverrideCompletions(
|
1023
|
+
priorWord: string,
|
1024
|
+
partialName: NameNode,
|
1025
|
+
decorators?: DecoratorNode[]
|
1026
|
+
): CompletionResults | undefined {
|
1027
|
+
const enclosingClass = ParseTreeUtils.getEnclosingClass(partialName, /* stopAtFunction */ true);
|
1028
|
+
if (!enclosingClass) {
|
1029
|
+
return undefined;
|
1030
|
+
}
|
1031
|
+
|
1032
|
+
const classResults = this._evaluator.getTypeOfClass(enclosingClass);
|
1033
|
+
if (!classResults) {
|
1034
|
+
return undefined;
|
1035
|
+
}
|
1036
|
+
|
1037
|
+
const symbolTable = new Map<string, Symbol>();
|
1038
|
+
for (let i = 1; i < classResults.classType.details.mro.length; i++) {
|
1039
|
+
const mroClass = classResults.classType.details.mro[i];
|
1040
|
+
if (isInstantiableClass(mroClass)) {
|
1041
|
+
getMembersForClass(mroClass, symbolTable, /* includeInstanceVars */ false);
|
1042
|
+
}
|
1043
|
+
}
|
1044
|
+
|
1045
|
+
const staticmethod = decorators?.some((d) => this._checkDecorator(d, 'staticmethod')) ?? false;
|
1046
|
+
const classmethod = decorators?.some((d) => this._checkDecorator(d, 'classmethod')) ?? false;
|
1047
|
+
|
1048
|
+
const completionMap = new CompletionMap();
|
1049
|
+
|
1050
|
+
symbolTable.forEach((symbol, name) => {
|
1051
|
+
let decl = getLastTypedDeclaredForSymbol(symbol);
|
1052
|
+
if (decl && decl.type === DeclarationType.Function) {
|
1053
|
+
if (StringUtils.isPatternInSymbol(partialName.value, name)) {
|
1054
|
+
const declaredType = this._evaluator.getTypeForDeclaration(decl);
|
1055
|
+
if (!declaredType) {
|
1056
|
+
return;
|
1057
|
+
}
|
1058
|
+
|
1059
|
+
let isProperty = isClassInstance(declaredType) && ClassType.isPropertyClass(declaredType);
|
1060
|
+
|
1061
|
+
if (SymbolNameUtils.isDunderName(name)) {
|
1062
|
+
// Don't offer suggestions for built-in properties like "__class__", etc.
|
1063
|
+
isProperty = false;
|
1064
|
+
}
|
1065
|
+
|
1066
|
+
if (!isFunction(declaredType) && !isProperty) {
|
1067
|
+
return;
|
1068
|
+
}
|
1069
|
+
|
1070
|
+
if (isProperty) {
|
1071
|
+
// For properties, we should override the "getter", which is typically
|
1072
|
+
// the first declaration.
|
1073
|
+
const typedDecls = symbol.getTypedDeclarations();
|
1074
|
+
if (typedDecls.length > 0 && typedDecls[0].type === DeclarationType.Function) {
|
1075
|
+
decl = typedDecls[0];
|
1076
|
+
}
|
1077
|
+
}
|
1078
|
+
|
1079
|
+
const isDeclaredStaticMethod =
|
1080
|
+
isFunction(declaredType) && FunctionType.isStaticMethod(declaredType);
|
1081
|
+
|
1082
|
+
// Special-case the "__init__subclass__" method because it's an implicit
|
1083
|
+
// classmethod that the type evaluator flags as a real classmethod.
|
1084
|
+
const isDeclaredClassMethod =
|
1085
|
+
isFunction(declaredType) &&
|
1086
|
+
FunctionType.isClassMethod(declaredType) &&
|
1087
|
+
name !== '__init_subclass__';
|
1088
|
+
|
1089
|
+
if (staticmethod !== isDeclaredStaticMethod || classmethod !== isDeclaredClassMethod) {
|
1090
|
+
return;
|
1091
|
+
}
|
1092
|
+
|
1093
|
+
const methodSignature = this._printMethodSignature(classResults.classType, decl);
|
1094
|
+
|
1095
|
+
let text: string;
|
1096
|
+
if (isStubFile(this._filePath)) {
|
1097
|
+
text = `${methodSignature}: ...`;
|
1098
|
+
} else {
|
1099
|
+
const methodBody = this._printOverriddenMethodBody(
|
1100
|
+
classResults.classType,
|
1101
|
+
isDeclaredStaticMethod,
|
1102
|
+
isProperty,
|
1103
|
+
decl
|
1104
|
+
);
|
1105
|
+
text = `${methodSignature}:\n${methodBody}`;
|
1106
|
+
}
|
1107
|
+
|
1108
|
+
const textEdit = this._createReplaceEdits(priorWord, partialName, text);
|
1109
|
+
|
1110
|
+
this._addSymbol(name, symbol, partialName.value, completionMap, {
|
1111
|
+
// method signature already contains ()
|
1112
|
+
funcParensDisabled: true,
|
1113
|
+
edits: {
|
1114
|
+
format: this._options.snippet ? InsertTextFormat.Snippet : undefined,
|
1115
|
+
textEdit,
|
1116
|
+
},
|
1117
|
+
});
|
1118
|
+
}
|
1119
|
+
}
|
1120
|
+
});
|
1121
|
+
|
1122
|
+
return { completionMap };
|
1123
|
+
}
|
1124
|
+
|
1125
|
+
private _createReplaceEdits(priorWord: string, node: ParseNode | undefined, text: string) {
|
1126
|
+
const replaceOrInsertEndChar =
|
1127
|
+
node?.nodeType === ParseNodeType.Name
|
1128
|
+
? this._position.character - priorWord.length + node.value.length
|
1129
|
+
: this._position.character;
|
1130
|
+
|
1131
|
+
const range: Range = {
|
1132
|
+
start: { line: this._position.line, character: this._position.character - priorWord.length },
|
1133
|
+
end: { line: this._position.line, character: replaceOrInsertEndChar },
|
1134
|
+
};
|
1135
|
+
|
1136
|
+
return TextEdit.replace(range, text);
|
1137
|
+
}
|
1138
|
+
|
1139
|
+
private _printMethodSignature(classType: ClassType, decl: FunctionDeclaration): string {
|
1140
|
+
const node = decl.node;
|
1141
|
+
|
1142
|
+
let ellipsisForDefault: boolean | undefined;
|
1143
|
+
if (isStubFile(this._filePath)) {
|
1144
|
+
// In stubs, always use "...".
|
1145
|
+
ellipsisForDefault = true;
|
1146
|
+
} else if (classType.details.moduleName === decl.moduleName) {
|
1147
|
+
// In the same file, always print the full default.
|
1148
|
+
ellipsisForDefault = false;
|
1149
|
+
}
|
1150
|
+
|
1151
|
+
const printFlags = isStubFile(this._filePath)
|
1152
|
+
? ParseTreeUtils.PrintExpressionFlags.ForwardDeclarations |
|
1153
|
+
ParseTreeUtils.PrintExpressionFlags.DoNotLimitStringLength
|
1154
|
+
: ParseTreeUtils.PrintExpressionFlags.DoNotLimitStringLength;
|
1155
|
+
|
1156
|
+
const paramList = node.parameters
|
1157
|
+
.map((param, index) => {
|
1158
|
+
let paramString = '';
|
1159
|
+
if (param.category === ParameterCategory.VarArgList) {
|
1160
|
+
paramString += '*';
|
1161
|
+
} else if (param.category === ParameterCategory.VarArgDictionary) {
|
1162
|
+
paramString += '**';
|
1163
|
+
}
|
1164
|
+
|
1165
|
+
if (param.name) {
|
1166
|
+
paramString += param.name.value;
|
1167
|
+
}
|
1168
|
+
|
1169
|
+
// Currently, we don't automatically add import if the type used in the annotation is not imported
|
1170
|
+
// in current file.
|
1171
|
+
const paramTypeAnnotation = ParseTreeUtils.getTypeAnnotationForParameter(node, index);
|
1172
|
+
if (paramTypeAnnotation) {
|
1173
|
+
paramString += ': ' + ParseTreeUtils.printExpression(paramTypeAnnotation, printFlags);
|
1174
|
+
}
|
1175
|
+
|
1176
|
+
if (param.defaultValue) {
|
1177
|
+
paramString += paramTypeAnnotation ? ' = ' : '=';
|
1178
|
+
|
1179
|
+
const useEllipsis = ellipsisForDefault ?? !isSimpleDefault(param.defaultValue);
|
1180
|
+
paramString += useEllipsis ? '...' : ParseTreeUtils.printExpression(param.defaultValue, printFlags);
|
1181
|
+
}
|
1182
|
+
|
1183
|
+
if (!paramString && !param.name && param.category === ParameterCategory.Simple) {
|
1184
|
+
return '/';
|
1185
|
+
}
|
1186
|
+
|
1187
|
+
return paramString;
|
1188
|
+
})
|
1189
|
+
.join(', ');
|
1190
|
+
|
1191
|
+
let methodSignature = node.name.value + '(' + paramList + ')';
|
1192
|
+
|
1193
|
+
if (node.returnTypeAnnotation) {
|
1194
|
+
methodSignature += ' -> ' + ParseTreeUtils.printExpression(node.returnTypeAnnotation, printFlags);
|
1195
|
+
} else if (node.functionAnnotationComment) {
|
1196
|
+
methodSignature +=
|
1197
|
+
' -> ' +
|
1198
|
+
ParseTreeUtils.printExpression(node.functionAnnotationComment.returnTypeAnnotation, printFlags);
|
1199
|
+
}
|
1200
|
+
|
1201
|
+
return methodSignature;
|
1202
|
+
|
1203
|
+
function isSimpleDefault(node: ExpressionNode): boolean {
|
1204
|
+
switch (node.nodeType) {
|
1205
|
+
case ParseNodeType.Number:
|
1206
|
+
case ParseNodeType.Constant:
|
1207
|
+
return true;
|
1208
|
+
|
1209
|
+
case ParseNodeType.String:
|
1210
|
+
return (node.token.flags & StringTokenFlags.Format) === 0;
|
1211
|
+
|
1212
|
+
case ParseNodeType.StringList:
|
1213
|
+
return node.strings.every(isSimpleDefault);
|
1214
|
+
|
1215
|
+
case ParseNodeType.UnaryOperation:
|
1216
|
+
return isSimpleDefault(node.expression);
|
1217
|
+
|
1218
|
+
case ParseNodeType.BinaryOperation:
|
1219
|
+
return isSimpleDefault(node.leftExpression) && isSimpleDefault(node.rightExpression);
|
1220
|
+
|
1221
|
+
default:
|
1222
|
+
return false;
|
1223
|
+
}
|
1224
|
+
}
|
1225
|
+
}
|
1226
|
+
|
1227
|
+
private _printOverriddenMethodBody(
|
1228
|
+
classType: ClassType,
|
1229
|
+
isStaticMethod: boolean,
|
1230
|
+
isProperty: boolean,
|
1231
|
+
decl: FunctionDeclaration
|
1232
|
+
) {
|
1233
|
+
let sb = this._parseResults.tokenizerOutput.predominantTabSequence;
|
1234
|
+
|
1235
|
+
if (
|
1236
|
+
classType.details.baseClasses.length === 1 &&
|
1237
|
+
isClass(classType.details.baseClasses[0]) &&
|
1238
|
+
classType.details.baseClasses[0].details.fullName === 'builtins.object'
|
1239
|
+
) {
|
1240
|
+
sb += this._options.snippet ? '${0:pass}' : 'pass';
|
1241
|
+
return sb;
|
1242
|
+
}
|
1243
|
+
|
1244
|
+
if (decl.node.parameters.length === 0) {
|
1245
|
+
sb += this._options.snippet ? '${0:pass}' : 'pass';
|
1246
|
+
return sb;
|
1247
|
+
}
|
1248
|
+
|
1249
|
+
const parameters = getParameters(isStaticMethod ? decl.node.parameters : decl.node.parameters.slice(1));
|
1250
|
+
if (decl.node.name.value !== '__init__') {
|
1251
|
+
sb += 'return ';
|
1252
|
+
}
|
1253
|
+
|
1254
|
+
if (decl.node.isAsync) {
|
1255
|
+
sb += 'await ';
|
1256
|
+
}
|
1257
|
+
|
1258
|
+
if (isProperty) {
|
1259
|
+
return sb + `super().${decl.node.name.value}`;
|
1260
|
+
}
|
1261
|
+
|
1262
|
+
return sb + `super().${decl.node.name.value}(${parameters.map(convertToString).join(', ')})`;
|
1263
|
+
|
1264
|
+
function getParameters(parameters: ParameterNode[]) {
|
1265
|
+
const results: [node: ParameterNode, keywordOnly: boolean][] = [];
|
1266
|
+
|
1267
|
+
let keywordOnly = false;
|
1268
|
+
for (const parameter of parameters) {
|
1269
|
+
if (parameter.name) {
|
1270
|
+
results.push([parameter, keywordOnly]);
|
1271
|
+
}
|
1272
|
+
|
1273
|
+
keywordOnly =
|
1274
|
+
parameter.category === ParameterCategory.VarArgList ||
|
1275
|
+
parameter.category === ParameterCategory.VarArgDictionary;
|
1276
|
+
}
|
1277
|
+
|
1278
|
+
return results;
|
1279
|
+
}
|
1280
|
+
|
1281
|
+
function convertToString(parameter: [node: ParameterNode, keywordOnly: boolean]) {
|
1282
|
+
const name = parameter[0].name?.value;
|
1283
|
+
if (parameter[0].category === ParameterCategory.VarArgList) {
|
1284
|
+
return `*${name}`;
|
1285
|
+
}
|
1286
|
+
|
1287
|
+
if (parameter[0].category === ParameterCategory.VarArgDictionary) {
|
1288
|
+
return `**${name}`;
|
1289
|
+
}
|
1290
|
+
|
1291
|
+
return parameter[1] ? `${name}=${name}` : name;
|
1292
|
+
}
|
1293
|
+
}
|
1294
|
+
|
1295
|
+
private _getMemberAccessCompletions(
|
1296
|
+
leftExprNode: ExpressionNode,
|
1297
|
+
priorWord: string
|
1298
|
+
): CompletionResults | undefined {
|
1299
|
+
const symbolTable = new Map<string, Symbol>();
|
1300
|
+
const completionMap = new CompletionMap();
|
1301
|
+
let memberAccessInfo: MemberAccessInfo = {};
|
1302
|
+
|
1303
|
+
let leftType = this._evaluator.getType(leftExprNode);
|
1304
|
+
|
1305
|
+
if (leftType) {
|
1306
|
+
leftType = this._evaluator.makeTopLevelTypeVarsConcrete(leftType);
|
1307
|
+
|
1308
|
+
doForEachSubtype(leftType, (subtype) => {
|
1309
|
+
subtype = this._evaluator.makeTopLevelTypeVarsConcrete(subtype);
|
1310
|
+
|
1311
|
+
if (isClass(subtype)) {
|
1312
|
+
// Handle LiteralString specially. Treat it like a 'str' for purposes
|
1313
|
+
// of completion suggestions.
|
1314
|
+
if (ClassType.isBuiltIn(subtype, 'LiteralString')) {
|
1315
|
+
const strObject = this._evaluator.getBuiltInObject(leftExprNode, 'str');
|
1316
|
+
if (strObject && isClassInstance(strObject)) {
|
1317
|
+
subtype = strObject;
|
1318
|
+
}
|
1319
|
+
}
|
1320
|
+
|
1321
|
+
getMembersForClass(subtype, symbolTable, /* includeInstanceVars */ TypeBase.isInstance(subtype));
|
1322
|
+
} else if (isModule(subtype)) {
|
1323
|
+
getMembersForModule(subtype, symbolTable);
|
1324
|
+
} else if (isFunction(subtype) || isOverloadedFunction(subtype)) {
|
1325
|
+
const functionClass = this._evaluator.getBuiltInType(leftExprNode, 'function');
|
1326
|
+
if (functionClass && isInstantiableClass(functionClass)) {
|
1327
|
+
getMembersForClass(functionClass, symbolTable, /* includeInstanceVars */ true);
|
1328
|
+
}
|
1329
|
+
} else if (isNoneInstance(subtype)) {
|
1330
|
+
const objectClass = this._evaluator.getBuiltInType(leftExprNode, 'object');
|
1331
|
+
if (objectClass && isInstantiableClass(objectClass)) {
|
1332
|
+
getMembersForClass(objectClass, symbolTable, TypeBase.isInstance(subtype));
|
1333
|
+
}
|
1334
|
+
}
|
1335
|
+
|
1336
|
+
this._addSymbolsForSymbolTable(
|
1337
|
+
symbolTable,
|
1338
|
+
() => true,
|
1339
|
+
priorWord,
|
1340
|
+
/* isInImport */ false,
|
1341
|
+
isClass(subtype) ? subtype : undefined,
|
1342
|
+
completionMap
|
1343
|
+
);
|
1344
|
+
});
|
1345
|
+
}
|
1346
|
+
|
1347
|
+
// If we don't know this type, look for a module we should stub.
|
1348
|
+
if (!leftType || isUnknown(leftType) || isUnbound(leftType)) {
|
1349
|
+
memberAccessInfo = this._getLastKnownModule(leftExprNode, leftType);
|
1350
|
+
}
|
1351
|
+
|
1352
|
+
return { completionMap, memberAccessInfo };
|
1353
|
+
}
|
1354
|
+
|
1355
|
+
private _getLastKnownModule(leftExprNode: ExpressionNode, leftType: Type | undefined): MemberAccessInfo {
|
1356
|
+
let curNode: ExpressionNode | undefined = leftExprNode;
|
1357
|
+
let curType: Type | undefined = leftType;
|
1358
|
+
let unknownMemberName: string | undefined =
|
1359
|
+
leftExprNode.nodeType === ParseNodeType.MemberAccess ? leftExprNode?.memberName.value : undefined;
|
1360
|
+
|
1361
|
+
// Walk left of the expression scope till we find a known type. A.B.Unknown.<-- return B.
|
1362
|
+
while (curNode) {
|
1363
|
+
if (curNode.nodeType === ParseNodeType.Call || curNode.nodeType === ParseNodeType.MemberAccess) {
|
1364
|
+
// Move left
|
1365
|
+
curNode = curNode.leftExpression;
|
1366
|
+
|
1367
|
+
// First time in the loop remember the name of the unknown type.
|
1368
|
+
if (unknownMemberName === undefined) {
|
1369
|
+
unknownMemberName =
|
1370
|
+
curNode.nodeType === ParseNodeType.MemberAccess ? curNode?.memberName.value ?? '' : '';
|
1371
|
+
}
|
1372
|
+
} else {
|
1373
|
+
curNode = undefined;
|
1374
|
+
}
|
1375
|
+
|
1376
|
+
if (curNode) {
|
1377
|
+
curType = this._evaluator.getType(curNode);
|
1378
|
+
|
1379
|
+
// Breakout if we found a known type.
|
1380
|
+
if (curType !== undefined && !isUnknown(curType) && !isUnbound(curType)) {
|
1381
|
+
break;
|
1382
|
+
}
|
1383
|
+
}
|
1384
|
+
}
|
1385
|
+
|
1386
|
+
const memberAccessInfo: MemberAccessInfo = {};
|
1387
|
+
if (curType && !isUnknown(curType) && !isUnbound(curType) && curNode) {
|
1388
|
+
const moduleNamesForType = getDeclaringModulesForType(curType);
|
1389
|
+
|
1390
|
+
// For union types we only care about non 'typing' modules.
|
1391
|
+
memberAccessInfo.lastKnownModule = moduleNamesForType.find((n) => n !== 'typing');
|
1392
|
+
|
1393
|
+
if (curNode.nodeType === ParseNodeType.MemberAccess) {
|
1394
|
+
memberAccessInfo.lastKnownMemberName = curNode.memberName.value;
|
1395
|
+
} else if (curNode.nodeType === ParseNodeType.Name && isInstantiableClass(curType)) {
|
1396
|
+
memberAccessInfo.lastKnownMemberName = curType.details.name;
|
1397
|
+
} else if (curNode.nodeType === ParseNodeType.Name && isClassInstance(curType)) {
|
1398
|
+
memberAccessInfo.lastKnownMemberName = curType.details.name;
|
1399
|
+
}
|
1400
|
+
|
1401
|
+
memberAccessInfo.unknownMemberName = unknownMemberName;
|
1402
|
+
}
|
1403
|
+
|
1404
|
+
return memberAccessInfo;
|
1405
|
+
}
|
1406
|
+
|
1407
|
+
private _getStatementCompletions(
|
1408
|
+
parseNode: ParseNode,
|
1409
|
+
priorWord: string,
|
1410
|
+
priorText: string,
|
1411
|
+
postText: string
|
1412
|
+
): CompletionResults | undefined {
|
1413
|
+
// For now, use the same logic for expressions and statements.
|
1414
|
+
return this._getExpressionCompletions(parseNode, priorWord, priorText, postText);
|
1415
|
+
}
|
1416
|
+
|
1417
|
+
private _getExpressionCompletions(
|
1418
|
+
parseNode: ParseNode,
|
1419
|
+
priorWord: string,
|
1420
|
+
priorText: string,
|
1421
|
+
postText: string
|
1422
|
+
): CompletionResults | undefined {
|
1423
|
+
const isIndexArgument = this._isIndexArgument(parseNode);
|
1424
|
+
|
1425
|
+
// If the user typed a "." as part of a number, don't present
|
1426
|
+
// any completion options.
|
1427
|
+
if (!isIndexArgument && parseNode.nodeType === ParseNodeType.Number) {
|
1428
|
+
return undefined;
|
1429
|
+
}
|
1430
|
+
|
1431
|
+
// Are we within a "with Y as []"?
|
1432
|
+
// Don't add any completion options.
|
1433
|
+
if (
|
1434
|
+
parseNode.parent?.nodeType === ParseNodeType.WithItem &&
|
1435
|
+
parseNode.parent === parseNode.parent.target?.parent
|
1436
|
+
) {
|
1437
|
+
return undefined;
|
1438
|
+
}
|
1439
|
+
|
1440
|
+
const completionMap = new CompletionMap();
|
1441
|
+
const completionResults = { completionMap };
|
1442
|
+
|
1443
|
+
// Return empty completionList for Ellipsis
|
1444
|
+
if (priorText.slice(-2) === '..') {
|
1445
|
+
return completionResults;
|
1446
|
+
}
|
1447
|
+
|
1448
|
+
// Add call argument completions.
|
1449
|
+
this._addCallArgumentCompletions(
|
1450
|
+
parseNode,
|
1451
|
+
priorWord,
|
1452
|
+
priorText,
|
1453
|
+
postText,
|
1454
|
+
/* atArgument */ false,
|
1455
|
+
completionMap
|
1456
|
+
);
|
1457
|
+
|
1458
|
+
// Add symbols that are in scope.
|
1459
|
+
this._addSymbols(parseNode, priorWord, completionMap);
|
1460
|
+
|
1461
|
+
// Add keywords.
|
1462
|
+
this._findMatchingKeywords(Keywords.forVersion(this._execEnv.pythonVersion), priorWord).map((keyword) => {
|
1463
|
+
if (completionMap.has(keyword)) {
|
1464
|
+
return;
|
1465
|
+
}
|
1466
|
+
const completionItem = CompletionItem.create(keyword);
|
1467
|
+
completionItem.kind = CompletionItemKind.Keyword;
|
1468
|
+
completionItem.sortText = this._makeSortText(SortCategory.Keyword, keyword);
|
1469
|
+
completionMap.set(completionItem);
|
1470
|
+
});
|
1471
|
+
|
1472
|
+
// Add auto-import suggestions from other modules.
|
1473
|
+
// Ignore this check for privates, since they are not imported.
|
1474
|
+
if (!priorWord.startsWith('_') && !this._itemToResolve) {
|
1475
|
+
this._addAutoImportCompletions(priorWord, similarityLimit, this._options.lazyEdit, completionResults);
|
1476
|
+
}
|
1477
|
+
|
1478
|
+
// Add literal values if appropriate.
|
1479
|
+
if (parseNode.nodeType === ParseNodeType.Error) {
|
1480
|
+
if (
|
1481
|
+
parseNode.category === ErrorExpressionCategory.MissingIndexOrSlice &&
|
1482
|
+
parseNode.parent?.nodeType === ParseNodeType.Index
|
1483
|
+
) {
|
1484
|
+
this._tryAddTypedDictStringLiteral(
|
1485
|
+
parseNode.parent,
|
1486
|
+
/* priorText */ undefined,
|
1487
|
+
/* postText */ undefined,
|
1488
|
+
completionMap
|
1489
|
+
);
|
1490
|
+
} else if (parseNode.category === ErrorExpressionCategory.MissingExpression) {
|
1491
|
+
if (parseNode.parent && parseNode.parent.nodeType === ParseNodeType.Assignment) {
|
1492
|
+
const declaredTypeOfTarget = this._evaluator.getExpectedType(parseNode)?.type;
|
1493
|
+
if (declaredTypeOfTarget) {
|
1494
|
+
this._addLiteralValuesForTargetType(
|
1495
|
+
declaredTypeOfTarget,
|
1496
|
+
priorText,
|
1497
|
+
priorWord,
|
1498
|
+
postText,
|
1499
|
+
completionMap
|
1500
|
+
);
|
1501
|
+
}
|
1502
|
+
}
|
1503
|
+
}
|
1504
|
+
}
|
1505
|
+
|
1506
|
+
if (isIndexArgument) {
|
1507
|
+
// Completion for dict key (ex, dict_variable[<here>])
|
1508
|
+
const indexNode = parseNode.parent!.parent! as IndexNode;
|
1509
|
+
|
1510
|
+
this._getIndexerKeys(indexNode, parseNode).forEach((key) => {
|
1511
|
+
if (completionMap.has(key)) {
|
1512
|
+
// Don't add key if it already exists in the completion.
|
1513
|
+
// ex) key = "dictKey"
|
1514
|
+
// dict[key] = 1
|
1515
|
+
// print(dict[<key will come from symbol table provider>]))
|
1516
|
+
return;
|
1517
|
+
}
|
1518
|
+
|
1519
|
+
this._addNameToCompletions(key, CompletionItemKind.Constant, priorWord, completionMap, {
|
1520
|
+
sortText: this._makeSortText(SortCategory.LiteralValue, key),
|
1521
|
+
itemDetail: dictionaryKeyDetail,
|
1522
|
+
});
|
1523
|
+
});
|
1524
|
+
}
|
1525
|
+
|
1526
|
+
return completionResults;
|
1527
|
+
}
|
1528
|
+
|
1529
|
+
private _isIndexArgument(node: ParseNode) {
|
1530
|
+
const currentNode = node.parent;
|
1531
|
+
return (
|
1532
|
+
currentNode &&
|
1533
|
+
currentNode.nodeType === ParseNodeType.Argument &&
|
1534
|
+
currentNode.argumentCategory === ArgumentCategory.Simple &&
|
1535
|
+
currentNode.parent &&
|
1536
|
+
currentNode.parent.nodeType === ParseNodeType.Index &&
|
1537
|
+
currentNode.parent.baseExpression &&
|
1538
|
+
currentNode.parent.baseExpression.nodeType === ParseNodeType.Name
|
1539
|
+
);
|
1540
|
+
}
|
1541
|
+
|
1542
|
+
private _addCallArgumentCompletions(
|
1543
|
+
parseNode: ParseNode,
|
1544
|
+
priorWord: string,
|
1545
|
+
priorText: string,
|
1546
|
+
postText: string,
|
1547
|
+
atArgument: boolean,
|
1548
|
+
completionMap: CompletionMap
|
1549
|
+
) {
|
1550
|
+
// If we're within the argument list of a call, add parameter names.
|
1551
|
+
const offset = convertPositionToOffset(this._position, this._parseResults.tokenizerOutput.lines)!;
|
1552
|
+
const callInfo = getCallNodeAndActiveParameterIndex(
|
1553
|
+
parseNode,
|
1554
|
+
offset,
|
1555
|
+
this._parseResults.tokenizerOutput.tokens
|
1556
|
+
);
|
1557
|
+
|
1558
|
+
if (!callInfo) {
|
1559
|
+
return;
|
1560
|
+
}
|
1561
|
+
|
1562
|
+
const signatureInfo = this._evaluator.getCallSignatureInfo(
|
1563
|
+
callInfo.callNode,
|
1564
|
+
callInfo.activeIndex,
|
1565
|
+
callInfo.activeOrFake
|
1566
|
+
);
|
1567
|
+
|
1568
|
+
if (signatureInfo) {
|
1569
|
+
// Are we past the call expression and within the argument list?
|
1570
|
+
const callNameEnd = convertOffsetToPosition(
|
1571
|
+
signatureInfo.callNode.leftExpression.start + signatureInfo.callNode.leftExpression.length,
|
1572
|
+
this._parseResults.tokenizerOutput.lines
|
1573
|
+
);
|
1574
|
+
|
1575
|
+
if (comparePositions(this._position, callNameEnd) > 0) {
|
1576
|
+
if (!atArgument) {
|
1577
|
+
this._addNamedParameters(signatureInfo, priorWord, completionMap);
|
1578
|
+
}
|
1579
|
+
|
1580
|
+
// Add literals that apply to this parameter.
|
1581
|
+
this._addLiteralValuesForArgument(signatureInfo, priorText, priorWord, postText, completionMap);
|
1582
|
+
}
|
1583
|
+
}
|
1584
|
+
}
|
1585
|
+
|
1586
|
+
private _addLiteralValuesForArgument(
|
1587
|
+
signatureInfo: CallSignatureInfo,
|
1588
|
+
priorText: string,
|
1589
|
+
priorWord: string,
|
1590
|
+
postText: string,
|
1591
|
+
completionMap: CompletionMap
|
1592
|
+
) {
|
1593
|
+
signatureInfo.signatures.forEach((signature) => {
|
1594
|
+
if (!signature.activeParam) {
|
1595
|
+
return undefined;
|
1596
|
+
}
|
1597
|
+
|
1598
|
+
const type = signature.type;
|
1599
|
+
const paramIndex = type.details.parameters.indexOf(signature.activeParam);
|
1600
|
+
|
1601
|
+
if (paramIndex < 0) {
|
1602
|
+
return undefined;
|
1603
|
+
}
|
1604
|
+
|
1605
|
+
const paramType = type.details.parameters[paramIndex].type;
|
1606
|
+
this._addLiteralValuesForTargetType(paramType, priorText, priorWord, postText, completionMap);
|
1607
|
+
return undefined;
|
1608
|
+
});
|
1609
|
+
}
|
1610
|
+
|
1611
|
+
private _addLiteralValuesForTargetType(
|
1612
|
+
type: Type,
|
1613
|
+
priorText: string,
|
1614
|
+
priorWord: string,
|
1615
|
+
postText: string,
|
1616
|
+
completionMap: CompletionMap
|
1617
|
+
) {
|
1618
|
+
const quoteValue = this._getQuoteInfo(priorText);
|
1619
|
+
this._getSubTypesWithLiteralValues(type).forEach((v) => {
|
1620
|
+
if (ClassType.isBuiltIn(v, 'str')) {
|
1621
|
+
const value = printLiteralValue(v, quoteValue.quoteCharacter);
|
1622
|
+
if (quoteValue.stringValue === undefined) {
|
1623
|
+
this._addNameToCompletions(value, CompletionItemKind.Constant, priorWord, completionMap, {
|
1624
|
+
sortText: this._makeSortText(SortCategory.LiteralValue, v.literalValue as string),
|
1625
|
+
});
|
1626
|
+
} else {
|
1627
|
+
this._addStringLiteralToCompletions(
|
1628
|
+
value.substr(1, value.length - 2),
|
1629
|
+
quoteValue.stringValue,
|
1630
|
+
postText,
|
1631
|
+
quoteValue.quoteCharacter,
|
1632
|
+
completionMap
|
1633
|
+
);
|
1634
|
+
}
|
1635
|
+
}
|
1636
|
+
});
|
1637
|
+
}
|
1638
|
+
|
1639
|
+
private _getDictExpressionStringKeys(parseNode: ParseNode, excludeIds?: Set<number | undefined>) {
|
1640
|
+
const node = getDictionaryLikeNode(parseNode);
|
1641
|
+
if (!node) {
|
1642
|
+
return [];
|
1643
|
+
}
|
1644
|
+
|
1645
|
+
return node.entries.flatMap((entry) => {
|
1646
|
+
if (entry.nodeType !== ParseNodeType.DictionaryKeyEntry || excludeIds?.has(entry.keyExpression.id)) {
|
1647
|
+
return [];
|
1648
|
+
}
|
1649
|
+
|
1650
|
+
if (entry.keyExpression.nodeType === ParseNodeType.StringList) {
|
1651
|
+
return [entry.keyExpression.strings.map((s) => s.value).join('')];
|
1652
|
+
}
|
1653
|
+
|
1654
|
+
return [];
|
1655
|
+
});
|
1656
|
+
|
1657
|
+
function getDictionaryLikeNode(parseNode: ParseNode) {
|
1658
|
+
// this method assumes the given parseNode is either a child of a dictionary or a dictionary itself
|
1659
|
+
if (parseNode.nodeType === ParseNodeType.Dictionary) {
|
1660
|
+
return parseNode;
|
1661
|
+
}
|
1662
|
+
|
1663
|
+
let curNode: ParseNode | undefined = parseNode;
|
1664
|
+
while (curNode && curNode.nodeType !== ParseNodeType.Dictionary && curNode.nodeType !== ParseNodeType.Set) {
|
1665
|
+
curNode = curNode.parent;
|
1666
|
+
if (!curNode) {
|
1667
|
+
return;
|
1668
|
+
}
|
1669
|
+
}
|
1670
|
+
|
1671
|
+
return curNode;
|
1672
|
+
}
|
1673
|
+
}
|
1674
|
+
|
1675
|
+
private _getSubTypesWithLiteralValues(type: Type) {
|
1676
|
+
const values: ClassType[] = [];
|
1677
|
+
|
1678
|
+
doForEachSubtype(type, (subtype) => {
|
1679
|
+
if (isClassInstance(subtype) && isLiteralType(subtype)) {
|
1680
|
+
values.push(subtype);
|
1681
|
+
}
|
1682
|
+
});
|
1683
|
+
|
1684
|
+
return values;
|
1685
|
+
}
|
1686
|
+
|
1687
|
+
private _getIndexerKeyType(baseType: ClassType) {
|
1688
|
+
// Handle dict type
|
1689
|
+
if (ClassType.isBuiltIn(baseType, 'dict') || ClassType.isBuiltIn(baseType, 'Mapping')) {
|
1690
|
+
if (baseType.typeArguments?.length === 2) {
|
1691
|
+
return baseType.typeArguments[0];
|
1692
|
+
}
|
1693
|
+
}
|
1694
|
+
|
1695
|
+
// Handle simple __getitem__
|
1696
|
+
const member = lookUpObjectMember(baseType, '__getitem__');
|
1697
|
+
if (member?.symbol.hasDeclarations()) {
|
1698
|
+
const declaration = member.symbol.getDeclarations()[0];
|
1699
|
+
if (isFunctionDeclaration(declaration) && declaration.isMethod) {
|
1700
|
+
const getItemType = this._evaluator.getTypeForDeclaration(declaration);
|
1701
|
+
if (getItemType && isFunction(getItemType) && getItemType.details.parameters.length === 2) {
|
1702
|
+
return getItemType.details.parameters[1].type;
|
1703
|
+
}
|
1704
|
+
}
|
1705
|
+
}
|
1706
|
+
|
1707
|
+
return undefined;
|
1708
|
+
}
|
1709
|
+
|
1710
|
+
private _getIndexerKeys(indexNode: IndexNode, invocationNode: ParseNode) {
|
1711
|
+
if (indexNode.baseExpression.nodeType !== ParseNodeType.Name) {
|
1712
|
+
// This completion only supports simple name case
|
1713
|
+
return [];
|
1714
|
+
}
|
1715
|
+
|
1716
|
+
const baseType = this._evaluator.getType(indexNode.baseExpression);
|
1717
|
+
if (!baseType || !isClassInstance(baseType)) {
|
1718
|
+
return [];
|
1719
|
+
}
|
1720
|
+
|
1721
|
+
// See whether indexer key is typed using Literal types. If it is, return those literal keys.
|
1722
|
+
const keyType = this._getIndexerKeyType(baseType);
|
1723
|
+
if (keyType) {
|
1724
|
+
const keys: string[] = [];
|
1725
|
+
|
1726
|
+
this._getSubTypesWithLiteralValues(keyType).forEach((v) => {
|
1727
|
+
if (
|
1728
|
+
!ClassType.isBuiltIn(v, 'str') &&
|
1729
|
+
!ClassType.isBuiltIn(v, 'int') &&
|
1730
|
+
!ClassType.isBuiltIn(v, 'bool') &&
|
1731
|
+
!ClassType.isBuiltIn(v, 'bytes') &&
|
1732
|
+
!ClassType.isEnumClass(v)
|
1733
|
+
) {
|
1734
|
+
return;
|
1735
|
+
}
|
1736
|
+
|
1737
|
+
keys.push(printLiteralValue(v, this._parseResults.tokenizerOutput.predominantSingleQuoteCharacter));
|
1738
|
+
});
|
1739
|
+
|
1740
|
+
if (keys.length > 0) {
|
1741
|
+
return keys;
|
1742
|
+
}
|
1743
|
+
}
|
1744
|
+
|
1745
|
+
// Must be local variable/parameter
|
1746
|
+
const declarations = this._evaluator.getDeclarationsForNameNode(indexNode.baseExpression) ?? [];
|
1747
|
+
const declaration = declarations.length > 0 ? declarations[0] : undefined;
|
1748
|
+
if (
|
1749
|
+
!declaration ||
|
1750
|
+
(declaration.type !== DeclarationType.Variable && declaration.type !== DeclarationType.Parameter)
|
1751
|
+
) {
|
1752
|
+
return [];
|
1753
|
+
}
|
1754
|
+
|
1755
|
+
if (declaration.path !== this._filePath) {
|
1756
|
+
return [];
|
1757
|
+
}
|
1758
|
+
|
1759
|
+
let startingNode: ParseNode = indexNode.baseExpression;
|
1760
|
+
if (declaration.node) {
|
1761
|
+
const scopeRoot = ParseTreeUtils.getEvaluationScopeNode(declaration.node);
|
1762
|
+
|
1763
|
+
// Find the lowest tree to search the symbol.
|
1764
|
+
if (
|
1765
|
+
ParseTreeUtils.getFileInfoFromNode(startingNode)?.filePath ===
|
1766
|
+
ParseTreeUtils.getFileInfoFromNode(scopeRoot)?.filePath
|
1767
|
+
) {
|
1768
|
+
startingNode = scopeRoot;
|
1769
|
+
}
|
1770
|
+
}
|
1771
|
+
|
1772
|
+
const results = DocumentSymbolCollector.collectFromNode(
|
1773
|
+
indexNode.baseExpression,
|
1774
|
+
this._evaluator,
|
1775
|
+
this._cancellationToken,
|
1776
|
+
startingNode
|
1777
|
+
);
|
1778
|
+
|
1779
|
+
const keys: Set<string> = new Set<string>();
|
1780
|
+
for (const result of results) {
|
1781
|
+
const node =
|
1782
|
+
result.node.parent?.nodeType === ParseNodeType.TypeAnnotation ? result.node.parent : result.node;
|
1783
|
+
|
1784
|
+
if (
|
1785
|
+
node.parent?.nodeType === ParseNodeType.Assignment ||
|
1786
|
+
node.parent?.nodeType === ParseNodeType.AssignmentExpression
|
1787
|
+
) {
|
1788
|
+
if (node.parent.rightExpression.nodeType === ParseNodeType.Dictionary) {
|
1789
|
+
const dictionary = node.parent.rightExpression;
|
1790
|
+
for (const entry of dictionary.entries.filter(
|
1791
|
+
(e) => e.nodeType === ParseNodeType.DictionaryKeyEntry
|
1792
|
+
) as DictionaryKeyEntryNode[]) {
|
1793
|
+
const key = this._parseResults.text
|
1794
|
+
.substr(entry.keyExpression.start, entry.keyExpression.length)
|
1795
|
+
.trim();
|
1796
|
+
if (key.length > 0) keys.add(key);
|
1797
|
+
}
|
1798
|
+
}
|
1799
|
+
|
1800
|
+
if (node.parent.rightExpression.nodeType === ParseNodeType.Call) {
|
1801
|
+
const call = node.parent.rightExpression;
|
1802
|
+
const type = this._evaluator.getType(call.leftExpression);
|
1803
|
+
if (!type || !isInstantiableClass(type) || !ClassType.isBuiltIn(type, 'dict')) {
|
1804
|
+
continue;
|
1805
|
+
}
|
1806
|
+
|
1807
|
+
for (const arg of call.arguments) {
|
1808
|
+
const key = arg.name?.value.trim() ?? '';
|
1809
|
+
const quote = this._parseResults.tokenizerOutput.predominantSingleQuoteCharacter;
|
1810
|
+
if (key.length > 0) {
|
1811
|
+
keys.add(`${quote}${key}${quote}`);
|
1812
|
+
}
|
1813
|
+
}
|
1814
|
+
}
|
1815
|
+
}
|
1816
|
+
|
1817
|
+
if (
|
1818
|
+
node.parent?.nodeType === ParseNodeType.Index &&
|
1819
|
+
node.parent.items.length === 1 &&
|
1820
|
+
node.parent.items[0].valueExpression.nodeType !== ParseNodeType.Error &&
|
1821
|
+
!TextRange.containsRange(node.parent, invocationNode)
|
1822
|
+
) {
|
1823
|
+
const indexArgument = node.parent.items[0];
|
1824
|
+
const key = this._parseResults.text
|
1825
|
+
.substr(indexArgument.valueExpression.start, indexArgument.valueExpression.length)
|
1826
|
+
.trim();
|
1827
|
+
if (key.length > 0) keys.add(key);
|
1828
|
+
}
|
1829
|
+
}
|
1830
|
+
|
1831
|
+
return [...keys];
|
1832
|
+
}
|
1833
|
+
|
1834
|
+
private _getLiteralCompletions(
|
1835
|
+
parseNode: StringNode | ErrorNode,
|
1836
|
+
priorWord: string,
|
1837
|
+
priorText: string,
|
1838
|
+
postText: string
|
1839
|
+
): CompletionResults | undefined {
|
1840
|
+
let parentNode: ParseNode | undefined = parseNode.parent;
|
1841
|
+
|
1842
|
+
if (!parentNode) {
|
1843
|
+
return undefined;
|
1844
|
+
}
|
1845
|
+
|
1846
|
+
const completionMap = new CompletionMap();
|
1847
|
+
|
1848
|
+
// See if the type evaluator can determine the expected type for this node.
|
1849
|
+
if (isExpressionNode(parentNode)) {
|
1850
|
+
const expectedTypeResult = this._evaluator.getExpectedType(parentNode);
|
1851
|
+
if (expectedTypeResult && isLiteralTypeOrUnion(expectedTypeResult.type)) {
|
1852
|
+
this._addLiteralValuesForTargetType(
|
1853
|
+
expectedTypeResult.type,
|
1854
|
+
priorText,
|
1855
|
+
priorWord,
|
1856
|
+
postText,
|
1857
|
+
completionMap
|
1858
|
+
);
|
1859
|
+
return { completionMap };
|
1860
|
+
}
|
1861
|
+
|
1862
|
+
if (parseNode.nodeType === ParseNodeType.String && parseNode.parent?.parent) {
|
1863
|
+
const stringParent = parseNode.parent.parent;
|
1864
|
+
|
1865
|
+
// If the dictionary is not yet filled in, it will appear as though it's
|
1866
|
+
// a set initially.
|
1867
|
+
let dictOrSet: DictionaryNode | SetNode | undefined;
|
1868
|
+
|
1869
|
+
if (
|
1870
|
+
stringParent.nodeType === ParseNodeType.DictionaryKeyEntry &&
|
1871
|
+
stringParent.keyExpression === parseNode.parent &&
|
1872
|
+
stringParent.parent?.nodeType === ParseNodeType.Dictionary
|
1873
|
+
) {
|
1874
|
+
dictOrSet = stringParent.parent;
|
1875
|
+
} else if (stringParent?.nodeType === ParseNodeType.Set) {
|
1876
|
+
dictOrSet = stringParent;
|
1877
|
+
}
|
1878
|
+
|
1879
|
+
if (dictOrSet) {
|
1880
|
+
if (this._addTypedDictKeys(dictOrSet, parseNode, priorText, postText, completionMap)) {
|
1881
|
+
return { completionMap };
|
1882
|
+
}
|
1883
|
+
}
|
1884
|
+
}
|
1885
|
+
}
|
1886
|
+
|
1887
|
+
if (parentNode.nodeType !== ParseNodeType.Argument) {
|
1888
|
+
if (parentNode.nodeType !== ParseNodeType.StringList || parentNode.strings.length > 1) {
|
1889
|
+
return undefined;
|
1890
|
+
}
|
1891
|
+
|
1892
|
+
parentNode = parentNode.parent;
|
1893
|
+
if (!parentNode) {
|
1894
|
+
return undefined;
|
1895
|
+
}
|
1896
|
+
}
|
1897
|
+
|
1898
|
+
if (parentNode.nodeType === ParseNodeType.Argument && parentNode.parent?.nodeType === ParseNodeType.Index) {
|
1899
|
+
const priorTextInString = parseNode.nodeType === ParseNodeType.String ? priorText : '';
|
1900
|
+
if (!this._tryAddTypedDictStringLiteral(parentNode.parent, priorTextInString, postText, completionMap)) {
|
1901
|
+
const keys = this._getIndexerKeys(parentNode.parent, parseNode);
|
1902
|
+
const quoteValue = this._getQuoteInfo(priorTextInString);
|
1903
|
+
|
1904
|
+
for (const key of keys) {
|
1905
|
+
const stringLiteral = /^["|'].*["|']$/.test(key);
|
1906
|
+
if (parseNode.nodeType === ParseNodeType.String && !stringLiteral) {
|
1907
|
+
continue;
|
1908
|
+
}
|
1909
|
+
|
1910
|
+
if (stringLiteral) {
|
1911
|
+
const keyWithoutQuote = key.substr(1, key.length - 2);
|
1912
|
+
|
1913
|
+
this._addStringLiteralToCompletions(
|
1914
|
+
keyWithoutQuote,
|
1915
|
+
quoteValue.stringValue,
|
1916
|
+
postText,
|
1917
|
+
quoteValue.quoteCharacter,
|
1918
|
+
completionMap,
|
1919
|
+
dictionaryKeyDetail
|
1920
|
+
);
|
1921
|
+
} else {
|
1922
|
+
this._addNameToCompletions(key, CompletionItemKind.Constant, priorWord, completionMap, {
|
1923
|
+
sortText: this._makeSortText(SortCategory.LiteralValue, key),
|
1924
|
+
itemDetail: dictionaryKeyDetail,
|
1925
|
+
});
|
1926
|
+
}
|
1927
|
+
}
|
1928
|
+
|
1929
|
+
if (completionMap.size === 0) {
|
1930
|
+
return undefined;
|
1931
|
+
}
|
1932
|
+
}
|
1933
|
+
} else {
|
1934
|
+
debug.assert(parseNode.nodeType === ParseNodeType.String);
|
1935
|
+
|
1936
|
+
const offset = convertPositionToOffset(this._position, this._parseResults.tokenizerOutput.lines)!;
|
1937
|
+
const atArgument = parentNode.start < offset && offset < TextRange.getEnd(parseNode);
|
1938
|
+
this._addCallArgumentCompletions(parseNode, priorWord, priorText, postText, atArgument, completionMap);
|
1939
|
+
}
|
1940
|
+
|
1941
|
+
return { completionMap };
|
1942
|
+
}
|
1943
|
+
|
1944
|
+
private _addTypedDictKeys(
|
1945
|
+
dictionaryNode: DictionaryNode | SetNode,
|
1946
|
+
stringNode: StringNode | undefined,
|
1947
|
+
priorText: string,
|
1948
|
+
postText: string,
|
1949
|
+
completionMap: CompletionMap
|
1950
|
+
) {
|
1951
|
+
const expectedTypeResult = this._evaluator.getExpectedType(dictionaryNode);
|
1952
|
+
if (!expectedTypeResult) {
|
1953
|
+
return false;
|
1954
|
+
}
|
1955
|
+
|
1956
|
+
// If the expected type result is associated with a node above the
|
1957
|
+
// dictionaryNode in the parse tree, there are no typed dict keys to add.
|
1958
|
+
if (ParseTreeUtils.getNodeDepth(expectedTypeResult.node) < ParseTreeUtils.getNodeDepth(dictionaryNode)) {
|
1959
|
+
return false;
|
1960
|
+
}
|
1961
|
+
|
1962
|
+
let typedDicts: ClassType[] = [];
|
1963
|
+
|
1964
|
+
doForEachSubtype(expectedTypeResult.type, (subtype) => {
|
1965
|
+
if (isClassInstance(subtype) && ClassType.isTypedDictClass(subtype)) {
|
1966
|
+
typedDicts.push(subtype);
|
1967
|
+
}
|
1968
|
+
});
|
1969
|
+
|
1970
|
+
if (typedDicts.length === 0) {
|
1971
|
+
return false;
|
1972
|
+
}
|
1973
|
+
|
1974
|
+
const keys = this._getDictExpressionStringKeys(
|
1975
|
+
dictionaryNode,
|
1976
|
+
stringNode ? new Set([stringNode.parent?.id]) : undefined
|
1977
|
+
);
|
1978
|
+
|
1979
|
+
typedDicts = this._tryNarrowTypedDicts(typedDicts, keys);
|
1980
|
+
|
1981
|
+
const quoteValue = this._getQuoteInfo(priorText);
|
1982
|
+
const excludes = new Set(keys);
|
1983
|
+
|
1984
|
+
typedDicts.forEach((typedDict) => {
|
1985
|
+
getTypedDictMembersForClass(this._evaluator, typedDict, /* allowNarrowed */ true).forEach((_, key) => {
|
1986
|
+
// Unions of TypedDicts may define the same key.
|
1987
|
+
if (excludes.has(key) || completionMap.has(key)) {
|
1988
|
+
return;
|
1989
|
+
}
|
1990
|
+
|
1991
|
+
excludes.add(key);
|
1992
|
+
|
1993
|
+
this._addStringLiteralToCompletions(
|
1994
|
+
key,
|
1995
|
+
quoteValue ? quoteValue.stringValue : undefined,
|
1996
|
+
postText,
|
1997
|
+
quoteValue
|
1998
|
+
? quoteValue.quoteCharacter
|
1999
|
+
: this._parseResults.tokenizerOutput.predominantSingleQuoteCharacter,
|
2000
|
+
completionMap
|
2001
|
+
);
|
2002
|
+
});
|
2003
|
+
});
|
2004
|
+
|
2005
|
+
return true;
|
2006
|
+
}
|
2007
|
+
|
2008
|
+
private _tryNarrowTypedDicts(types: ClassType[], keys: string[]): ClassType[] {
|
2009
|
+
const newTypes = types.flatMap((type) => {
|
2010
|
+
const entries = getTypedDictMembersForClass(this._evaluator, type, /* allowNarrowed */ true);
|
2011
|
+
|
2012
|
+
for (let index = 0; index < keys.length; index++) {
|
2013
|
+
if (!entries.has(keys[index])) {
|
2014
|
+
return [];
|
2015
|
+
}
|
2016
|
+
}
|
2017
|
+
|
2018
|
+
return [type];
|
2019
|
+
});
|
2020
|
+
|
2021
|
+
if (newTypes.length === 0) {
|
2022
|
+
// Couldn't narrow to any typed dicts. Just include all.
|
2023
|
+
return types;
|
2024
|
+
}
|
2025
|
+
|
2026
|
+
return newTypes;
|
2027
|
+
}
|
2028
|
+
|
2029
|
+
// Find out quotation and string prefix to use for string literals
|
2030
|
+
// completion under current context.
|
2031
|
+
private _getQuoteInfo(priorText: string | undefined): {
|
2032
|
+
stringValue: string | undefined;
|
2033
|
+
quoteCharacter: string;
|
2034
|
+
} {
|
2035
|
+
let stringValue = undefined;
|
2036
|
+
let quoteCharacter = this._parseResults.tokenizerOutput.predominantSingleQuoteCharacter;
|
2037
|
+
|
2038
|
+
// If completion is not inside of the existing string literal
|
2039
|
+
// ex) typedDict[ |<= here
|
2040
|
+
// use default quotation char without any string prefix.
|
2041
|
+
if (!this._insideStringLiteral) {
|
2042
|
+
return { stringValue, quoteCharacter };
|
2043
|
+
}
|
2044
|
+
|
2045
|
+
const singleQuote = "'";
|
2046
|
+
const doubleQuote = '"';
|
2047
|
+
|
2048
|
+
// If completion is inside of string literal and has prior text
|
2049
|
+
// ex) typedDict["key |<= here
|
2050
|
+
// find quotation user has used (ex, ") and string prefix (ex, key)
|
2051
|
+
if (priorText !== undefined) {
|
2052
|
+
const lastSingleQuote = priorText.lastIndexOf(singleQuote);
|
2053
|
+
const lastDoubleQuote = priorText.lastIndexOf(doubleQuote);
|
2054
|
+
|
2055
|
+
if (lastSingleQuote > lastDoubleQuote) {
|
2056
|
+
stringValue = priorText.substr(lastSingleQuote + 1);
|
2057
|
+
quoteCharacter = singleQuote;
|
2058
|
+
} else if (lastDoubleQuote > lastSingleQuote) {
|
2059
|
+
stringValue = priorText.substr(lastDoubleQuote + 1);
|
2060
|
+
quoteCharacter = doubleQuote;
|
2061
|
+
}
|
2062
|
+
}
|
2063
|
+
|
2064
|
+
// If the string literal that completion is invoked in is f-string,
|
2065
|
+
// quotation must be the other one than one that is used for f-string.
|
2066
|
+
// ex) f"....{typedDict[|<= here ]}"
|
2067
|
+
// then quotation must be "'"
|
2068
|
+
//
|
2069
|
+
// for f-string, this code path will be only taken when completion is inside
|
2070
|
+
// of f-string segment.
|
2071
|
+
// ex) f"..{|<= here }"
|
2072
|
+
if (this._insideStringLiteral.flags & StringTokenFlags.Format) {
|
2073
|
+
quoteCharacter = this._insideStringLiteral.flags & StringTokenFlags.SingleQuote ? doubleQuote : singleQuote;
|
2074
|
+
}
|
2075
|
+
|
2076
|
+
return { stringValue, quoteCharacter };
|
2077
|
+
}
|
2078
|
+
|
2079
|
+
private _tryAddTypedDictStringLiteral(
|
2080
|
+
indexNode: IndexNode | undefined,
|
2081
|
+
priorText: string | undefined,
|
2082
|
+
postText: string | undefined,
|
2083
|
+
completionMap: CompletionMap
|
2084
|
+
) {
|
2085
|
+
if (!indexNode) {
|
2086
|
+
return false;
|
2087
|
+
}
|
2088
|
+
|
2089
|
+
const baseType = this._evaluator.getType(indexNode.baseExpression);
|
2090
|
+
if (!baseType) {
|
2091
|
+
return false;
|
2092
|
+
}
|
2093
|
+
|
2094
|
+
let foundTypedDict = false;
|
2095
|
+
|
2096
|
+
doForEachSubtype(baseType, (subtype) => {
|
2097
|
+
if (!isClassInstance(subtype)) {
|
2098
|
+
return;
|
2099
|
+
}
|
2100
|
+
|
2101
|
+
if (!ClassType.isTypedDictClass(subtype)) {
|
2102
|
+
return;
|
2103
|
+
}
|
2104
|
+
|
2105
|
+
const entries = getTypedDictMembersForClass(this._evaluator, subtype, /* allowNarrowed */ true);
|
2106
|
+
const quoteValue = this._getQuoteInfo(priorText);
|
2107
|
+
|
2108
|
+
entries.forEach((_, key) => {
|
2109
|
+
this._addStringLiteralToCompletions(
|
2110
|
+
key,
|
2111
|
+
quoteValue.stringValue,
|
2112
|
+
postText,
|
2113
|
+
quoteValue.quoteCharacter,
|
2114
|
+
completionMap
|
2115
|
+
);
|
2116
|
+
});
|
2117
|
+
|
2118
|
+
foundTypedDict = true;
|
2119
|
+
});
|
2120
|
+
|
2121
|
+
return foundTypedDict;
|
2122
|
+
}
|
2123
|
+
|
2124
|
+
private _addStringLiteralToCompletions(
|
2125
|
+
value: string,
|
2126
|
+
priorString: string | undefined,
|
2127
|
+
postText: string | undefined,
|
2128
|
+
quoteCharacter: string,
|
2129
|
+
completionMap: CompletionMap,
|
2130
|
+
detail?: string
|
2131
|
+
) {
|
2132
|
+
if (StringUtils.isPatternInSymbol(priorString || '', value)) {
|
2133
|
+
const valueWithQuotes = `${quoteCharacter}${value}${quoteCharacter}`;
|
2134
|
+
if (completionMap.has(valueWithQuotes)) {
|
2135
|
+
return;
|
2136
|
+
}
|
2137
|
+
|
2138
|
+
const completionItem = CompletionItem.create(valueWithQuotes);
|
2139
|
+
|
2140
|
+
completionItem.kind = CompletionItemKind.Constant;
|
2141
|
+
completionItem.sortText = this._makeSortText(SortCategory.LiteralValue, valueWithQuotes);
|
2142
|
+
let rangeStartCol = this._position.character;
|
2143
|
+
if (priorString !== undefined) {
|
2144
|
+
rangeStartCol -= priorString.length + 1;
|
2145
|
+
}
|
2146
|
+
|
2147
|
+
// If the text after the insertion point is the closing quote,
|
2148
|
+
// replace it.
|
2149
|
+
let rangeEndCol = this._position.character;
|
2150
|
+
if (postText !== undefined) {
|
2151
|
+
if (postText.startsWith(quoteCharacter)) {
|
2152
|
+
rangeEndCol++;
|
2153
|
+
}
|
2154
|
+
}
|
2155
|
+
|
2156
|
+
const range: Range = {
|
2157
|
+
start: { line: this._position.line, character: rangeStartCol },
|
2158
|
+
end: { line: this._position.line, character: rangeEndCol },
|
2159
|
+
};
|
2160
|
+
completionItem.textEdit = TextEdit.replace(range, valueWithQuotes);
|
2161
|
+
completionItem.detail = detail;
|
2162
|
+
|
2163
|
+
completionMap.set(completionItem);
|
2164
|
+
}
|
2165
|
+
}
|
2166
|
+
|
2167
|
+
private _addAutoImportCompletions(
|
2168
|
+
priorWord: string,
|
2169
|
+
similarityLimit: number,
|
2170
|
+
lazyEdit: boolean,
|
2171
|
+
completionResults: CompletionResults
|
2172
|
+
) {
|
2173
|
+
if (
|
2174
|
+
!completionResults.completionMap ||
|
2175
|
+
!this._configOptions.autoImportCompletions ||
|
2176
|
+
!this._options.autoImport
|
2177
|
+
) {
|
2178
|
+
// If auto import on the server is turned off or this particular invocation
|
2179
|
+
// is turned off (ex, notebook), don't do any thing.
|
2180
|
+
return;
|
2181
|
+
}
|
2182
|
+
|
2183
|
+
const moduleSymbolMap = this._autoImportMaps.getModuleSymbolsMap();
|
2184
|
+
|
2185
|
+
const autoImporter = new AutoImporter(
|
2186
|
+
this._execEnv,
|
2187
|
+
this._importResolver,
|
2188
|
+
this._parseResults,
|
2189
|
+
this._position,
|
2190
|
+
completionResults.completionMap,
|
2191
|
+
moduleSymbolMap,
|
2192
|
+
{ libraryMap: this._autoImportMaps.libraryMap, lazyEdit }
|
2193
|
+
);
|
2194
|
+
|
2195
|
+
const results: AutoImportResult[] = [];
|
2196
|
+
const info = this._autoImportMaps.nameMap?.get(priorWord);
|
2197
|
+
if (info && priorWord.length > 1 && !completionResults.completionMap.has(priorWord)) {
|
2198
|
+
appendArray(results, autoImporter.getAutoImportCandidatesForAbbr(priorWord, info, this._cancellationToken));
|
2199
|
+
}
|
2200
|
+
|
2201
|
+
results.push(
|
2202
|
+
...autoImporter.getAutoImportCandidates(
|
2203
|
+
priorWord,
|
2204
|
+
similarityLimit,
|
2205
|
+
/* abbrFromUsers */ undefined,
|
2206
|
+
this._cancellationToken
|
2207
|
+
)
|
2208
|
+
);
|
2209
|
+
|
2210
|
+
const perfInfo = autoImporter.getPerfInfo();
|
2211
|
+
|
2212
|
+
const additionDuration = new Duration();
|
2213
|
+
for (const result of results) {
|
2214
|
+
if (result.symbol) {
|
2215
|
+
this._addSymbol(result.name, result.symbol, priorWord, completionResults.completionMap, {
|
2216
|
+
autoImportSource: result.source,
|
2217
|
+
autoImportAlias: result.alias,
|
2218
|
+
edits: {
|
2219
|
+
textEdit: this._createReplaceEdits(priorWord, /* node */ undefined, result.insertionText),
|
2220
|
+
additionalTextEdits: result.edits,
|
2221
|
+
},
|
2222
|
+
});
|
2223
|
+
} else {
|
2224
|
+
this._addNameToCompletions(
|
2225
|
+
result.alias ?? result.name,
|
2226
|
+
result.kind ?? CompletionItemKind.Module,
|
2227
|
+
priorWord,
|
2228
|
+
completionResults.completionMap,
|
2229
|
+
{
|
2230
|
+
autoImportText: this._getAutoImportText(result.name, result.source, result.alias),
|
2231
|
+
edits: {
|
2232
|
+
textEdit: this._createReplaceEdits(priorWord, /* node */ undefined, result.insertionText),
|
2233
|
+
additionalTextEdits: result.edits,
|
2234
|
+
},
|
2235
|
+
}
|
2236
|
+
);
|
2237
|
+
}
|
2238
|
+
}
|
2239
|
+
|
2240
|
+
completionResults.autoImportInfo = {
|
2241
|
+
indexUsed: perfInfo.indexUsed,
|
2242
|
+
totalTimeInMS: perfInfo.totalInMs,
|
2243
|
+
|
2244
|
+
moduleTimeInMS: perfInfo.moduleTimeInMS,
|
2245
|
+
indexTimeInMS: perfInfo.indexTimeInMS,
|
2246
|
+
importAliasTimeInMS: perfInfo.importAliasTimeInMS,
|
2247
|
+
|
2248
|
+
itemCount: results.length,
|
2249
|
+
symbolCount: perfInfo.symbolCount,
|
2250
|
+
indexCount: perfInfo.indexCount,
|
2251
|
+
importAliasCount: perfInfo.importAliasCount,
|
2252
|
+
|
2253
|
+
additionTimeInMS: additionDuration.getDurationInMilliseconds(),
|
2254
|
+
};
|
2255
|
+
}
|
2256
|
+
|
2257
|
+
private _getImportFromCompletions(
|
2258
|
+
importFromNode: ImportFromNode,
|
2259
|
+
priorWord: string
|
2260
|
+
): CompletionResults | undefined {
|
2261
|
+
// Don't attempt to provide completions for "from X import *".
|
2262
|
+
if (importFromNode.isWildcardImport) {
|
2263
|
+
return undefined;
|
2264
|
+
}
|
2265
|
+
|
2266
|
+
// Access the imported module information, which is hanging
|
2267
|
+
// off the ImportFromNode.
|
2268
|
+
const importInfo = AnalyzerNodeInfo.getImportInfo(importFromNode.module);
|
2269
|
+
if (!importInfo) {
|
2270
|
+
return undefined;
|
2271
|
+
}
|
2272
|
+
|
2273
|
+
const completionMap = new CompletionMap();
|
2274
|
+
|
2275
|
+
const resolvedPath =
|
2276
|
+
importInfo.resolvedPaths.length > 0 ? importInfo.resolvedPaths[importInfo.resolvedPaths.length - 1] : '';
|
2277
|
+
|
2278
|
+
const lookupResults = this._importLookup(resolvedPath);
|
2279
|
+
if (lookupResults) {
|
2280
|
+
this._addSymbolsForSymbolTable(
|
2281
|
+
lookupResults.symbolTable,
|
2282
|
+
(symbol, name) => {
|
2283
|
+
// Don't suggest built in symbols or ones that have already been imported.
|
2284
|
+
return (
|
2285
|
+
symbol.getDeclarations().some((d) => !isIntrinsicDeclaration(d)) &&
|
2286
|
+
!importFromNode.imports.find((imp) => imp.name.value === name)
|
2287
|
+
);
|
2288
|
+
},
|
2289
|
+
priorWord,
|
2290
|
+
/* isInImport */ true,
|
2291
|
+
/* boundObject */ undefined,
|
2292
|
+
completionMap
|
2293
|
+
);
|
2294
|
+
}
|
2295
|
+
|
2296
|
+
// Add the implicit imports.
|
2297
|
+
importInfo.implicitImports.forEach((implImport) => {
|
2298
|
+
if (!importFromNode.imports.find((imp) => imp.name.value === implImport.name)) {
|
2299
|
+
this._addNameToCompletions(implImport.name, CompletionItemKind.Module, priorWord, completionMap);
|
2300
|
+
}
|
2301
|
+
});
|
2302
|
+
|
2303
|
+
return { completionMap };
|
2304
|
+
}
|
2305
|
+
|
2306
|
+
private _findMatchingKeywords(keywordList: string[], partialMatch: string): string[] {
|
2307
|
+
return keywordList.filter((keyword) => {
|
2308
|
+
if (partialMatch) {
|
2309
|
+
return StringUtils.isPatternInSymbol(partialMatch, keyword);
|
2310
|
+
} else {
|
2311
|
+
return true;
|
2312
|
+
}
|
2313
|
+
});
|
2314
|
+
}
|
2315
|
+
|
2316
|
+
private _addNamedParameters(signatureInfo: CallSignatureInfo, priorWord: string, completionMap: CompletionMap) {
|
2317
|
+
const argNameMap = new Map<string, string>();
|
2318
|
+
|
2319
|
+
signatureInfo.signatures.forEach((signature) => {
|
2320
|
+
this._addNamedParametersToMap(signature.type, argNameMap);
|
2321
|
+
});
|
2322
|
+
|
2323
|
+
// Remove any named parameters that are already provided.
|
2324
|
+
signatureInfo.callNode.arguments!.forEach((arg) => {
|
2325
|
+
if (arg.name) {
|
2326
|
+
argNameMap.delete(arg.name.value);
|
2327
|
+
}
|
2328
|
+
});
|
2329
|
+
|
2330
|
+
// Add the remaining unique parameter names to the completion list.
|
2331
|
+
argNameMap.forEach((argName) => {
|
2332
|
+
if (StringUtils.isPatternInSymbol(priorWord, argName)) {
|
2333
|
+
const label = argName + '=';
|
2334
|
+
if (completionMap.has(label)) {
|
2335
|
+
return;
|
2336
|
+
}
|
2337
|
+
|
2338
|
+
const completionItem = CompletionItem.create(label);
|
2339
|
+
completionItem.kind = CompletionItemKind.Variable;
|
2340
|
+
|
2341
|
+
const completionItemData: CompletionItemData = {
|
2342
|
+
workspacePath: this._workspacePath,
|
2343
|
+
filePath: this._filePath,
|
2344
|
+
position: this._position,
|
2345
|
+
};
|
2346
|
+
completionItem.data = toLSPAny(completionItemData);
|
2347
|
+
completionItem.sortText = this._makeSortText(SortCategory.NamedParameter, argName);
|
2348
|
+
completionItem.filterText = argName;
|
2349
|
+
|
2350
|
+
completionMap.set(completionItem);
|
2351
|
+
}
|
2352
|
+
});
|
2353
|
+
}
|
2354
|
+
|
2355
|
+
private _addNamedParametersToMap(type: FunctionType, paramMap: Map<string, string>) {
|
2356
|
+
type.details.parameters.forEach((param) => {
|
2357
|
+
if (param.name && !param.isNameSynthesized) {
|
2358
|
+
// Don't add private or protected names. These are assumed
|
2359
|
+
// not to be named parameters.
|
2360
|
+
if (!SymbolNameUtils.isPrivateOrProtectedName(param.name)) {
|
2361
|
+
paramMap.set(param.name, param.name);
|
2362
|
+
}
|
2363
|
+
}
|
2364
|
+
});
|
2365
|
+
}
|
2366
|
+
|
2367
|
+
private _addSymbols(node: ParseNode, priorWord: string, completionMap: CompletionMap) {
|
2368
|
+
let curNode: ParseNode | undefined = node;
|
2369
|
+
|
2370
|
+
while (curNode) {
|
2371
|
+
// Does this node have a scope associated with it?
|
2372
|
+
let scope = getScopeForNode(curNode);
|
2373
|
+
if (scope) {
|
2374
|
+
while (scope) {
|
2375
|
+
this._addSymbolsForSymbolTable(
|
2376
|
+
scope.symbolTable,
|
2377
|
+
() => true,
|
2378
|
+
priorWord,
|
2379
|
+
/* isInImport */ false,
|
2380
|
+
/* boundObject */ undefined,
|
2381
|
+
completionMap
|
2382
|
+
);
|
2383
|
+
scope = scope.parent;
|
2384
|
+
}
|
2385
|
+
|
2386
|
+
// If this is a class scope, add symbols from parent classes.
|
2387
|
+
if (curNode.nodeType === ParseNodeType.Class) {
|
2388
|
+
const classType = this._evaluator.getTypeOfClass(curNode);
|
2389
|
+
if (classType && isInstantiableClass(classType.classType)) {
|
2390
|
+
classType.classType.details.mro.forEach((baseClass, index) => {
|
2391
|
+
if (isInstantiableClass(baseClass)) {
|
2392
|
+
this._addSymbolsForSymbolTable(
|
2393
|
+
baseClass.details.fields,
|
2394
|
+
(symbol) => {
|
2395
|
+
if (!symbol.isClassMember()) {
|
2396
|
+
return false;
|
2397
|
+
}
|
2398
|
+
|
2399
|
+
// Return only variables, not methods or classes.
|
2400
|
+
return symbol
|
2401
|
+
.getDeclarations()
|
2402
|
+
.some((decl) => decl.type === DeclarationType.Variable);
|
2403
|
+
},
|
2404
|
+
priorWord,
|
2405
|
+
/* isInImport */ false,
|
2406
|
+
/* boundObject */ undefined,
|
2407
|
+
completionMap
|
2408
|
+
);
|
2409
|
+
}
|
2410
|
+
});
|
2411
|
+
}
|
2412
|
+
}
|
2413
|
+
break;
|
2414
|
+
}
|
2415
|
+
|
2416
|
+
curNode = curNode.parent;
|
2417
|
+
}
|
2418
|
+
}
|
2419
|
+
|
2420
|
+
private _addSymbolsForSymbolTable(
|
2421
|
+
symbolTable: SymbolTable,
|
2422
|
+
includeSymbolCallback: (symbol: Symbol, name: string) => boolean,
|
2423
|
+
priorWord: string,
|
2424
|
+
isInImport: boolean,
|
2425
|
+
boundObjectOrClass: ClassType | undefined,
|
2426
|
+
completionMap: CompletionMap
|
2427
|
+
) {
|
2428
|
+
symbolTable.forEach((symbol, name) => {
|
2429
|
+
// If there are no declarations or the symbol is not
|
2430
|
+
// exported from this scope, don't include it in the
|
2431
|
+
// suggestion list unless we are in the same file.
|
2432
|
+
const hidden =
|
2433
|
+
symbol.isExternallyHidden() &&
|
2434
|
+
!symbol.getDeclarations().some((d) => isDefinedInFile(d, this._filePath));
|
2435
|
+
if (!hidden && includeSymbolCallback(symbol, name)) {
|
2436
|
+
// Don't add a symbol more than once. It may have already been
|
2437
|
+
// added from an inner scope's symbol table.
|
2438
|
+
if (!completionMap.has(name)) {
|
2439
|
+
this._addSymbol(name, symbol, priorWord, completionMap, {
|
2440
|
+
boundObjectOrClass,
|
2441
|
+
funcParensDisabled: isInImport,
|
2442
|
+
});
|
2443
|
+
}
|
2444
|
+
}
|
2445
|
+
});
|
2446
|
+
}
|
2447
|
+
|
2448
|
+
private _addSymbol(
|
2449
|
+
name: string,
|
2450
|
+
symbol: Symbol,
|
2451
|
+
priorWord: string,
|
2452
|
+
completionMap: CompletionMap,
|
2453
|
+
detail: SymbolDetail
|
2454
|
+
) {
|
2455
|
+
// If the symbol is a py.typed import that is not supposed to be re-exported,
|
2456
|
+
// don't offer it as a completion suggestion.
|
2457
|
+
if (symbol.isPrivatePyTypedImport()) {
|
2458
|
+
return;
|
2459
|
+
}
|
2460
|
+
|
2461
|
+
let primaryDecl = getLastTypedDeclaredForSymbol(symbol);
|
2462
|
+
if (!primaryDecl) {
|
2463
|
+
const declarations = symbol.getDeclarations();
|
2464
|
+
if (declarations.length > 0) {
|
2465
|
+
primaryDecl = declarations[declarations.length - 1];
|
2466
|
+
}
|
2467
|
+
}
|
2468
|
+
|
2469
|
+
if (primaryDecl) {
|
2470
|
+
let itemKind: CompletionItemKind = CompletionItemKind.Variable;
|
2471
|
+
|
2472
|
+
primaryDecl = this._evaluator.resolveAliasDeclaration(primaryDecl, /* resolveLocalNames */ true);
|
2473
|
+
if (primaryDecl) {
|
2474
|
+
itemKind = this._convertDeclarationTypeToItemKind(primaryDecl);
|
2475
|
+
|
2476
|
+
// Handle enum members specially. Enum members normally look like
|
2477
|
+
// variables, but the are declared using assignment expressions
|
2478
|
+
// within an enum class.
|
2479
|
+
if (
|
2480
|
+
primaryDecl.type === DeclarationType.Variable &&
|
2481
|
+
detail.boundObjectOrClass &&
|
2482
|
+
isInstantiableClass(detail.boundObjectOrClass) &&
|
2483
|
+
ClassType.isEnumClass(detail.boundObjectOrClass) &&
|
2484
|
+
primaryDecl.node.parent?.nodeType === ParseNodeType.Assignment
|
2485
|
+
) {
|
2486
|
+
itemKind = CompletionItemKind.EnumMember;
|
2487
|
+
}
|
2488
|
+
|
2489
|
+
// Are we resolving a completion item? If so, see if this symbol
|
2490
|
+
// is the one that we're trying to match.
|
2491
|
+
if (this._itemToResolve) {
|
2492
|
+
const completionItemData = fromLSPAny<CompletionItemData>(this._itemToResolve.data);
|
2493
|
+
|
2494
|
+
if (completionItemData.symbolLabel === name && !completionItemData.autoImportText) {
|
2495
|
+
// This call can be expensive to perform on every completion item
|
2496
|
+
// that we return, so we do it lazily in the "resolve" callback.
|
2497
|
+
const type = this._evaluator.getEffectiveTypeOfSymbol(symbol);
|
2498
|
+
if (type) {
|
2499
|
+
let typeDetail: string | undefined;
|
2500
|
+
let documentation: string | undefined;
|
2501
|
+
|
2502
|
+
switch (primaryDecl.type) {
|
2503
|
+
case DeclarationType.Intrinsic:
|
2504
|
+
case DeclarationType.Variable:
|
2505
|
+
case DeclarationType.Parameter: {
|
2506
|
+
let expandTypeAlias = false;
|
2507
|
+
if (type && TypeBase.isInstantiable(type)) {
|
2508
|
+
const typeAliasInfo = getTypeAliasInfo(type);
|
2509
|
+
if (typeAliasInfo) {
|
2510
|
+
if (typeAliasInfo.name === name) {
|
2511
|
+
expandTypeAlias = true;
|
2512
|
+
}
|
2513
|
+
}
|
2514
|
+
}
|
2515
|
+
typeDetail = name + ': ' + this._evaluator.printType(type, expandTypeAlias);
|
2516
|
+
break;
|
2517
|
+
}
|
2518
|
+
|
2519
|
+
case DeclarationType.Function: {
|
2520
|
+
const functionType =
|
2521
|
+
detail.boundObjectOrClass && (isFunction(type) || isOverloadedFunction(type))
|
2522
|
+
? this._evaluator.bindFunctionToClassOrObject(
|
2523
|
+
detail.boundObjectOrClass,
|
2524
|
+
type
|
2525
|
+
)
|
2526
|
+
: type;
|
2527
|
+
if (functionType) {
|
2528
|
+
if (
|
2529
|
+
isProperty(functionType) &&
|
2530
|
+
detail.boundObjectOrClass &&
|
2531
|
+
isClassInstance(detail.boundObjectOrClass)
|
2532
|
+
) {
|
2533
|
+
const propertyType =
|
2534
|
+
this._evaluator.getGetterTypeFromProperty(
|
2535
|
+
functionType as ClassType,
|
2536
|
+
/* inferTypeIfNeeded */ true
|
2537
|
+
) || UnknownType.create();
|
2538
|
+
typeDetail =
|
2539
|
+
name +
|
2540
|
+
': ' +
|
2541
|
+
this._evaluator.printType(propertyType, /* expandTypeAlias */ false) +
|
2542
|
+
' (property)';
|
2543
|
+
} else if (isOverloadedFunction(functionType)) {
|
2544
|
+
// 35 is completion tooltip's default width size
|
2545
|
+
typeDetail = getOverloadedFunctionTooltip(
|
2546
|
+
functionType,
|
2547
|
+
this._evaluator,
|
2548
|
+
/* columnThreshold */ 35
|
2549
|
+
);
|
2550
|
+
} else {
|
2551
|
+
typeDetail =
|
2552
|
+
name +
|
2553
|
+
': ' +
|
2554
|
+
this._evaluator.printType(functionType, /* expandTypeAlias */ false);
|
2555
|
+
}
|
2556
|
+
}
|
2557
|
+
break;
|
2558
|
+
}
|
2559
|
+
|
2560
|
+
case DeclarationType.Class:
|
2561
|
+
case DeclarationType.SpecialBuiltInClass: {
|
2562
|
+
typeDetail = 'class ' + name + '()';
|
2563
|
+
break;
|
2564
|
+
}
|
2565
|
+
|
2566
|
+
case DeclarationType.Alias: {
|
2567
|
+
typeDetail = name;
|
2568
|
+
if (primaryDecl.path) {
|
2569
|
+
const lookupResults = this._importLookup(primaryDecl.path);
|
2570
|
+
if (lookupResults) {
|
2571
|
+
documentation = lookupResults.docString;
|
2572
|
+
}
|
2573
|
+
}
|
2574
|
+
break;
|
2575
|
+
}
|
2576
|
+
|
2577
|
+
default: {
|
2578
|
+
typeDetail = name;
|
2579
|
+
break;
|
2580
|
+
}
|
2581
|
+
}
|
2582
|
+
|
2583
|
+
if (
|
2584
|
+
primaryDecl.type === DeclarationType.Variable &&
|
2585
|
+
primaryDecl.typeAliasName &&
|
2586
|
+
primaryDecl.docString
|
2587
|
+
) {
|
2588
|
+
documentation = primaryDecl.docString;
|
2589
|
+
} else if (isModule(type)) {
|
2590
|
+
documentation = getModuleDocString(type, primaryDecl, this._sourceMapper);
|
2591
|
+
} else if (isInstantiableClass(type)) {
|
2592
|
+
documentation = getClassDocString(type, primaryDecl, this._sourceMapper);
|
2593
|
+
} else if (isFunction(type)) {
|
2594
|
+
const functionType = detail.boundObjectOrClass
|
2595
|
+
? this._evaluator.bindFunctionToClassOrObject(detail.boundObjectOrClass, type)
|
2596
|
+
: type;
|
2597
|
+
if (functionType && isFunction(functionType)) {
|
2598
|
+
documentation = getFunctionDocStringFromType(
|
2599
|
+
functionType,
|
2600
|
+
this._sourceMapper,
|
2601
|
+
this._evaluator
|
2602
|
+
);
|
2603
|
+
}
|
2604
|
+
} else if (isOverloadedFunction(type)) {
|
2605
|
+
const functionType = detail.boundObjectOrClass
|
2606
|
+
? this._evaluator.bindFunctionToClassOrObject(detail.boundObjectOrClass, type)
|
2607
|
+
: type;
|
2608
|
+
if (functionType && isOverloadedFunction(functionType)) {
|
2609
|
+
documentation = getOverloadedFunctionDocStringsFromType(
|
2610
|
+
functionType,
|
2611
|
+
this._sourceMapper,
|
2612
|
+
this._evaluator
|
2613
|
+
).find((doc) => doc);
|
2614
|
+
}
|
2615
|
+
} else if (primaryDecl?.type === DeclarationType.Function) {
|
2616
|
+
// @property functions
|
2617
|
+
documentation = getPropertyDocStringInherited(
|
2618
|
+
primaryDecl,
|
2619
|
+
this._sourceMapper,
|
2620
|
+
this._evaluator
|
2621
|
+
);
|
2622
|
+
} else if (primaryDecl?.type === DeclarationType.Variable) {
|
2623
|
+
const decl = (symbol
|
2624
|
+
.getDeclarations()
|
2625
|
+
.find((d) => d.type === DeclarationType.Variable && !!d.docString) ??
|
2626
|
+
primaryDecl) as VariableDeclaration;
|
2627
|
+
documentation = getVariableDocString(decl, this._sourceMapper);
|
2628
|
+
}
|
2629
|
+
|
2630
|
+
if (this._options.format === MarkupKind.Markdown) {
|
2631
|
+
let markdownString = '```python\n' + typeDetail + '\n```\n';
|
2632
|
+
|
2633
|
+
if (documentation) {
|
2634
|
+
markdownString += '---\n';
|
2635
|
+
markdownString += convertDocStringToMarkdown(documentation);
|
2636
|
+
}
|
2637
|
+
|
2638
|
+
markdownString = markdownString.trimEnd();
|
2639
|
+
|
2640
|
+
this._itemToResolve.documentation = {
|
2641
|
+
kind: MarkupKind.Markdown,
|
2642
|
+
value: markdownString,
|
2643
|
+
};
|
2644
|
+
} else if (this._options.format === MarkupKind.PlainText) {
|
2645
|
+
let plainTextString = typeDetail + '\n';
|
2646
|
+
|
2647
|
+
if (documentation) {
|
2648
|
+
plainTextString += '\n';
|
2649
|
+
plainTextString += convertDocStringToPlainText(documentation);
|
2650
|
+
}
|
2651
|
+
|
2652
|
+
plainTextString = plainTextString.trimEnd();
|
2653
|
+
|
2654
|
+
this._itemToResolve.documentation = {
|
2655
|
+
kind: MarkupKind.PlainText,
|
2656
|
+
value: plainTextString,
|
2657
|
+
};
|
2658
|
+
} else {
|
2659
|
+
fail(`Unsupported markup type: ${this._options.format}`);
|
2660
|
+
}
|
2661
|
+
}
|
2662
|
+
}
|
2663
|
+
}
|
2664
|
+
}
|
2665
|
+
|
2666
|
+
const autoImportText = detail.autoImportSource
|
2667
|
+
? this._getAutoImportText(name, detail.autoImportSource, detail.autoImportAlias)
|
2668
|
+
: undefined;
|
2669
|
+
|
2670
|
+
this._addNameToCompletions(detail.autoImportAlias ?? name, itemKind, priorWord, completionMap, {
|
2671
|
+
autoImportText,
|
2672
|
+
funcParensDisabled: detail.funcParensDisabled,
|
2673
|
+
edits: detail.edits,
|
2674
|
+
});
|
2675
|
+
} else {
|
2676
|
+
// Does the symbol have no declaration but instead has a synthesized type?
|
2677
|
+
const synthesizedType = symbol.getSynthesizedType();
|
2678
|
+
if (synthesizedType) {
|
2679
|
+
const itemKind: CompletionItemKind = CompletionItemKind.Variable;
|
2680
|
+
this._addNameToCompletions(name, itemKind, priorWord, completionMap, {
|
2681
|
+
funcParensDisabled: detail.funcParensDisabled,
|
2682
|
+
edits: detail.edits,
|
2683
|
+
});
|
2684
|
+
}
|
2685
|
+
}
|
2686
|
+
}
|
2687
|
+
|
2688
|
+
private _getAutoImportText(importName: string, importFrom?: string, importAlias?: string) {
|
2689
|
+
const autoImportText = getAutoImportText(importName, importFrom, importAlias);
|
2690
|
+
|
2691
|
+
let importText = '';
|
2692
|
+
if (this._options.format === MarkupKind.Markdown) {
|
2693
|
+
importText = `\`\`\`\n${autoImportText}\n\`\`\``;
|
2694
|
+
} else if (this._options.format === MarkupKind.PlainText) {
|
2695
|
+
importText = autoImportText;
|
2696
|
+
} else {
|
2697
|
+
fail(`Unsupported markup type: ${this._options.format}`);
|
2698
|
+
}
|
2699
|
+
|
2700
|
+
return {
|
2701
|
+
source: importFrom ?? '',
|
2702
|
+
importText,
|
2703
|
+
};
|
2704
|
+
}
|
2705
|
+
|
2706
|
+
private _addNameToCompletions(
|
2707
|
+
name: string,
|
2708
|
+
itemKind: CompletionItemKind,
|
2709
|
+
filter: string,
|
2710
|
+
completionMap: CompletionMap,
|
2711
|
+
detail?: CompletionDetail
|
2712
|
+
) {
|
2713
|
+
// Auto importer already filtered out unnecessary ones. No need to do it again.
|
2714
|
+
const similarity = detail?.autoImportText ? true : StringUtils.isPatternInSymbol(filter, name);
|
2715
|
+
if (!similarity) {
|
2716
|
+
return;
|
2717
|
+
}
|
2718
|
+
|
2719
|
+
if (
|
2720
|
+
completionMap.has(name, CompletionMap.matchKindAndImportText, itemKind, detail?.autoImportText?.importText)
|
2721
|
+
) {
|
2722
|
+
return;
|
2723
|
+
}
|
2724
|
+
|
2725
|
+
const completionItem = CompletionItem.create(name);
|
2726
|
+
completionItem.kind = itemKind;
|
2727
|
+
|
2728
|
+
const completionItemData: CompletionItemData = {
|
2729
|
+
workspacePath: this._workspacePath,
|
2730
|
+
filePath: this._filePath,
|
2731
|
+
position: this._position,
|
2732
|
+
};
|
2733
|
+
|
2734
|
+
if (detail?.funcParensDisabled) {
|
2735
|
+
completionItemData.funcParensDisabled = true;
|
2736
|
+
}
|
2737
|
+
|
2738
|
+
completionItem.data = toLSPAny(completionItemData);
|
2739
|
+
|
2740
|
+
if (detail?.sortText || detail?.itemDetail) {
|
2741
|
+
completionItem.sortText = detail.sortText;
|
2742
|
+
completionItem.detail = detail.itemDetail;
|
2743
|
+
} else if (detail?.autoImportText) {
|
2744
|
+
// Force auto-import entries to the end.
|
2745
|
+
completionItem.sortText = this._makeSortText(
|
2746
|
+
SortCategory.AutoImport,
|
2747
|
+
name,
|
2748
|
+
detail.autoImportText.importText
|
2749
|
+
);
|
2750
|
+
completionItemData.autoImportText = detail.autoImportText.importText;
|
2751
|
+
completionItem.detail = autoImportDetail;
|
2752
|
+
|
2753
|
+
if (detail.autoImportText.source) {
|
2754
|
+
completionItem.labelDetails = { description: detail.autoImportText.source };
|
2755
|
+
}
|
2756
|
+
} else if (itemKind === CompletionItemKind.EnumMember) {
|
2757
|
+
// Handle enum members separately so they are sorted above other symbols.
|
2758
|
+
completionItem.sortText = this._makeSortText(SortCategory.EnumMember, name);
|
2759
|
+
} else if (SymbolNameUtils.isDunderName(name)) {
|
2760
|
+
// Force dunder-named symbols to appear after all other symbols.
|
2761
|
+
completionItem.sortText = this._makeSortText(SortCategory.DunderSymbol, name);
|
2762
|
+
} else if (filter === '' && SymbolNameUtils.isPrivateOrProtectedName(name)) {
|
2763
|
+
// Distinguish between normal and private symbols only if there is
|
2764
|
+
// currently no filter text. Once we get a single character to filter
|
2765
|
+
// upon, we'll no longer differentiate.
|
2766
|
+
completionItem.sortText = this._makeSortText(SortCategory.PrivateSymbol, name);
|
2767
|
+
} else {
|
2768
|
+
completionItem.sortText = this._makeSortText(SortCategory.NormalSymbol, name);
|
2769
|
+
}
|
2770
|
+
|
2771
|
+
completionItemData.symbolLabel = name;
|
2772
|
+
|
2773
|
+
if (this._options.format === MarkupKind.Markdown) {
|
2774
|
+
let markdownString = '';
|
2775
|
+
|
2776
|
+
if (detail?.autoImportText) {
|
2777
|
+
markdownString += detail.autoImportText.importText;
|
2778
|
+
if (detail.typeDetail || detail.documentation) {
|
2779
|
+
// Micro perf optimization to not create new string from trimEnd.
|
2780
|
+
markdownString += '\n\n';
|
2781
|
+
}
|
2782
|
+
}
|
2783
|
+
|
2784
|
+
if (detail?.typeDetail) {
|
2785
|
+
markdownString += '```python\n' + detail.typeDetail + '\n```\n';
|
2786
|
+
}
|
2787
|
+
|
2788
|
+
if (detail?.documentation) {
|
2789
|
+
markdownString += '---\n';
|
2790
|
+
markdownString += convertDocStringToMarkdown(detail.documentation);
|
2791
|
+
}
|
2792
|
+
|
2793
|
+
markdownString = markdownString.trimEnd();
|
2794
|
+
|
2795
|
+
if (markdownString) {
|
2796
|
+
completionItem.documentation = {
|
2797
|
+
kind: MarkupKind.Markdown,
|
2798
|
+
value: markdownString,
|
2799
|
+
};
|
2800
|
+
}
|
2801
|
+
} else if (this._options.format === MarkupKind.PlainText) {
|
2802
|
+
let plainTextString = '';
|
2803
|
+
|
2804
|
+
if (detail?.autoImportText) {
|
2805
|
+
plainTextString += detail.autoImportText.importText;
|
2806
|
+
if (detail.typeDetail || detail.documentation) {
|
2807
|
+
// Micro perf optimization to not create new string from trimEnd.
|
2808
|
+
plainTextString += '\n\n';
|
2809
|
+
}
|
2810
|
+
}
|
2811
|
+
|
2812
|
+
if (detail?.typeDetail) {
|
2813
|
+
plainTextString += detail.typeDetail + '\n';
|
2814
|
+
}
|
2815
|
+
|
2816
|
+
if (detail?.documentation) {
|
2817
|
+
plainTextString += '\n' + convertDocStringToPlainText(detail.documentation);
|
2818
|
+
}
|
2819
|
+
|
2820
|
+
plainTextString = plainTextString.trimEnd();
|
2821
|
+
|
2822
|
+
if (plainTextString) {
|
2823
|
+
completionItem.documentation = {
|
2824
|
+
kind: MarkupKind.PlainText,
|
2825
|
+
value: plainTextString,
|
2826
|
+
};
|
2827
|
+
}
|
2828
|
+
} else {
|
2829
|
+
fail(`Unsupported markup type: ${this._options.format}`);
|
2830
|
+
}
|
2831
|
+
|
2832
|
+
if (detail?.edits?.format) {
|
2833
|
+
completionItem.insertTextFormat = detail.edits.format;
|
2834
|
+
}
|
2835
|
+
|
2836
|
+
if (detail?.edits?.textEdit) {
|
2837
|
+
completionItem.textEdit = detail.edits.textEdit;
|
2838
|
+
}
|
2839
|
+
|
2840
|
+
if (detail?.edits?.additionalTextEdits) {
|
2841
|
+
completionItem.additionalTextEdits = detail.edits.additionalTextEdits.map((te) => {
|
2842
|
+
const textEdit: TextEdit = {
|
2843
|
+
range: {
|
2844
|
+
start: { line: te.range.start.line, character: te.range.start.character },
|
2845
|
+
end: { line: te.range.end.line, character: te.range.end.character },
|
2846
|
+
},
|
2847
|
+
newText: te.replacementText,
|
2848
|
+
};
|
2849
|
+
return textEdit;
|
2850
|
+
});
|
2851
|
+
|
2852
|
+
if (this._itemToResolve) {
|
2853
|
+
const data = fromLSPAny<CompletionItemData>(this._itemToResolve.data);
|
2854
|
+
if (data.autoImportText === completionItemData.autoImportText) {
|
2855
|
+
this._itemToResolve.additionalTextEdits = completionItem.additionalTextEdits;
|
2856
|
+
}
|
2857
|
+
}
|
2858
|
+
}
|
2859
|
+
|
2860
|
+
completionMap.set(completionItem);
|
2861
|
+
}
|
2862
|
+
|
2863
|
+
private _getRecentListIndex(name: string, autoImportText: string) {
|
2864
|
+
return CompletionProvider._mostRecentCompletions.findIndex(
|
2865
|
+
(item) => item.label === name && item.autoImportText === autoImportText
|
2866
|
+
);
|
2867
|
+
}
|
2868
|
+
|
2869
|
+
private _makeSortText(sortCategory: SortCategory, name: string, autoImportText = ''): string {
|
2870
|
+
const recentListIndex = this._getRecentListIndex(name, autoImportText);
|
2871
|
+
|
2872
|
+
// If the label is in the recent list, modify the category
|
2873
|
+
// so it appears higher in our list.
|
2874
|
+
if (recentListIndex >= 0) {
|
2875
|
+
if (sortCategory === SortCategory.AutoImport) {
|
2876
|
+
sortCategory = SortCategory.RecentAutoImport;
|
2877
|
+
} else if (sortCategory === SortCategory.ImportModuleName) {
|
2878
|
+
sortCategory = SortCategory.RecentImportModuleName;
|
2879
|
+
} else if (
|
2880
|
+
sortCategory === SortCategory.Keyword ||
|
2881
|
+
sortCategory === SortCategory.NormalSymbol ||
|
2882
|
+
sortCategory === SortCategory.PrivateSymbol ||
|
2883
|
+
sortCategory === SortCategory.DunderSymbol
|
2884
|
+
) {
|
2885
|
+
sortCategory = SortCategory.RecentKeywordOrSymbol;
|
2886
|
+
}
|
2887
|
+
}
|
2888
|
+
|
2889
|
+
// Generate a sort string of the format
|
2890
|
+
// XX.YYYY.name
|
2891
|
+
// where XX is the sort category
|
2892
|
+
// and YYYY is the index of the item in the MRU list
|
2893
|
+
return this._formatInteger(sortCategory, 2) + '.' + this._formatInteger(recentListIndex, 4) + '.' + name;
|
2894
|
+
}
|
2895
|
+
|
2896
|
+
private _formatInteger(val: number, digits: number): string {
|
2897
|
+
const charCodeZero = '0'.charCodeAt(0);
|
2898
|
+
|
2899
|
+
let result = '';
|
2900
|
+
for (let i = 0; i < digits; i++) {
|
2901
|
+
// Prepend the next digit.
|
2902
|
+
let digit = Math.floor(val % 10);
|
2903
|
+
if (digit < 0) {
|
2904
|
+
digit = 9;
|
2905
|
+
}
|
2906
|
+
result = String.fromCharCode(digit + charCodeZero) + result;
|
2907
|
+
val = Math.floor(val / 10);
|
2908
|
+
}
|
2909
|
+
|
2910
|
+
return result;
|
2911
|
+
}
|
2912
|
+
|
2913
|
+
private _convertDeclarationTypeToItemKind(declaration: Declaration): CompletionItemKind {
|
2914
|
+
const resolvedDeclaration = this._evaluator.resolveAliasDeclaration(declaration, /* resolveLocalNames */ true);
|
2915
|
+
if (!resolvedDeclaration) {
|
2916
|
+
return CompletionItemKind.Variable;
|
2917
|
+
}
|
2918
|
+
|
2919
|
+
switch (resolvedDeclaration.type) {
|
2920
|
+
case DeclarationType.Intrinsic:
|
2921
|
+
return resolvedDeclaration.intrinsicType === 'class'
|
2922
|
+
? CompletionItemKind.Class
|
2923
|
+
: CompletionItemKind.Variable;
|
2924
|
+
|
2925
|
+
case DeclarationType.Parameter:
|
2926
|
+
return CompletionItemKind.Variable;
|
2927
|
+
|
2928
|
+
case DeclarationType.Variable:
|
2929
|
+
return resolvedDeclaration.isConstant || resolvedDeclaration.isFinal
|
2930
|
+
? CompletionItemKind.Constant
|
2931
|
+
: CompletionItemKind.Variable;
|
2932
|
+
|
2933
|
+
case DeclarationType.Function: {
|
2934
|
+
if (this._isPossiblePropertyDeclaration(resolvedDeclaration)) {
|
2935
|
+
const functionType = this._evaluator.getTypeOfFunction(resolvedDeclaration.node);
|
2936
|
+
if (functionType && isProperty(functionType.decoratedType)) {
|
2937
|
+
return CompletionItemKind.Property;
|
2938
|
+
}
|
2939
|
+
}
|
2940
|
+
return resolvedDeclaration.isMethod ? CompletionItemKind.Method : CompletionItemKind.Function;
|
2941
|
+
}
|
2942
|
+
|
2943
|
+
case DeclarationType.Class:
|
2944
|
+
case DeclarationType.SpecialBuiltInClass:
|
2945
|
+
return CompletionItemKind.Class;
|
2946
|
+
|
2947
|
+
case DeclarationType.Alias:
|
2948
|
+
return CompletionItemKind.Module;
|
2949
|
+
}
|
2950
|
+
}
|
2951
|
+
|
2952
|
+
private _getImportModuleCompletions(node: ModuleNameNode): CompletionResults {
|
2953
|
+
const moduleDescriptor: ImportedModuleDescriptor = {
|
2954
|
+
leadingDots: node.leadingDots,
|
2955
|
+
hasTrailingDot: node.hasTrailingDot || false,
|
2956
|
+
nameParts: node.nameParts.map((part) => part.value),
|
2957
|
+
importedSymbols: [],
|
2958
|
+
};
|
2959
|
+
|
2960
|
+
const completions = this._importResolver.getCompletionSuggestions(
|
2961
|
+
this._filePath,
|
2962
|
+
this._execEnv,
|
2963
|
+
moduleDescriptor
|
2964
|
+
);
|
2965
|
+
|
2966
|
+
const completionMap = new CompletionMap();
|
2967
|
+
|
2968
|
+
// If we're in the middle of a "from X import Y" statement, offer
|
2969
|
+
// the "import" keyword as a completion.
|
2970
|
+
if (
|
2971
|
+
!node.hasTrailingDot &&
|
2972
|
+
node.parent &&
|
2973
|
+
node.parent.nodeType === ParseNodeType.ImportFrom &&
|
2974
|
+
node.parent.missingImportKeyword
|
2975
|
+
) {
|
2976
|
+
const keyword = 'import';
|
2977
|
+
const completionItem = CompletionItem.create(keyword);
|
2978
|
+
completionItem.kind = CompletionItemKind.Keyword;
|
2979
|
+
completionItem.sortText = this._makeSortText(SortCategory.Keyword, keyword);
|
2980
|
+
completionMap.set(completionItem);
|
2981
|
+
}
|
2982
|
+
|
2983
|
+
completions.forEach((completionName) => {
|
2984
|
+
if (completionMap.has(completionName)) {
|
2985
|
+
return;
|
2986
|
+
}
|
2987
|
+
|
2988
|
+
const completionItem = CompletionItem.create(completionName);
|
2989
|
+
completionItem.kind = CompletionItemKind.Module;
|
2990
|
+
completionItem.sortText = this._makeSortText(SortCategory.ImportModuleName, completionName);
|
2991
|
+
completionMap.set(completionItem);
|
2992
|
+
});
|
2993
|
+
|
2994
|
+
return { completionMap };
|
2995
|
+
}
|
2996
|
+
|
2997
|
+
private _isPossiblePropertyDeclaration(decl: FunctionDeclaration) {
|
2998
|
+
// Do cheap check using only nodes that will cover 99.9% cases
|
2999
|
+
// before doing more expensive type evaluation.
|
3000
|
+
return decl.isMethod && decl.node.decorators.length > 0;
|
3001
|
+
}
|
3002
|
+
}
|
3003
|
+
|
3004
|
+
export class CompletionMap {
|
3005
|
+
private _completions: Map<string, CompletionItem | CompletionItem[]> = new Map();
|
3006
|
+
|
3007
|
+
get size() {
|
3008
|
+
return this._completions.size;
|
3009
|
+
}
|
3010
|
+
|
3011
|
+
set(value: CompletionItem): void {
|
3012
|
+
const existing = this._completions.get(value.label);
|
3013
|
+
if (!existing) {
|
3014
|
+
this._completions.set(value.label, value);
|
3015
|
+
} else if (Array.isArray(existing)) {
|
3016
|
+
existing.push(value);
|
3017
|
+
} else {
|
3018
|
+
this._completions.set(value.label, [existing, value]);
|
3019
|
+
}
|
3020
|
+
}
|
3021
|
+
|
3022
|
+
get(key: string): CompletionItem | CompletionItem[] | undefined {
|
3023
|
+
return this._completions.get(key);
|
3024
|
+
}
|
3025
|
+
|
3026
|
+
has(
|
3027
|
+
label: string,
|
3028
|
+
predicate?: (
|
3029
|
+
other: CompletionItem | CompletionItem[],
|
3030
|
+
kind?: CompletionItemKind,
|
3031
|
+
autoImportText?: string
|
3032
|
+
) => boolean,
|
3033
|
+
kind?: CompletionItemKind,
|
3034
|
+
autImportText?: string
|
3035
|
+
): boolean {
|
3036
|
+
const existing = this._completions.get(label);
|
3037
|
+
if (!existing) {
|
3038
|
+
return false;
|
3039
|
+
}
|
3040
|
+
|
3041
|
+
if (predicate) {
|
3042
|
+
return predicate(existing, kind, autImportText);
|
3043
|
+
}
|
3044
|
+
return true;
|
3045
|
+
}
|
3046
|
+
|
3047
|
+
clear(): void {
|
3048
|
+
this._completions.clear();
|
3049
|
+
}
|
3050
|
+
|
3051
|
+
delete(key: string): boolean {
|
3052
|
+
return this._completions.delete(key);
|
3053
|
+
}
|
3054
|
+
|
3055
|
+
toArray(): CompletionItem[] {
|
3056
|
+
const items: CompletionItem[] = [];
|
3057
|
+
this._completions?.forEach((value) => {
|
3058
|
+
if (Array.isArray(value)) {
|
3059
|
+
value.forEach((item) => {
|
3060
|
+
items.push(item);
|
3061
|
+
});
|
3062
|
+
} else {
|
3063
|
+
items.push(value);
|
3064
|
+
}
|
3065
|
+
});
|
3066
|
+
return items;
|
3067
|
+
}
|
3068
|
+
|
3069
|
+
static matchKindAndImportText(
|
3070
|
+
completionItemOrItems: CompletionItem | CompletionItem[],
|
3071
|
+
kind?: CompletionItemKind,
|
3072
|
+
autoImportText?: string
|
3073
|
+
): boolean {
|
3074
|
+
if (!Array.isArray(completionItemOrItems)) {
|
3075
|
+
return (
|
3076
|
+
completionItemOrItems.kind === kind &&
|
3077
|
+
_getCompletionData(completionItemOrItems)?.autoImportText === autoImportText
|
3078
|
+
);
|
3079
|
+
} else {
|
3080
|
+
return !!completionItemOrItems.find(
|
3081
|
+
(c) => c.kind === kind && _getCompletionData(c)?.autoImportText === autoImportText
|
3082
|
+
);
|
3083
|
+
}
|
3084
|
+
}
|
3085
|
+
|
3086
|
+
static labelOnlyIgnoringAutoImports(completionItemOrItems: CompletionItem | CompletionItem[]): boolean {
|
3087
|
+
if (!Array.isArray(completionItemOrItems)) {
|
3088
|
+
if (!_getCompletionData(completionItemOrItems)?.autoImportText) {
|
3089
|
+
return true;
|
3090
|
+
}
|
3091
|
+
} else {
|
3092
|
+
if (completionItemOrItems.find((c) => !_getCompletionData(c)?.autoImportText)) {
|
3093
|
+
return true;
|
3094
|
+
}
|
3095
|
+
}
|
3096
|
+
|
3097
|
+
return false;
|
3098
|
+
}
|
3099
|
+
}
|
3100
|
+
|
3101
|
+
function _getCompletionData(completionItem: CompletionItem): CompletionItemData | undefined {
|
3102
|
+
return fromLSPAny(completionItem.data);
|
3103
|
+
}
|