Support for setting userdata types, validating them and autocompleting them

This commit is contained in:
Deukhoofd 2018-11-29 18:13:45 +01:00
parent b1b863d5a3
commit e0420e9315
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
9 changed files with 116 additions and 11 deletions

View File

@ -57,7 +57,8 @@ function activateLanguageServer(context) {
fileEvents: [ fileEvents: [
vscode.workspace.createFileSystemWatcher("**/.clientrc"), vscode.workspace.createFileSystemWatcher("**/.clientrc"),
vscode.workspace.createFileSystemWatcher("**/.yup"), vscode.workspace.createFileSystemWatcher("**/.yup"),
vscode.workspace.createFileSystemWatcher("**/.lua") vscode.workspace.createFileSystemWatcher("**/.lua"),
vscode.workspace.createFileSystemWatcher("**/.upsilon/*.json")
] ]
} }
}; };
@ -78,5 +79,4 @@ exports.activate = activate;
// this method is called when your extension is deactivated // this method is called when your extension is deactivated
function deactivate() { } function deactivate() { }
exports.deactivate = deactivate; exports.deactivate = deactivate;
6;
//# sourceMappingURL=extension.js.map //# sourceMappingURL=extension.js.map

View File

@ -1 +1 @@
{"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AACb,6DAA6D;AAC7D,8EAA8E;AAE9E,iCAAiC;AACjC,wDAAwD;AACxD,6BAA6B;AAC7B,yBAAyB;AAEzB,mEAAmE;AACnE,MAAM,mBAAmB,GAAG;IAC1B,+BAA+B;IAC/B,kGAAkG;CACnG,CAAC;AAEF,SAAS,sBAAsB,CAAC,OAAgC;IAC9D,0DAA0D;IAC1D,IAAI,YAAY,GAAW,IAAI,CAAC;IAChC,KAAK,IAAI,CAAC,IAAI,mBAAmB,EAAE;QACjC,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;QAC9B,kBAAkB;QAClB,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE;YACpB,YAAY,GAAG,CAAC,CAAC;YACjB,MAAM;SACP;KACF;IACD,IAAI,CAAC,YAAY;QACf,MAAM,IAAI,QAAQ,CAAC,yCAAyC,CAAC,CAAC;IAChE,IAAI,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAC1C,OAAO,CAAC,GAAG,CAAC,OAAO,YAAY,oBAAoB,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,cAAc,QAAQ,GAAG,CAAC,CAAC;IAEvC,oFAAoF;IACpF,qCAAqC;IACrC,IAAI,aAAa,GAAiC;QAChD,GAAG,EAAE;YACH,OAAO,EAAE,QAAQ;YACjB,IAAI,EAAE,CAAC,YAAY,CAAC;YACpB,OAAO,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE;SAC3B;QACD,KAAK,EAAE;YACL,OAAO,EAAE,QAAQ;YACjB,IAAI,EAAE,CAAC,YAAY,EAAE,SAAS,CAAC;YAC/B,OAAO,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE;SAC3B;KACF,CAAC;IACF,yCAAyC;IACzC,IAAI,aAAa,GAAyC;QACxD,+CAA+C;QAC/C,gBAAgB,EAAE;YAChB;gBACE,QAAQ,EAAE,SAAS;gBACnB,MAAM,EAAE,MAAM;aACf;SACF;QACD,WAAW,EAAE;YACX,wEAAwE;YACxE,oBAAoB,EAAE,uBAAuB;YAC7C,oFAAoF;YACpF,UAAU,EAAE;gBACV,MAAM,CAAC,SAAS,CAAC,uBAAuB,CAAC,cAAc,CAAC;gBACxD,MAAM,CAAC,SAAS,CAAC,uBAAuB,CAAC,SAAS,CAAC;gBACnD,MAAM,CAAC,SAAS,CAAC,uBAAuB,CAAC,SAAS,CAAC;aACpD;SACF;KACF,CAAC;IAEF,mDAAmD;IACnD,IAAI,MAAM,GAAG,IAAI,cAAc,CAAC,cAAc,CAC5C,uBAAuB,EACvB,yBAAyB,EACzB,aAAa,EACb,aAAa,CACd,CAAC;IACF,IAAI,UAAU,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC;IAEhC,iEAAiE;IACjE,sDAAsD;IACtD,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AACzC,CAAC;AAED,yDAAyD;AACzD,0EAA0E;AAC1E,SAAgB,QAAQ,CAAC,OAAgC;IACvD,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;IACnD,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAClC,CAAC;AAHD,4BAGC;AAED,2DAA2D;AAC3D,SAAgB,UAAU,KAAI,CAAC;AAA/B,gCAA+B;AAC/B,CAAC,CAAC"} {"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AACb,6DAA6D;AAC7D,8EAA8E;AAE9E,iCAAiC;AACjC,wDAAwD;AACxD,6BAA6B;AAC7B,yBAAyB;AAEzB,mEAAmE;AACnE,MAAM,mBAAmB,GAAG;IAC1B,+BAA+B;IAC/B,kGAAkG;CACnG,CAAC;AAEF,SAAS,sBAAsB,CAAC,OAAgC;IAC9D,0DAA0D;IAC1D,IAAI,YAAY,GAAW,IAAI,CAAC;IAChC,KAAK,IAAI,CAAC,IAAI,mBAAmB,EAAE;QACjC,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;QAC9B,kBAAkB;QAClB,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE;YACpB,YAAY,GAAG,CAAC,CAAC;YACjB,MAAM;SACP;KACF;IACD,IAAI,CAAC,YAAY;QACf,MAAM,IAAI,QAAQ,CAAC,yCAAyC,CAAC,CAAC;IAChE,IAAI,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAC1C,OAAO,CAAC,GAAG,CAAC,OAAO,YAAY,oBAAoB,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,cAAc,QAAQ,GAAG,CAAC,CAAC;IAEvC,oFAAoF;IACpF,qCAAqC;IACrC,IAAI,aAAa,GAAiC;QAChD,GAAG,EAAE;YACH,OAAO,EAAE,QAAQ;YACjB,IAAI,EAAE,CAAC,YAAY,CAAC;YACpB,OAAO,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE;SAC3B;QACD,KAAK,EAAE;YACL,OAAO,EAAE,QAAQ;YACjB,IAAI,EAAE,CAAC,YAAY,EAAE,SAAS,CAAC;YAC/B,OAAO,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE;SAC3B;KACF,CAAC;IACF,yCAAyC;IACzC,IAAI,aAAa,GAAyC;QACxD,+CAA+C;QAC/C,gBAAgB,EAAE;YAChB;gBACE,QAAQ,EAAE,SAAS;gBACnB,MAAM,EAAE,MAAM;aACf;SACF;QACD,WAAW,EAAE;YACX,wEAAwE;YACxE,oBAAoB,EAAE,uBAAuB;YAC7C,oFAAoF;YACpF,UAAU,EAAE;gBACV,MAAM,CAAC,SAAS,CAAC,uBAAuB,CAAC,cAAc,CAAC;gBACxD,MAAM,CAAC,SAAS,CAAC,uBAAuB,CAAC,SAAS,CAAC;gBACnD,MAAM,CAAC,SAAS,CAAC,uBAAuB,CAAC,SAAS,CAAC;gBACnD,MAAM,CAAC,SAAS,CAAC,uBAAuB,CAAC,oBAAoB,CAAC;aAC/D;SACF;KACF,CAAC;IAEF,mDAAmD;IACnD,IAAI,MAAM,GAAG,IAAI,cAAc,CAAC,cAAc,CAC5C,uBAAuB,EACvB,yBAAyB,EACzB,aAAa,EACb,aAAa,CACd,CAAC;IACF,IAAI,UAAU,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC;IAEhC,iEAAiE;IACjE,sDAAsD;IACtD,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AACzC,CAAC;AAED,yDAAyD;AACzD,0EAA0E;AAC1E,SAAgB,QAAQ,CAAC,OAAgC;IACvD,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;IACnD,sBAAsB,CAAC,OAAO,CAAC,CAAC;AAClC,CAAC;AAHD,4BAGC;AAED,2DAA2D;AAC3D,SAAgB,UAAU,KAAI,CAAC;AAA/B,gCAA+B"}

