mirror of
https://github.com/microsoft/pyright.git
synced 2024-09-11 16:06:39 +03:00
Added docStrings in hover provider for imported modules.
This commit is contained in:
parent
33a36f6b02
commit
36cf83a768
@ -13,6 +13,7 @@ import { DiagnosticTextPosition, DiagnosticTextRange } from '../common/diagnosti
|
||||
import { convertOffsetToPosition, convertPositionToOffset } from '../common/positionUtils';
|
||||
import { ModuleNameNode, NameNode, ParseNode } from '../parser/parseNodes';
|
||||
import { ParseResults } from '../parser/parser';
|
||||
import { ImportMap } from './analyzerFileInfo';
|
||||
import { AnalyzerNodeInfo } from './analyzerNodeInfo';
|
||||
import { ImportType } from './importResult';
|
||||
import { ParseTreeUtils } from './parseTreeUtils';
|
||||
@ -31,8 +32,8 @@ export interface HoverResults {
|
||||
}
|
||||
|
||||
export class HoverProvider {
|
||||
static getHoverForPosition(parseResults: ParseResults,
|
||||
position: DiagnosticTextPosition): HoverResults | undefined {
|
||||
static getHoverForPosition(parseResults: ParseResults, position: DiagnosticTextPosition,
|
||||
importMap: ImportMap): HoverResults | undefined {
|
||||
|
||||
let offset = convertPositionToOffset(position, parseResults.lines);
|
||||
if (offset === undefined) {
|
||||
@ -73,14 +74,25 @@ export class HoverProvider {
|
||||
}
|
||||
|
||||
if (importInfo.resolvedPaths[pathOffset]) {
|
||||
this._addResultsPart(results, '(module) "' + importInfo.resolvedPaths[pathOffset] + '"', true);
|
||||
const resolvedPath = importInfo.resolvedPaths[pathOffset];
|
||||
this._addResultsPart(results, '(module) "' + resolvedPath + '"', true);
|
||||
|
||||
if (importInfo.importType === ImportType.ThirdParty && !importInfo.isStubFile) {
|
||||
this._addResultsPart(results,
|
||||
'No type stub found for this module. Imported symbol types are unknown.');
|
||||
}
|
||||
|
||||
this._addDocumentationPart(results, node);
|
||||
// If the module has been resolved and already analyzed,
|
||||
// we can add the docString for it as well.
|
||||
if (importMap[resolvedPath]) {
|
||||
const moduleNode = importMap[resolvedPath].parseTree;
|
||||
if (moduleNode) {
|
||||
const moduleType = AnalyzerNodeInfo.getExpressionType(moduleNode) as ModuleType;
|
||||
if (moduleType) {
|
||||
this._addDocumentationPartForType(results, moduleType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
@ -204,7 +216,12 @@ export class HoverProvider {
|
||||
|
||||
private static _addDocumentationPart(results: HoverResults, node: ParseNode) {
|
||||
const type = this._getTypeFromNode(node);
|
||||
if (type) {
|
||||
this._addDocumentationPartForType(results, type);
|
||||
}
|
||||
}
|
||||
|
||||
private static _addDocumentationPartForType(results: HoverResults, type: Type) {
|
||||
if (type instanceof ModuleType) {
|
||||
const docString = type.getDocString();
|
||||
if (docString) {
|
||||
|
@ -618,12 +618,13 @@ export class Program {
|
||||
getHoverForPosition(filePath: string, position: DiagnosticTextPosition):
|
||||
HoverResults | undefined {
|
||||
|
||||
const sourceFile = this.getSourceFile(filePath);
|
||||
if (!sourceFile) {
|
||||
const sourceFileInfo = this._sourceFileMap[filePath];
|
||||
if (!sourceFileInfo) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return sourceFile.getHoverForPosition(position);
|
||||
return sourceFileInfo.sourceFile.getHoverForPosition(position,
|
||||
this._buildImportMap(sourceFileInfo));
|
||||
}
|
||||
|
||||
getSignatureHelpForPosition(filePath: string, position: DiagnosticTextPosition,
|
||||
|
@ -24,8 +24,9 @@ import { PythonVersion } from '../common/pythonVersion';
|
||||
import { TextRange } from '../common/textRange';
|
||||
import { AwaitExpressionNode, ClassNode, ErrorExpressionNode,
|
||||
ExpressionNode, FunctionNode, GlobalNode, IfNode, LambdaNode, ModuleNameNode,
|
||||
ModuleNode, NonlocalNode, RaiseNode, StatementListNode, StringNode, SuiteNode,
|
||||
TryNode, WhileNode, YieldExpressionNode,
|
||||
ModuleNode, NonlocalNode, RaiseNode, StatementListNode, StatementNode, StringNode,
|
||||
SuiteNode, TryNode, WhileNode,
|
||||
YieldExpressionNode,
|
||||
YieldFromExpressionNode } from '../parser/parseNodes';
|
||||
import { StringTokenFlags } from '../parser/tokenizerTypes';
|
||||
import { ScopeUtils } from '../scopeUtils';
|
||||
@ -154,7 +155,8 @@ export abstract class SemanticAnalyzer extends ParseTreeWalker {
|
||||
}
|
||||
|
||||
let classType = new ClassType(node.name.nameToken.value, classFlags,
|
||||
AnalyzerNodeInfo.getTypeSourceId(node), this._getDocString(node.suite));
|
||||
AnalyzerNodeInfo.getTypeSourceId(node),
|
||||
this._getDocString(node.suite.statements));
|
||||
|
||||
// Don't walk the arguments for stub files because of forward
|
||||
// declarations.
|
||||
@ -223,7 +225,8 @@ export abstract class SemanticAnalyzer extends ParseTreeWalker {
|
||||
functionFlags &= ~FunctionTypeFlags.InstanceMethod;
|
||||
}
|
||||
|
||||
let functionType = new FunctionType(functionFlags, this._getDocString(node.suite));
|
||||
let functionType = new FunctionType(functionFlags,
|
||||
this._getDocString(node.suite.statements));
|
||||
|
||||
this.walkMultiple(node.decorators);
|
||||
node.parameters.forEach(param => {
|
||||
@ -459,19 +462,19 @@ export abstract class SemanticAnalyzer extends ParseTreeWalker {
|
||||
symbol.setInferredTypeForSource(type, typeSourceId);
|
||||
}
|
||||
|
||||
private _getDocString(suiteNode: SuiteNode): string | undefined {
|
||||
protected _getDocString(statemetns: StatementNode[]): string | undefined {
|
||||
// See if the first statement in the suite is a triple-quote string.
|
||||
if (suiteNode.statements.length === 0) {
|
||||
if (statemetns.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (!(suiteNode.statements[0] instanceof StatementListNode)) {
|
||||
if (!(statemetns[0] instanceof StatementListNode)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// If the first statement in the suite isn't a StringNode,
|
||||
// assume there is no docString.
|
||||
const statementList = suiteNode.statements[0] as StatementListNode;
|
||||
const statementList = statemetns[0] as StatementListNode;
|
||||
if (statementList.statements.length === 0 || !(statementList.statements[0] instanceof StringNode)) {
|
||||
return undefined;
|
||||
}
|
||||
@ -566,7 +569,8 @@ export class ModuleScopeAnalyzer extends SemanticAnalyzer {
|
||||
this.walkChildren(this._scopedNode);
|
||||
|
||||
// Associate the module's scope with the module type.
|
||||
let moduleType = new ModuleType(this._currentScope.getSymbolTable());
|
||||
const moduleType = new ModuleType(this._currentScope.getSymbolTable(),
|
||||
this._getDocString((this._scopedNode as ModuleNode).statements));
|
||||
AnalyzerNodeInfo.setExpressionType(this._scopedNode, moduleType);
|
||||
}
|
||||
|
||||
|
@ -468,14 +468,14 @@ export class SourceFile {
|
||||
this._analysisJob.parseResults, position);
|
||||
}
|
||||
|
||||
getHoverForPosition(position: DiagnosticTextPosition): HoverResults | undefined {
|
||||
getHoverForPosition(position: DiagnosticTextPosition, importMap: ImportMap): HoverResults | undefined {
|
||||
// If we have no completed analysis job, there's nothing to do.
|
||||
if (!this._analysisJob.parseResults) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return HoverProvider.getHoverForPosition(
|
||||
this._analysisJob.parseResults, position);
|
||||
this._analysisJob.parseResults, position, importMap);
|
||||
}
|
||||
|
||||
getSignatureHelpForPosition(position: DiagnosticTextPosition): SignatureHelpResults | undefined {
|
||||
|
Loading…
Reference in New Issue
Block a user