Skip to content

Commit 4593ddf

Browse files
committed
Add support for hover
1 parent 221e3d7 commit 4593ddf

File tree

8 files changed

+214
-23
lines changed

8 files changed

+214
-23
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ Still in development.
1010
#### Current Features
1111

1212
- Completion
13+
- Hover
1314

1415
#### Planned Features
1516

1617
- Diagnostics
17-
- Hover
1818
- Jump to def
1919

2020
## 🔨 Usage

Server/Buffer.cs

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
1-
using ShaderlabVS;
1+
using System.Numerics;
2+
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
3+
using ShaderlabVS;
4+
using static System.Net.Mime.MediaTypeNames;
25

36
namespace ShaderLS
47
{
58
public class Buffer
69
{
7-
private string _text = "";
10+
private string _text = ""; // full buffer
811
private HashSet<string> _tokens = new();
912

13+
1014
public string GetText() { return _text; }
1115
public HashSet<string> Tokens() { return _tokens; }
1216

@@ -16,6 +20,37 @@ public Buffer(string text)
1620
SetWordsInDocuments(text);
1721
}
1822

23+
public string GetWordAtPosition(Position position)
24+
{
25+
if (position == null)
26+
return null;
27+
28+
string[] lines = _text.Split("\n");
29+
30+
int line = position.Line;
31+
int column = position.Character;
32+
33+
string lineStr = lines[line];
34+
35+
string[] words = GetWords(lineStr);
36+
37+
int currentColumn = 0;
38+
39+
string on = words[0];
40+
41+
foreach (var word in words)
42+
{
43+
if (column <= currentColumn)
44+
break;
45+
46+
currentColumn = lineStr.IndexOf(word, currentColumn);
47+
currentColumn += word.Length; // push to the end
48+
on = word;
49+
}
50+
51+
return on;
52+
}
53+
1954
private void SetWordsInDocuments(string text)
2055
{
2156
var reader = new StringReader(text);
@@ -30,10 +65,7 @@ private void SetWordsInDocuments(string text)
3065
continue;
3166
}
3267

33-
string[] words = line.Split(
34-
new char[] { '{', '}', ' ', '\t', '(', ')', '[', ']', '+', '-', '*', '/', '%', '^', '>', '<', ':',
35-
'.', ';', '\"', '\'', '?', '\\', '&', '|', '`', '$', '#', ','},
36-
StringSplitOptions.RemoveEmptyEntries);
68+
string[] words = GetWords(line);
3769

3870
foreach (var word in words)
3971
{
@@ -43,5 +75,13 @@ private void SetWordsInDocuments(string text)
4375
line = reader.ReadLine();
4476
}
4577
}
78+
79+
private string[] GetWords(string text)
80+
{
81+
return text.Split(
82+
new char[] { '{', '}', ' ', '\t', '(', ')', '[', ']', '+', '-', '*', '/', '%', '^', '>', '<', ':',
83+
'.', ';', '\"', '\'', '?', '\\', '&', '|', '`', '$', '#', ','},
84+
StringSplitOptions.RemoveEmptyEntries);
85+
}
4686
}
4787
}

Server/BufferService.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,23 @@ public string GetText(DocumentUri key)
3737
return _buffers[key].GetText();
3838
}
3939

40+
public string GetWordAtPosition(DocumentUri key, Position position)
41+
{
42+
return _buffers[key].GetWordAtPosition(position);
43+
}
44+
4045
public HashSet<string> Tokens(DocumentUri key)
4146
{
4247
return _buffers[key].Tokens();
4348
}
4449

