mirror of
https://github.com/godotengine/godot-vscode-plugin.git
synced 2025-12-31 13:48:24 +03:00
Add signature helper for builtin functions
Add signature infomations for workspace functions in hover message
This commit is contained in:
@@ -20,6 +20,8 @@ class Config {
|
||||
public nodeInfoMap: Object;
|
||||
// symbolname: {completionItem: CompletionItem, rowDoc: docdata}
|
||||
public builtinSymbolInfoMap: Object;
|
||||
// path.function: signature
|
||||
public workspaceMethodSignatureMap: Object;
|
||||
|
||||
constructor() {
|
||||
this.symbols = {};
|
||||
@@ -90,7 +92,7 @@ class Config {
|
||||
builtinSymbolInfoMap[classdoc.name] = {completionItem: item, rowDoc: classdoc};
|
||||
// methods
|
||||
const methods = classdoc.methods
|
||||
const parsMethod = (m, kind: CompletionItemKind, insertAction=(name)=>name+"()")=>{
|
||||
const parsMethod = (m, kind: CompletionItemKind, insertAction=(name)=>name)=>{
|
||||
const mi = new CompletionItem(m.name, kind);
|
||||
mi.insertText = insertAction(m.name)
|
||||
mi.filterText = m.name
|
||||
@@ -154,7 +156,7 @@ class Config {
|
||||
return _items;
|
||||
}
|
||||
items = [...items, ...addScriptItems(script.classes, CompletionItemKind.Class, "Class")];
|
||||
items = [...items, ...addScriptItems(script.functions, CompletionItemKind.Method, "Method", (t)=>`${t}()`)];
|
||||
items = [...items, ...addScriptItems(script.functions, CompletionItemKind.Method, "Method", (f)=>f+`${script.signatures[f]}`)];
|
||||
items = [...items, ...addScriptItems(script.variables, CompletionItemKind.Variable, "Variable")];
|
||||
items = [...items, ...addScriptItems(script.signals, CompletionItemKind.Interface, "Signal")];
|
||||
items = [...items, ...addScriptItems(script.constants, CompletionItemKind.Enum, "Constant")];
|
||||
|
||||
@@ -82,7 +82,7 @@ class GDScriptDiagnosticSeverity {
|
||||
if(semicolonIndex != -1) {
|
||||
diagnostics.push(new vscode.Diagnostic(new vscode.Range(i, semicolonIndex, i, semicolonIndex+1), "Statement ends with a semicolon.", DiagnosticSeverity.Warning));
|
||||
}
|
||||
if(line.match(/\s*(if|elif|else|for|while|func|class)\s*/g) && line.indexOf(":") == -1) {
|
||||
if(line.match(/\s*(if|elif|else|for|while|func|class)\s*$/g) && line.indexOf(":") == -1) {
|
||||
if(line.indexOf("#") == -1)
|
||||
diagnostics.push(new vscode.Diagnostic(new vscode.Range(i, 0, i, line.length), "':' expected at end of the line.", DiagnosticSeverity.Error));
|
||||
}
|
||||
|
||||
@@ -44,7 +44,10 @@ class GDScriptHoverProvider implements HoverProvider {
|
||||
let dfile = path;
|
||||
if (workspace && workspace.asRelativePath(dfile))
|
||||
dfile = workspace.asRelativePath(dfile);
|
||||
_items.push({language:'gdscript', value:`${type} ${name}`});
|
||||
let extra = "";
|
||||
if(type == "func"|| type == "signal" && script.signatures[name])
|
||||
extra = script.signatures[name];
|
||||
_items.push({language:'gdscript', value:`${type} ${name}${extra}`});
|
||||
_items.push(`Defined in *[${dfile}](${Uri.file(path).toString()})*`)
|
||||
break;
|
||||
}
|
||||
|
||||
94
src/gdscript/signature_helper.ts
Normal file
94
src/gdscript/signature_helper.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import {
|
||||
SignatureHelpProvider,
|
||||
TextDocument,
|
||||
Position,
|
||||
CancellationToken,
|
||||
SignatureInformation,
|
||||
SignatureHelp,
|
||||
CompletionItemKind,
|
||||
ParameterInformation
|
||||
} from 'vscode';
|
||||
import config from '../config';
|
||||
import { countSubStr } from './utils';
|
||||
class GDScriptSignatureHelpProvider implements SignatureHelpProvider {
|
||||
constructor() {}
|
||||
|
||||
/**
|
||||
* Provide help for the signature at the given position and document.
|
||||
*
|
||||
* @param document The document in which the command was invoked.
|
||||
* @param position The position at which the command was invoked.
|
||||
* @param token A cancellation token.
|
||||
* @return Signature help or a thenable that resolves to such. The lack of a result can be
|
||||
* signaled by returning `undefined` or `null`.
|
||||
*/
|
||||
provideSignatureHelp(document : TextDocument, position : Position, token : CancellationToken) : SignatureHelp | Thenable < SignatureHelp > {
|
||||
const range = document.getWordRangeAtPosition(position);
|
||||
let funcname = "";
|
||||
let curparam = 0;
|
||||
const checkPosition = () => {
|
||||
const line = document.lineAt(position);
|
||||
const startPos = line.firstNonWhitespaceCharacterIndex;
|
||||
const endPos = position.character;
|
||||
const queryStr = line.text.substring(startPos, endPos);
|
||||
|
||||
var reg = /([A-z_]+[A-z0-9_]*)\(/g;
|
||||
let match = reg.exec(queryStr);
|
||||
while (match != null) {
|
||||
funcname = match[1];
|
||||
match = reg.exec(queryStr);
|
||||
}
|
||||
if(funcname != "") {
|
||||
const funcrangestr = line.text.substring(line.text.indexOf(queryStr)+queryStr.indexOf(funcname)+funcname.length, endPos);
|
||||
curparam = countSubStr(funcrangestr, ",");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
checkPosition();
|
||||
|
||||
let help: SignatureHelp = {
|
||||
signatures: [],
|
||||
activeSignature: 0,
|
||||
activeParameter: curparam
|
||||
};
|
||||
|
||||
if (funcname.length > 0) {
|
||||
// Builtin functions
|
||||
for (let key of Object.keys(config.builtinSymbolInfoMap)) {
|
||||
if (key.endsWith(`\.${funcname}`)) {
|
||||
if (config.builtinSymbolInfoMap[key].completionItem.kind == CompletionItemKind.Method || config.builtinSymbolInfoMap[key].completionItem.kind == CompletionItemKind.Function) {
|
||||
const rawDoc = config.builtinSymbolInfoMap[key].rowDoc;
|
||||
const item = config.builtinSymbolInfoMap[key].completionItem;
|
||||
let signatureInfor: SignatureInformation = new SignatureInformation(item.documentation.split('\n')[0], rawDoc.description);
|
||||
for(let arg of rawDoc.arguments){
|
||||
let param: ParameterInformation = new ParameterInformation(`${arg.type} ${arg.name}${arg.default_value.length>0?'='+arg.default_value:''}`, "");
|
||||
signatureInfor.parameters.push(param);
|
||||
}
|
||||
help.signatures.push(signatureInfor);
|
||||
}
|
||||
}
|
||||
}
|
||||
// workspace functions
|
||||
// for (let path of Object.keys(config.getAllSymbols())) {
|
||||
// const script = config.getSymbols(path);
|
||||
// for(let f of Object.keys(script.signatures)) {
|
||||
// if(f == funcname) {
|
||||
// let signatureInfor: SignatureInformation = new SignatureInformation(`func ${f}${script.signatures[f]}`, `Method defined in ${path}`);
|
||||
// let param: ParameterInformation = new ParameterInformation(script.signatures[f], "");
|
||||
// signatureInfor.parameters.push(param);
|
||||
// help.signatures.push(signatureInfor);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
if(help.signatures.length>0)
|
||||
return help;
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default GDScriptSignatureHelpProvider;
|
||||
@@ -8,7 +8,8 @@ interface GDScript {
|
||||
signals: {},
|
||||
classes: {},
|
||||
base: string,
|
||||
native: string
|
||||
native: string,
|
||||
signatures: {}
|
||||
}
|
||||
|
||||
class GDScriptSymbolParser {
|
||||
@@ -23,7 +24,8 @@ class GDScriptSymbolParser {
|
||||
signals: {},
|
||||
classes: {},
|
||||
base: "Object",
|
||||
native: "Object"
|
||||
native: "Object",
|
||||
signatures: {}
|
||||
}
|
||||
const text = content;
|
||||
const lines = text.split(/\r?\n/);
|
||||
@@ -66,8 +68,18 @@ class GDScriptSymbolParser {
|
||||
|
||||
let funcsnames = getMatches(text, /func\s+([_A-Za-z]+[_A-Za-z0-9]*)\s*\(/g, 1);
|
||||
const funcs = findLineRanges(funcsnames, "func\\s+$X$\\s*\\(");
|
||||
for (let key of Object.keys(funcs))
|
||||
script.functions[key] = determRange(key, funcs);
|
||||
for (let key of Object.keys(funcs)) {
|
||||
let r: Range = determRange(key, funcs);
|
||||
script.functions[key] = r;
|
||||
const line = lines[r.start.line];
|
||||
if(line.indexOf("(")!= -1 && line.indexOf(")")!=-1) {
|
||||
const signature = line.substring(line.indexOf("("), line.indexOf(")")+1);
|
||||
if(signature && signature.length >0) {
|
||||
script.signatures[key] = signature;
|
||||
// console.log(key, signature);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let signalnames = getMatches(text, /signal\s+([_A-Za-z]+[_A-Za-z0-9]*)\s*\(/g, 1);
|
||||
const signals = findLineRanges(signalnames, "signal\\s+$X$\\s*\\(");
|
||||
|
||||
@@ -28,4 +28,14 @@ export function getStrContent(rawstr: string):string {
|
||||
ss = ss.replace(/"|'|@"|"""/g,"")
|
||||
}
|
||||
return ss;
|
||||
}
|
||||
|
||||
export function countSubStr(str:string, sub:string): number {
|
||||
let count = 0;
|
||||
let pos = str.indexOf(sub);
|
||||
while (pos !== -1) {
|
||||
count++;
|
||||
pos = str.indexOf(sub, pos + sub.length);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import GDScriptCompletionItemProvider from './gdscript/completion';
|
||||
import GDScriptDefinitionProivder from './gdscript/definitionprovider';
|
||||
import GDScriptHoverProvider from './gdscript/hoverprovider';
|
||||
import GDScriptDocumentContentProvider from './gdscript/docprovider';
|
||||
|
||||
import GDScriptSignatureHelpProvider from './gdscript/signature_helper';
|
||||
var glob = require("glob")
|
||||
import config from './config';
|
||||
import * as path from 'path';
|
||||
@@ -45,6 +45,8 @@ class ToolManager {
|
||||
vscode.languages.registerHoverProvider('gdscript', new GDScriptHoverProvider());
|
||||
// code completion provider
|
||||
vscode.languages.registerCompletionItemProvider('gdscript', new GDScriptCompletionItemProvider(), '.', '"', "'");
|
||||
// signature help provider
|
||||
vscode.languages.registerSignatureHelpProvider('gdscript', new GDScriptSignatureHelpProvider(), '(', ',');
|
||||
// Commands
|
||||
this._disposable = vscode.Disposable.from(
|
||||
vscode.commands.registerCommand('godot.updateWorkspaceSymbols', this.loadWorkspaceSymbols.bind(this)),
|
||||
|
||||
Reference in New Issue
Block a user