forked from DonJayamanne/pythonVSCode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsignatureProvider.ts
More file actions
95 lines (87 loc) · 4.04 KB
/
Copy pathsignatureProvider.ts
File metadata and controls
95 lines (87 loc) · 4.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
"use strict";
import * as vscode from "vscode";
import {TextDocument, Position, CancellationToken, SignatureHelp, ExtensionContext} from "vscode";
import * as proxy from "./jediProxy";
import * as telemetryContracts from "../common/telemetryContracts";
const DOCSTRING_PARAM_PATTERNS = [
"\\s*:type\\s*PARAMNAME:\\s*([^\\n, ]+)", // Sphinx
"\\s*:param\\s*(\\w?)\\s*PARAMNAME:[^\\n]+", // Sphinx param with type
"\\s*@type\\s*PARAMNAME:\\s*([^\\n, ]+)" // Epydoc
];
/**
* Extrct the documentation for parameters from a given docstring
*
* @param {string} paramName Name of the parameter
* @param {string} docString The docstring for the function
* @returns {string} Docstring for the parameter
*/
function extractParamDocString(paramName: string, docString: string): string {
let paramDocString = "";
// In docstring the '*' is escaped with a backslash
paramName = paramName.replace(new RegExp("\\*", "g"), "\\\\\\*");
DOCSTRING_PARAM_PATTERNS.forEach(pattern => {
if (paramDocString.length > 0) {
return;
}
pattern = pattern.replace("PARAMNAME", paramName);
let regExp = new RegExp(pattern);
let matches = regExp.exec(docString);
if (matches && matches.length > 0) {
paramDocString = matches[0];
if (paramDocString.indexOf(":") >= 0) {
paramDocString = paramDocString.substring(paramDocString.indexOf(":") + 1);
}
if (paramDocString.indexOf(":") >= 0) {
paramDocString = paramDocString.substring(paramDocString.indexOf(":") + 1);
}
}
});
return paramDocString.trim();
}
export class PythonSignatureProvider implements vscode.SignatureHelpProvider {
private jediProxyHandler: proxy.JediProxyHandler<proxy.IArgumentsResult, vscode.SignatureHelp>;
public constructor(context: vscode.ExtensionContext, jediProxy: proxy.JediProxy = null) {
this.jediProxyHandler = new proxy.JediProxyHandler(context, null, PythonSignatureProvider.parseData, jediProxy);
}
private static parseData(data: proxy.IArgumentsResult): vscode.SignatureHelp {
if (data && Array.isArray(data.definitions) && data.definitions.length > 0) {
let signature = new SignatureHelp();
signature.activeSignature = 0;
data.definitions.forEach(def => {
signature.activeParameter = def.paramindex;
// Don't display the documentation, as vs code doesn't format the docmentation
// i.e. line feeds are not respected, long content is stripped
let sig = <vscode.SignatureInformation>{
// documentation: def.docstring,
label: def.docstring,
parameters: []
};
sig.parameters = def.params.map(arg => {
if (arg.docstring.length === 0) {
arg.docstring = extractParamDocString(arg.name, def.docstring);
}
return <vscode.ParameterInformation>{
documentation: arg.docstring.length > 0 ? arg.docstring : arg.description,
label: arg.description.length > 0 ? arg.description : arg.name
};
});
signature.signatures.push(sig);
});
return signature;
}
return new SignatureHelp();
}
provideSignatureHelp(document: TextDocument, position: Position, token: CancellationToken): Thenable<SignatureHelp> {
return new Promise<SignatureHelp>((resolve, reject) => {
let cmd: proxy.ICommand<proxy.IArgumentsResult> = {
telemetryEvent: telemetryContracts.IDE.Symbol,
command: proxy.CommandType.Arguments,
fileName: document.fileName,
columnIndex: position.character,
lineIndex: position.line,
source: document.getText()
};
this.jediProxyHandler.sendCommand(cmd, resolve, token);
});
}
}