Skip to content

Commit

Permalink
Improved vscode extension
Browse files Browse the repository at this point in the history
  • Loading branch information
GerardSmit committed Dec 9, 2023
1 parent cf7c040 commit 659a278
Show file tree
Hide file tree
Showing 23 changed files with 963 additions and 3,776 deletions.
11 changes: 9 additions & 2 deletions src/Yabal.Compiler/Yabal/Ast/LanguageType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,17 +99,24 @@ public override string ToString()
StaticType.Integer => "int",
StaticType.Boolean => "bool",
StaticType.Void => "void",
StaticType.Pointer => $"*{ElementType}",
StaticType.Pointer => $"{ElementType}[]",
StaticType.Struct => StructReference?.Name ?? "struct",
StaticType.Assembly => "assembly",
StaticType.Reference => $"ref {ElementType}",
StaticType.Unknown => "unknown",
StaticType.Char => "char",
StaticType.Function => $"({string.Join(", ", FunctionType?.Parameters ?? new List<LanguageType>())}) => {FunctionType?.ReturnType}",
StaticType.Function => GetFunctionName(),
_ => throw new ArgumentOutOfRangeException()
};
}

private string GetFunctionName()
{
return FunctionType?.Parameters is null or { Count: 0 }
? $"func<{FunctionType?.ReturnType ?? Void}>"
: $"func<{string.Join(", ", FunctionType.Parameters)}, {FunctionType?.ReturnType ?? Void}>";
}