View File

@ -60,7 +60,8 @@ function activateLanguageServer(context: vscode.ExtensionContext) {
fileEvents: [ fileEvents: [
vscode.workspace.createFileSystemWatcher("**/.clientrc"), vscode.workspace.createFileSystemWatcher("**/.clientrc"),
vscode.workspace.createFileSystemWatcher("**/.yup"), vscode.workspace.createFileSystemWatcher("**/.yup"),
vscode.workspace.createFileSystemWatcher("**/.lua") vscode.workspace.createFileSystemWatcher("**/.lua"),
vscode.workspace.createFileSystemWatcher("**/.upsilon/*.json")
] ]
} }
}; };
@ -88,4 +89,3 @@ export function activate(context: vscode.ExtensionContext) {
// this method is called when your extension is deactivated // this method is called when your extension is deactivated
export function deactivate() {} export function deactivate() {}
6;

View File

@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Upsilon.BoundTypes;
using Type = Upsilon.BaseTypes.Type;
namespace UpsilonLanguageServer
{
public static class BoundTypeParser
{
public static void LoadBoundTypes(string fileContent)
{
BoundTypeHandler.Reset();
var json = JObject.Parse(fileContent);
foreach (var prop in json.Properties())
{
var typeName = prop.Name;
var dic = new Dictionary<string, UserDataBoundProperty>();
var innerProperties = ((JObject)prop.Value).Properties();
foreach (var innerProperty in innerProperties)
{
var propertyName = innerProperty.Name;
var value = (JObject)innerProperty.Value;
var type = value.GetValue("type", StringComparison.InvariantCultureIgnoreCase)?.ToString();
var comment = value.GetValue("comment", StringComparison.InvariantCultureIgnoreCase)?.ToString();
dic.Add(propertyName, new UserDataBoundProperty()
{
Name = propertyName,
ActualType = type,
Comment = comment,
//TODO
Type = ParseType(type)
});
}
BoundTypeHandler.LoadUserDataTypeDefinition(new UserDataBoundTypeDefinition(typeName, dic));
}
}
private static Type ParseType(string input)
{
if (string.Equals(input, "string", StringComparison.InvariantCultureIgnoreCase))
return Type.String;
if (string.Equals(input, "number", StringComparison.InvariantCultureIgnoreCase))
return Type.Number;
if (string.Equals(input, "bool", StringComparison.InvariantCultureIgnoreCase))
return Type.Boolean;
if (string.Equals(input, "table", StringComparison.InvariantCultureIgnoreCase))
return Type.Table;
if (string.Equals(input, "function", StringComparison.InvariantCultureIgnoreCase))
return Type.Function;
return Type.UserData;
}
}
}

View File

@ -1,4 +1,5 @@
using System; using System;
using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using JsonRpc.Standard; using JsonRpc.Standard;
using JsonRpc.Standard.Contracts; using JsonRpc.Standard.Contracts;
@ -16,6 +17,15 @@ namespace UpsilonLanguageServer.Services
public InitializeResult Initialize(int processId, Uri rootUri, ClientCapabilities capabilities, public InitializeResult Initialize(int processId, Uri rootUri, ClientCapabilities capabilities,
JToken initializationOptions = null, string trace = null) JToken initializationOptions = null, string trace = null)
{ {
if (rootUri != null)
{
var configPath = rootUri.AbsolutePath + "/.upsilon";
var typesConfigFile = configPath + "/types.json";
if (File.Exists(typesConfigFile))
{
BoundTypeParser.LoadBoundTypes(File.ReadAllText(typesConfigFile));
}
}
return new InitializeResult(new ServerCapabilities return new InitializeResult(new ServerCapabilities
{ {
HoverProvider = true, HoverProvider = true,

View File

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -6,9 +7,8 @@ using System.Threading.Tasks;
using JsonRpc.Standard.Contracts; using JsonRpc.Standard.Contracts;
using LanguageServer.VsCode; using LanguageServer.VsCode;
using LanguageServer.VsCode.Contracts; using LanguageServer.VsCode.Contracts;
using LanguageServer.VsCode.Server;
using Upsilon.Binder; using Upsilon.Binder;
using Upsilon.Parser; using Upsilon.BoundTypes;
using Upsilon.Utilities; using Upsilon.Utilities;
namespace UpsilonLanguageServer.Services namespace UpsilonLanguageServer.Services
@ -62,16 +62,24 @@ namespace UpsilonLanguageServer.Services
[JsonRpcMethod] [JsonRpcMethod]
public SignatureHelp SignatureHelp(TextDocumentIdentifier textDocument, Position position) public SignatureHelp SignatureHelp(TextDocumentIdentifier textDocument, Position position)
{ {
// TODO
return new SignatureHelp(new List<SignatureInformation> return new SignatureHelp(new List<SignatureInformation>
{ {
new SignatureInformation("**Function1**", "Documentation1"),
new SignatureInformation("**Function2** <strong>test</strong>", "Documentation2"),
}); });
} }
[JsonRpcMethod(IsNotification = true)] [JsonRpcMethod(IsNotification = true)]
public async Task DidOpen(TextDocumentItem textDocument) public async Task DidOpen(TextDocumentItem textDocument)
{ {
if (textDocument.Uri.IsUntitled())
{
var workspace = Session.Client.Workspace;
if (workspace != null)
{
}
}
var doc = new SessionDocument(textDocument); var doc = new SessionDocument(textDocument);
var session = Session; var session = Session;
doc.DocumentChanged += async (sender, args) => doc.DocumentChanged += async (sender, args) =>
@ -126,6 +134,17 @@ namespace UpsilonLanguageServer.Services
var findNode = doc.Bound.GetBottomNodeAtPosition(linePos + position.Character - 2); var findNode = doc.Bound.GetBottomNodeAtPosition(linePos + position.Character - 2);
if (findNode is BoundVariableSymbol variableSymbol) if (findNode is BoundVariableSymbol variableSymbol)
{ {
if (variableSymbol.VariableSymbol is FunctionParameterSymbol parameterSymbol &&
parameterSymbol.BoundTypeDefinition is UserDataBoundTypeDefinition udBoundDef)
{
return new CompletionList(
udBoundDef.Properties.Select(x =>
{
var (key, value) = x;
return new CompletionItem(key, CompletionItemKind.Variable,
$"{value.ActualType}({value.Type})", $"{value.Comment}", null);
}));
}
if (variableSymbol.VariableSymbol is TableVariableSymbol tableSymbol) if (variableSymbol.VariableSymbol is TableVariableSymbol tableSymbol)
{ {
return new CompletionList( return new CompletionList(
@ -136,7 +155,7 @@ namespace UpsilonLanguageServer.Services
CompletionItemKind.Variable, value.Type.ToString(), CompletionItemKind.Variable, value.Type.ToString(),
x.Value.CommentValue == null x.Value.CommentValue == null
? "" ? ""
: $"\n\n{string.Join(" \n", value.CommentValue)}"); : $"{string.Join(" \n", value.CommentValue)}", null);
})); }));
} }
} }

View File

@ -4,6 +4,7 @@ using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using JsonRpc.Standard.Contracts; using JsonRpc.Standard.Contracts;
using LanguageServer.VsCode.Contracts; using LanguageServer.VsCode.Contracts;
using Upsilon.BoundTypes;
namespace UpsilonLanguageServer.Services namespace UpsilonLanguageServer.Services
{ {
@ -46,7 +47,24 @@ namespace UpsilonLanguageServer.Services
await Client.Document.PublishDiagnostics(change.Uri, new Diagnostic[0]); await Client.Document.PublishDiagnostics(change.Uri, new Diagnostic[0]);
} }
} }
else if (string.Equals(Path.GetExtension(localPath), ".json",
StringComparison.InvariantCultureIgnoreCase))
{
var name = Path.GetFileName(localPath);
if (string.Equals(Path.GetFileName(localPath), "types.json",
StringComparison.InvariantCultureIgnoreCase))
{
if (change.Type == FileChangeType.Created || change.Type == FileChangeType.Changed)
{
BoundTypeParser.LoadBoundTypes(File.ReadAllText(localPath));
foreach (var doc in Session.Documents.Values)
{
var diag = await DiagnosticProvider.LintDocument(doc.Document, doc, Session.Settings.MaxNumberOfProblems);
await Client.Document.PublishDiagnostics(doc.Document.Uri, diag);
}
}
}
}
} }
} }
} }