50+
//public string GetText(DocumentUri key, Position position)
51+
//{
52+
// string text = GetText(key);
53+
// GetIndex(text, position);
54+
// return ;
55+
//}
56+
4557
private static int GetIndex(string buffer, Position position)
4658
{
4759
var index = 0;

Server/Handlers/CodeActionHandler.cs

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,28 @@
44
using OmniSharp.Extensions.LanguageServer.Protocol.Document;
55
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
66
using OmniSharp.Extensions.LanguageServer.Protocol.Server;
7-
using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities;
87
using OmniSharp.Extensions.LanguageServer.Protocol.Workspace;
8+
using ShaderLS.Management;
99

1010
namespace ShaderLS.Handlers
1111
{
1212
public class CodeActionHandler : CodeActionHandlerBase, IExecuteCommandHandler
1313
{
1414
private readonly ILogger<CodeActionHandler> _logger;
1515
private readonly ILanguageServerConfiguration _configuration;
16-
17-
private readonly DocumentSelector _documentSelector = new DocumentSelector(
18-
new DocumentFilter { Pattern = "**/*.shader" },
19-
new DocumentFilter { Pattern = "**/*.cginc" },
20-
new DocumentFilter { Pattern = "**/*.glslinc" },
21-
new DocumentFilter { Pattern = "**/*.compute" },
22-
new DocumentFilter { Pattern = "**/*.cg" },
23-
new DocumentFilter { Pattern = "**/*.hlsl" }
24-
);
16+
private readonly Workspace _workspace;
17+
private readonly DocumentSelector _documentSelector;
2518

2619
public CodeActionHandler(
2720
ILogger<CodeActionHandler> logger,
28-
ILanguageServerConfiguration configuration)
21+
ILanguageServerConfiguration configuration,
22+
DocumentSelector documentSelector,
23+
Workspace workspace)
2924
{
3025
this._logger = logger;
3126
this._configuration = configuration;
27+
this._documentSelector = documentSelector;
28+
this._workspace = workspace;
3229
}
3330

3431
public ExecuteCommandRegistrationOptions GetRegistrationOptions(ExecuteCommandCapability capability, ClientCapabilities clientCapabilities)

Server/Handlers/CompletionHandler.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using Microsoft.Extensions.Logging;
2-
using OmniSharp.Extensions.LanguageServer.Protocol;
32
using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities;
43
using OmniSharp.Extensions.LanguageServer.Protocol.Document;
54
using OmniSharp.Extensions.LanguageServer.Protocol.Models;

Server/Handlers/HoverHandler.cs

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
using Microsoft.Extensions.Logging;
2+
using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities;
3+
using OmniSharp.Extensions.LanguageServer.Protocol.Document;
4+
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
5+
using OmniSharp.Extensions.LanguageServer.Protocol.Server;
6+
using ShaderlabVS.Data;
7+
using ShaderLS.Management;
8+
9+
namespace ShaderLS.Handlers
10+
{
11+
public class HoverHandler : HoverHandlerBase
12+
{
13+
private readonly ILogger<HoverHandler> _logger;
14+
private readonly ILanguageServerConfiguration _configuration;
15+
private readonly Workspace _workspace;
16+
private readonly DocumentSelector _documentSelector;
17+
18+
private Dictionary<string, string> _quickInfos = new();
19+
20+
public HoverHandler(
21+
ILogger<HoverHandler> logger,
22+
ILanguageServerConfiguration configuration,
23+
DocumentSelector documentSelector,
24+
Workspace workspace)
25+
{
26+
this._logger = logger;
27+
this._configuration = configuration;
28+
this._documentSelector = documentSelector;
29+
this._workspace = workspace;
30+
QuickInfoInit();
31+
}
32+
33+
public override async Task<Hover?> Handle(HoverParams request, CancellationToken cancellationToken)
34+
{
35+
var uri = request.TextDocument.Uri;
36+
37+
Position position = request.Position;
38+
39+
string keyText = _workspace.BufferService.GetWordAtPosition(uri, position);
40+
41+
string info;
42+
_quickInfos.TryGetValue(keyText, out info);
43+
44+
if (info == null)
45+
info = string.Empty;
46+
47+
_logger.LogWarning("keyText: " + keyText);
48+
_logger.LogWarning("info: " + info);
49+
50+
return new Hover
51+
{
52+
Contents = new MarkedStringsOrMarkupContent(new MarkupContent() { Value = info, Kind = MarkupKind.Markdown })
53+
};
54+
}
55+
56+
protected override HoverRegistrationOptions CreateRegistrationOptions(HoverCapability capability, ClientCapabilities clientCapabilities)
57+
=> new HoverRegistrationOptions()
58+
{
59+
DocumentSelector = _documentSelector
60+
};
61+
62+
private void QuickInfoInit()
63+
{
64+
if (_quickInfos.Keys.Count != 0)
65+
return;
66+
67+
ShaderlabDataManager.Instance.HLSLCGFunctions.ForEach((f) =>
68+
{
69+
if (_quickInfos.ContainsKey(f.Name))
70+
{
71+
string info = _quickInfos[f.Name];
72+
info = info + string.Format("\nFunction: {0}", f.Description);
73+
_quickInfos[f.Name] = info;
74+
}
75+
else
76+
{
77+
_quickInfos.Add(f.Name, f.Description);
78+
}
79+
});
80+
81+
ShaderlabDataManager.Instance.UnityBuiltinDatatypes.ForEach((d) =>
82+
{
83+
if (_quickInfos.ContainsKey(d.Name))
84+
{
85+
_quickInfos[d.Name] = _quickInfos[d.Name] + string.Format("\nUnity3d built-in balues: {0}", d.Description);
86+
}
87+
else
88+
{
89+
_quickInfos.Add(d.Name, d.Description);
90+
}
91+
});
92+
93+
ShaderlabDataManager.Instance.UnityBuiltinFunctions.ForEach((f) =>
94+
{
95+
if (_quickInfos.ContainsKey(f.Name))
96+
{
97+
_quickInfos[f.Name] = _quickInfos[f.Name] + string.Format("\nUnity3D built-in function: {0}", f.Description);
98+
}
99+
else
100+
{
101+
_quickInfos.Add(f.Name, f.Description);
102+
}
103+
});
104+
105+
ShaderlabDataManager.Instance.UnityBuiltinMacros.ForEach((f) =>
106+
{
107+
108+
string description = string.Format("{0}\n{1}", string.Join(";\n", f.Synopsis), f.Description);
109+
if (_quickInfos.ContainsKey(f.Name))
110+
{
111+
_quickInfos[f.Name] = _quickInfos[f.Name] + string.Format("\nUnity3D built-in macros: {0}", description);
112+
}
113+
else
114+
{
115+
_quickInfos.Add(f.Name, description);
116+
}
117+
});
118+
119+
ShaderlabDataManager.Instance.UnityKeywords.ForEach((k) =>
120+
{
121+
if (_quickInfos.ContainsKey(k.Name))
122+
{
123+
_quickInfos[k.Name] = _quickInfos[k.Name] + string.Format("\nUnity3D keywords: {0}", k.Description);
124+
}
125+
else
126+
{
127+
_quickInfos.Add(k.Name, k.Description);
128+
}
129+
});
130+
131+
ShaderlabDataManager.Instance.UnityBuiltinValues.ForEach((v) =>
132+
{
133+
if (_quickInfos.ContainsKey(v.Name))
134+
{
135+
_quickInfos[v.Name] = _quickInfos[v.Name] + string.Format("\nUnity3d built-in values: {0}", v.VauleDescription);
136+
}
137+
else
138+
{
139+
_quickInfos.Add(v.Name, v.VauleDescription);
140+
}
141+
});
142+
}
143+
144+
}
145+
}

Server/Handlers/TextDocumentSyncHandler.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,7 @@ public class TextDocumentSyncHandler : TextDocumentSyncHandlerBase
1616
{
1717
private readonly ILogger<TextDocumentSyncHandler> _logger;
1818
private readonly ILanguageServerConfiguration _configuration;
19-
20-
private readonly TextDocumentSyncKind _documentSyncKind;
2119
private readonly Workspace _workspace;
22-
2320
private readonly DocumentSelector _documentSelector;
2421

2522
public TextDocumentSyncHandler(
@@ -64,7 +61,6 @@ public override async Task<Unit> Handle(DidOpenTextDocumentParams notification,
6461
_workspace.Init(uri);
6562
_logger.LogWarning("didOpen: " + uri.Path);
6663
_workspace.BufferService.Add(uri, text);
67-
_logger.LogWarning(_workspace.BufferService.Tokens(uri).ToString());
6864
return Unit.Value;
6965
}
7066

Server/Program.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,14 @@ private static void Configure(LanguageServerOptions options)
4242
.WithHandler<TextDocumentSyncHandler>()
4343
.WithHandler<CompletionHandler>()
4444
//.WithHandler<CodeActionHandler>()
45+
.WithHandler<HoverHandler>()
4546
.WithServices(ConfigureServices);
4647
}
4748

4849
private static void ConfigureServices(IServiceCollection services)
4950
{
5051
services.AddSingleton(new ConfigurationItem { Section = "shaderlab" });
52+
services.AddSingleton(new ConfigurationItem { Section = "shader-ls.completion.word" });
5153
services.AddSingleton(new DocumentSelector(
5254
new DocumentFilter { Pattern = "**/*.shader" },
5355
new DocumentFilter { Pattern = "**/*.cginc" },

0 commit comments

Comments
 (0)