public virtual bool Equals(LanguageType? other)
{
if (ReferenceEquals(null, other)) return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ public record FunctionParameter(Identifier Name, LanguageType Type, bool HasDefa

public record FunctionName(SourceRange Range);

public record FunctionIdentifier(SourceRange Range, string Name) : FunctionName(Range)
public record FunctionIdentifier(Identifier Identifier) : FunctionName(Identifier.Range)
{
public override string ToString()
{
return Name;
return Identifier.Name;
}
}

Expand Down Expand Up @@ -69,6 +69,14 @@ public override string ToString()

public bool IsDirectReference => true;

Identifier IVariable.Identifier => Name switch
{
FunctionIdentifier { Identifier: { } identifier } => identifier,
FunctionOperator { Range: var range, Operator: var op } => new Identifier(range, $"operator:{op}"),
FunctionCast { Range: var range } => new Identifier(range, $"cast:{ReturnType}"),
_ => throw new NotSupportedException()
};

Pointer IVariable.Pointer => Label;

LanguageType IVariable.Type => new(StaticType.Function, FunctionType: new LanguageFunction(ReturnType, Parameters.Select(i => i.Type).ToList()));
Expand All @@ -77,6 +85,8 @@ public override string ToString()

bool IVariable.Constant { get; set; } = true;

IEnumerable<Identifier> IVariable.References => References;

void IVariable.AddReference(Identifier identifierExpression)
{
References.Add(identifierExpression);
Expand Down
6 changes: 6 additions & 0 deletions src/Yabal.Compiler/Yabal/Visitor/Variable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ public interface IVariable

bool IsDirectReference { get; }

Identifier Identifier { get; }

Pointer Pointer { get; }

LanguageType Type { get; }
Expand All @@ -19,6 +21,8 @@ public interface IVariable

public bool Constant { get; set; }

IEnumerable<Identifier> References { get; }

void AddReference(Identifier identifierExpression);

void AddUsage();
Expand Down Expand Up @@ -49,6 +53,8 @@ public record Variable(

public List<Identifier> References { get; } = new();

IEnumerable<Identifier> IVariable.References => References;

void IVariable.AddReference(Identifier identifierExpression)
{
References.Add(identifierExpression);
Expand Down
2 changes: 1 addition & 1 deletion src/Yabal.Compiler/Yabal/Visitor/YabalVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ public override Node VisitFunctionDeclaration(YabalParser.FunctionDeclarationCon

if (context.identifierName() is { } identifierName)
{
name = new FunctionIdentifier(SourceRange.From(identifierName, _file), identifierName.GetText());
name = new FunctionIdentifier(new Identifier(SourceRange.From(identifierName, _file), identifierName.GetText()));
}
else if (context.operatorName() is { } operatorName)
{
Expand Down
10 changes: 5 additions & 5 deletions src/Yabal.Compiler/Yabal/YabalBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -973,20 +973,20 @@ private void AddStrings(InstructionBuilder builder)

public void DeclareFunction(Function function)
{
if (function.Name is FunctionIdentifier identifier)
if (function.Name is FunctionIdentifier name)
{
if (!_functions.TryGetValue(identifier.Name, out var functions))
if (!_functions.TryGetValue(name.Identifier.Name, out var functions))
{
functions = new List<Function>();
_functions.Add(identifier.Name, functions);
_functions.Add(name.Identifier.Name, functions);
}

if (functions.Any(i =>
i.Namespace.Equals(function.Namespace) &&
i.Parameters.Count == function.Parameters.Count &&
i.Parameters.Zip(function.Parameters).All(j => j.First.Type == j.Second.Type)))
{
throw new InvalidCodeException($"Function '{identifier.Name}' with the same parameters already exists.", identifier.Range);
throw new InvalidCodeException($"Function '{name.Identifier.Name}' with the same parameters already exists.", name.Range);
}

functions.Add(function);
Expand All @@ -1000,7 +1000,7 @@ public void DeclareFunction(Function function)

BinaryOperators.Add((op.Operator, function.Parameters[0].Type, function.Parameters[1].Type), function);
}
else if (function.Name is FunctionCast cast)
else if (function.Name is FunctionCast)
{
if (function.Parameters.Count != 1)
{
Expand Down
19 changes: 5 additions & 14 deletions src/Yabal.LanguageServer/Document.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,14 @@

namespace Yabal.LanguageServer;

public class Document
public class Document(DocumentUri uri, ILanguageServerFacade languageServer, TextDocumentContainer documentContainer)
{
private readonly TextDocumentContainer _documentContainer;
private readonly ILanguageServerFacade _languageServer;
private readonly string _uriString;

public Document(DocumentUri uri, ILanguageServerFacade languageServer, TextDocumentContainer documentContainer)
{
_languageServer = languageServer;
_documentContainer = documentContainer;
Uri = uri;
_uriString = uri.ToString();
}
private readonly TextDocumentContainer _documentContainer = documentContainer;
private readonly string _uriString = uri.ToString();

public YabalBuilder Builder { get; set; }

public DocumentUri Uri { get; }
public DocumentUri Uri { get; } = uri;

public int? Version { get; set; }

Expand Down Expand Up @@ -69,7 +60,7 @@ public async Task UpdateAsync(int? version, string text)

builder.Build();

_languageServer.TextDocument.PublishDiagnostics(new PublishDiagnosticsParams
languageServer.TextDocument.PublishDiagnostics(new PublishDiagnosticsParams
{
Uri = Uri,
Diagnostics = diagnostics
Expand Down
40 changes: 40 additions & 0 deletions src/Yabal.LanguageServer/Extensions/RangeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,44 @@ public static (Identifier?, Variable?) Find(this IEnumerable<Variable> variables

return default;
}

public static (Identifier?, Function?) Find(this IEnumerable<Function> functions, Position position)
{
foreach (var function in functions)
{
if (function.Name is not FunctionIdentifier { Identifier: {} name })
{
continue;
}

if (name.Range.IsInRange(position))
{
return (name, function);
}

foreach (var identifier in function.References)
{
if (identifier.Range.IsInRange(position))
{
return (identifier, function);
}
}
}

return default;
}

public static (Identifier?, IVariable?) Find(this YabalBuilder builder, Position position)
{
(var identifier, IVariable? variable) = builder.Variables.Find(position);

if (identifier != null && variable != null)
{
return (identifier, variable);
}

(identifier, variable) = builder.Functions.Find(position);

return (identifier, variable);
}
}
41 changes: 41 additions & 0 deletions src/Yabal.LanguageServer/Handlers/DefinitionHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities;
using OmniSharp.Extensions.LanguageServer.Protocol.Document;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;

namespace Yabal.LanguageServer.Handlers;

public class DefinitionHandler(TextDocumentContainer documentContainer) : IDefinitionHandler
{
public Task<LocationOrLocationLinks?> Handle(DefinitionParams request, CancellationToken cancellationToken)
{
if (!documentContainer.Documents.TryGetValue(request.TextDocument.Uri, out var document))
{
return Task.FromResult<LocationOrLocationLinks?>(null);
}

var (_, variable) = document.Builder.Find(request.Position);

if (variable == null)
{
return Task.FromResult<LocationOrLocationLinks?>(null);
}

return Task.FromResult<LocationOrLocationLinks?>(new LocationOrLocationLinks(new LocationOrLocationLink(new Location
{
Uri = request.TextDocument.Uri,
Range = variable.Identifier.Range.ToRange()
})));
}

public DefinitionRegistrationOptions GetRegistrationOptions(DefinitionCapability capability,
ClientCapabilities clientCapabilities)
{
return new DefinitionRegistrationOptions
{
DocumentSelector = TextDocumentSelector.ForLanguage("yabal")
};
}
}
13 changes: 3 additions & 10 deletions src/Yabal.LanguageServer/Handlers/HighlightHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,13 @@

namespace Yabal.LanguageServer.Handlers;

public class HighlightHandler : IDocumentHighlightHandler
public class HighlightHandler(TextDocumentContainer documentContainer) : IDocumentHighlightHandler
{
private readonly TextDocumentContainer _documentContainer;

public HighlightHandler(TextDocumentContainer documentContainer)
{
_documentContainer = documentContainer;
}

public Task<DocumentHighlightContainer?> Handle(DocumentHighlightParams request, CancellationToken cancellationToken)
{
var items = new List<DocumentHighlight>();

if (_documentContainer.Documents.TryGetValue(request.TextDocument.Uri, out var document))
if (documentContainer.Documents.TryGetValue(request.TextDocument.Uri, out var document))
{
AddHighlights(request, document, items);
}
Expand All @@ -31,7 +24,7 @@ public HighlightHandler(TextDocumentContainer documentContainer)

private static void AddHighlights(TextDocumentPositionParams request, Document document, List<DocumentHighlight> items)
{
var (_, variable) = document.Builder.Variables.Find(request.Position);
var (_, variable) = document.Builder.Find(request.Position);

if (variable == null) return;

Expand Down
20 changes: 9 additions & 11 deletions src/Yabal.LanguageServer/Handlers/HoverHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,20 @@
using OmniSharp.Extensions.LanguageServer.Protocol.Document;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
using Yabal.Ast;
using Yabal.Instructions;

namespace Yabal.LanguageServer.Handlers;

public class HoverHandler : IHoverHandler
public class HoverHandler(TextDocumentContainer documentContainer) : IHoverHandler
{
private readonly TextDocumentContainer _documentContainer;

public HoverHandler(TextDocumentContainer documentContainer)
{
_documentContainer = documentContainer;
}

public Task<Hover?> Handle(HoverParams request, CancellationToken cancellationToken)
{
if (!_documentContainer.Documents.TryGetValue(request.TextDocument.Uri, out var document))
if (!documentContainer.Documents.TryGetValue(request.TextDocument.Uri, out var document))
{
return Task.FromResult<Hover?>(null);
}

var (identifier, variable) = document.Builder.Variables.Find(request.Position);
var (identifier, variable) = document.Builder.Find(request.Position);

if (identifier == null || variable == null)
{
Expand All @@ -36,7 +30,11 @@ public HoverHandler(TextDocumentContainer documentContainer)

sb.AppendLine($"Type: {variable.Type} ");
sb.AppendLine($"Size: {size} ");
sb.AppendLine($"Variable address: {variable.Pointer.Address} ");

if (variable.Pointer is not InstructionLabel)
{
sb.AppendLine($"Variable address: {variable.Pointer.Address} ");
}

if (variable.Initializer is IPointerSource { Pointer: {} pointer })
{
Expand Down
60 changes: 60 additions & 0 deletions src/Yabal.LanguageServer/Handlers/RenameHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using OmniSharp.Extensions.LanguageServer.Protocol;
using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities;
using OmniSharp.Extensions.LanguageServer.Protocol.Document;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;

namespace Yabal.LanguageServer.Handlers;

public class RenameHandler(TextDocumentContainer documentContainer) : IRenameHandler
{
public Task<WorkspaceEdit?> Handle(RenameParams request, CancellationToken cancellationToken)
{
if (!documentContainer.Documents.TryGetValue(request.TextDocument.Uri, out var document))
{
return Task.FromResult<WorkspaceEdit?>(null);
}

var (_, variable) = document.Builder.Find(request.Position);

if (variable == null)
{
return Task.FromResult<WorkspaceEdit?>(null);
}

return Task.FromResult<WorkspaceEdit?>(new WorkspaceEdit
{
Changes = new Dictionary<DocumentUri, IEnumerable<TextEdit>>
{
[request.TextDocument.Uri] =
[
..variable.References
.OrderByDescending(i => i.Range)
.DistinctBy(i => i.Range.Index)
.Select(i => new TextEdit
{
Range = i.Range.ToRange(),
NewText = request.NewName
}),
new TextEdit
{
Range = variable.Identifier.Range.ToRange(),
NewText = request.NewName
}
]
}
});
}

public RenameRegistrationOptions GetRegistrationOptions(RenameCapability capability, ClientCapabilities clientCapabilities)
{
return new RenameRegistrationOptions
{
DocumentSelector = TextDocumentSelector.ForLanguage("yabal")
};
}
}
Loading

0 comments on commit 659a278

Please sign in to comment.