enhanced code completion

This commit is contained in:
geequlim
2017-08-06 16:57:08 +08:00
parent 90457a0df6
commit dda701026c
2 changed files with 139 additions and 43 deletions

View File

@@ -9,10 +9,21 @@ interface NodeInfo {
instance: string
};
interface CompletionSymbols {
classes : CompletionItem[],
functions : CompletionItem[],
signals : CompletionItem[],
constants : CompletionItem[],
properties : CompletionItem[],
nodes : CompletionItem[],
builtinConstants: CompletionItem[]
};
class Config {
private symbols;
private classes;
public bintinSybmolInfoList: CompletionItem[];
private workspaceSymbols; // filePath: GDScript in symbolparser.ts
private builtinCompletions : CompletionSymbols;
private builtinClassDoc;
public parser: GDScriptSymbolParser;
// scriptpath : scenepath
public scriptSceneMap: Object;
@@ -22,8 +33,16 @@ class Config {
public builtinSymbolInfoMap: Object;
constructor() {
this.symbols = {};
this.bintinSybmolInfoList = [];
this.builtinCompletions = {
classes : [],
functions : [],
signals : [],
constants : [],
properties : [],
nodes : [],
builtinConstants: []
};
this.workspaceSymbols = {};
this.builtinSymbolInfoMap = {};
this.nodeInfoMap = {};
this.scriptSceneMap = {};
@@ -40,19 +59,19 @@ class Config {
}
setSymbols(path, s) {
this.symbols[this.normalizePath(path)] = s;
this.workspaceSymbols[this.normalizePath(path)] = s;
}
getSymbols(path) {
return this.symbols[this.normalizePath(path)];
return this.workspaceSymbols[this.normalizePath(path)];
}
setAllSymbols(s) {
this.symbols = s;
this.workspaceSymbols = s;
}
getAllSymbols() {
return this.symbols;
return this.workspaceSymbols;
}
normalizePath(path) {
@@ -75,7 +94,7 @@ class Config {
const content = fs.readFileSync(docfile, "utf-8");
const docdata = JSON.parse(content);
if(docdata.classes) {
this.classes = docdata.classes;
this.builtinClassDoc = docdata.classes;
done = true;
}
}
@@ -83,18 +102,16 @@ class Config {
console.error(error);
}
if(done) {
for (let key of Object.keys(this.classes)) {
const classdoc = this.classes[key];
const bintinSybmolInfoList = this.bintinSybmolInfoList;
for (let key of Object.keys(this.builtinClassDoc)) {
const classdoc = this.builtinClassDoc[key];
const builtinSymbolInfoMap = this.builtinSymbolInfoMap;
// class
// ---------------------- class -----------------
const item: CompletionItem = new CompletionItem(classdoc.name, CompletionItemKind.Class);
item.detail = 'Native Class';
item.documentation = classdoc.brief_description + " \n\n" +classdoc.description;
bintinSybmolInfoList.push(item);
this.builtinCompletions.classes.push(item);
builtinSymbolInfoMap[classdoc.name] = {completionItem: item, rowDoc: classdoc};
// methods
const methods = classdoc.methods
// ----------------------- functions -----------------------
const parsMethod = (m, kind: CompletionItemKind, insertAction=(name)=>name)=>{
const mi = new CompletionItem(m.name, kind);
mi.insertText = insertAction(m.name) + (m.arguments.length==0?"()":"");
@@ -110,31 +127,46 @@ class Config {
mdoc += " \n\n";
mdoc += m.description;
mi.documentation = mdoc;
bintinSybmolInfoList.push(mi);
if(CompletionItemKind.Interface == kind)
this.builtinCompletions.signals.push(mi);
else
this.builtinCompletions.functions.push(mi);
builtinSymbolInfoMap[`${classdoc.name}.${m.name}`] = {completionItem: mi, rowDoc: m};
};
// methods
const methods = classdoc.methods
methods.map(m=>parsMethod(m, CompletionItemKind.Method));
// signals
const signals = classdoc.signals;
signals.map(s=>parsMethod(s, CompletionItemKind.Interface));
// constants
// ------------------------------ constants ---------------------
const constants = classdoc.constants;
constants.map(c=>{
const ci = new CompletionItem(c.name, CompletionItemKind.Enum);
ci.detail = c.value;
ci.documentation = `${classdoc.name}.${c.name} = ${c.value}`;
bintinSybmolInfoList.push(ci);
if(key[0] == "@")
this.builtinCompletions.builtinConstants.push(ci);
else
this.builtinCompletions.constants.push(ci);
builtinSymbolInfoMap[`${classdoc.name}.${c.name}`] = {completionItem: ci, rowDoc: c};
});
// properties
const properties = classdoc.properties;
const parseProp = (p)=>{
});
// ----------------------- properties -----------------------
const parseProp = (p) => {
const pi = new CompletionItem(p.name, CompletionItemKind.Property);
pi.detail = `${p.type} of ${classdoc.name}`;
pi.documentation = p.description;
bintinSybmolInfoList.push(pi);
builtinSymbolInfoMap[`${classdoc.name}.${p.name}`] = {completionItem: pi, rowDoc: p};
this
.builtinCompletions
.properties
.push(pi);
builtinSymbolInfoMap[`${classdoc.name}.${p.name}`] = {
completionItem: pi,
rowDoc: p
};
};
// properties
const properties = classdoc.properties;
properties.map(p=>parseProp(p));
// theme_properties
const theme_properties = classdoc.theme_properties;
@@ -144,10 +176,18 @@ class Config {
return done;
};
getWorkspaceCompletionItems(): CompletionItem[] {
let items: CompletionItem[] = [];
for (let path of Object.keys(this.symbols)) {
const script = this.symbols[path];
getWorkspaceCompletionItems() : CompletionSymbols {
const symbols = {
classes: [],
functions: [],
signals: [],
constants: [],
properties: [],
nodes: [],
builtinConstants: []
};
for (let path of Object.keys(this.workspaceSymbols)) {
const script = this.workspaceSymbols[path];
const addScriptItems = (items, kind: CompletionItemKind, kindName:string = "Symbol", insertText = (n)=>n)=>{
const _items: CompletionItem[] = [];
for (let name of Object.keys(items)) {
@@ -164,13 +204,15 @@ class Config {
}
return _items;
}
items = [...items, ...addScriptItems(script.classes, CompletionItemKind.Class, "Class")];
items = [...items, ...addScriptItems(script.functions, CompletionItemKind.Method, "Method")];
items = [...items, ...addScriptItems(script.variables, CompletionItemKind.Variable, "Variable")];
items = [...items, ...addScriptItems(script.signals, CompletionItemKind.Interface, "Signal")];
items = [...items, ...addScriptItems(script.constants, CompletionItemKind.Enum, "Constant")];
symbols.classes = [ ...(symbols.classes), ...(addScriptItems(script.classes, CompletionItemKind.Class, "Class"))]
symbols.functions = [ ...(symbols.functions), ...(addScriptItems(script.functions, CompletionItemKind.Method, "Method"))]
symbols.signals = [ ...(symbols.signals), ...(addScriptItems(script.signals, CompletionItemKind.Interface, "Signal"))]
symbols.properties = [ ...(symbols.properties), ...(addScriptItems(script.variables, CompletionItemKind.Variable, "Variable"))]
symbols.constants = [ ...(symbols.constants), ...(addScriptItems(script.constants, CompletionItemKind.Enum, "Constant"))]
if(script.enumerations)
items = [...items, ...addScriptItems(script.enumerations, CompletionItemKind.Enum, "Enumeration")];
symbols.constants = [...(symbols.constants), ...(addScriptItems(script.enumerations, CompletionItemKind.Enum, "Enumeration"))];
}
const addSceneNodes = ()=>{
@@ -193,9 +235,9 @@ class Config {
}
return _items;
};
items = [...items, ...addSceneNodes()];
symbols.nodes = [...(symbols.nodes), ...(addSceneNodes())];
return items;
return symbols;
}
loadScene(scenePath: string) {
@@ -257,13 +299,17 @@ class Config {
}
getClass(name: string) {
return this.classes[name];
return this.builtinClassDoc[name];
}
getBuiltinCompletions() {
return this.builtinCompletions;
}
getBuiltinClassNameList() {
let namelist = null;
if(this.classes)
namelist = Object.keys(this.classes);
if (this.builtinClassDoc)
namelist = Object.keys(this.builtinClassDoc);
if(!namelist)
namelist = [];
return namelist;

View File

@@ -34,10 +34,60 @@ class GDScriptCompletionItemProvider implements CompletionItemProvider {
constructor() {
}
private get_previous_flag(document : TextDocument, position : Position): string {
const line = document.lineAt(position).text;
let res = "";
for (let index = position.character; index >= 0; index--) {
res = line[index];
if (['.', '$', '"', "'"].indexOf(res) != -1 )
break;
}
return res;
}
provideCompletionItems(document : TextDocument, position : Position, token : CancellationToken) : CompletionItem[] | Thenable < CompletionItem[] > | CompletionList | Thenable < CompletionList > {
let items:CompletionItem[] = config.getWorkspaceCompletionItems();
items = [...items, ...config.bintinSybmolInfoList];
const lastFlag = this.get_previous_flag(document, position);
const builtins = config.getBuiltinCompletions();
const workspaces = config.getWorkspaceCompletionItems();
let items:CompletionItem[] = [...(builtins.builtinConstants)];
if(!lastFlag || lastFlag.trim().length == 0) {
items = [
...items,
...(workspaces.functions),
...(workspaces.classes),
...(builtins.functions),
...(builtins.classes),
]
}
else {
if(lastFlag.trim() == ".") {
items = [
...items,
...(workspaces.functions),
...(workspaces.constants),
...(workspaces.properties),
...(workspaces.classes),
...(builtins.functions),
...(builtins.constants),
...(builtins.properties)
]
}
else if(lastFlag.trim() == "'" || lastFlag.trim() == '"') {
items = [
...items,
...(workspaces.signals),
...(workspaces.functions),
...(workspaces.properties),
...(builtins.signals),
...(builtins.functions),
...(builtins.properties),
...(workspaces.nodes),
]
}
}
return items;
}