Support for setting userdata types, validating them and autocompleting them

This commit is contained in:
2018-11-29 18:13:45 +01:00
parent b1b863d5a3
commit e0420e9315
9 changed files with 116 additions and 11 deletions

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.IO;
using System.Threading.Tasks;
using JsonRpc.Standard;
using JsonRpc.Standard.Contracts;
@@ -16,6 +17,15 @@ namespace UpsilonLanguageServer.Services
public InitializeResult Initialize(int processId, Uri rootUri, ClientCapabilities capabilities,
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
{
HoverProvider = true,

View File

@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -6,9 +7,8 @@ using System.Threading.Tasks;
using JsonRpc.Standard.Contracts;
using LanguageServer.VsCode;
using LanguageServer.VsCode.Contracts;
using LanguageServer.VsCode.Server;
using Upsilon.Binder;
using Upsilon.Parser;
using Upsilon.BoundTypes;
using Upsilon.Utilities;
namespace UpsilonLanguageServer.Services
@@ -62,16 +62,24 @@ namespace UpsilonLanguageServer.Services
[JsonRpcMethod]
public SignatureHelp SignatureHelp(TextDocumentIdentifier textDocument, Position position)
{
// TODO
return new SignatureHelp(new List<SignatureInformation>
{
new SignatureInformation("**Function1**", "Documentation1"),
new SignatureInformation("**Function2** <strong>test</strong>", "Documentation2"),
});
}
[JsonRpcMethod(IsNotification = true)]
public async Task DidOpen(TextDocumentItem textDocument)
{
if (textDocument.Uri.IsUntitled())
{
var workspace = Session.Client.Workspace;
if (workspace != null)
{
}
}
var doc = new SessionDocument(textDocument);
var session = Session;
doc.DocumentChanged += async (sender, args) =>
@@ -126,6 +134,17 @@ namespace UpsilonLanguageServer.Services
var findNode = doc.Bound.GetBottomNodeAtPosition(linePos + position.Character - 2);
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)
{
return new CompletionList(
@@ -136,7 +155,7 @@ namespace UpsilonLanguageServer.Services
CompletionItemKind.Variable, value.Type.ToString(),
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 JsonRpc.Standard.Contracts;
using LanguageServer.VsCode.Contracts;
using Upsilon.BoundTypes;
namespace UpsilonLanguageServer.Services
{
@@ -46,7 +47,24 @@ namespace UpsilonLanguageServer.Services
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);
}
}
}
}
}
}
}