Skip to content
This repository was archived by the owner on Sep 24, 2019. It is now read-only.

Commit 087256b

Browse files
author
N. Taylor Mullen
committed
Add directive attribute support.
- Updated `TagHelperDescriptorJsonConverter` to match what is in Razor. - Added the new completion item provider APIs to our list of services. - Created a new `Completion` namespace to hold off of Razor's various completion pieces. - Added a new completion item provider to provide `@...` when in a directive attribute compatible area when no text has been typed. - Partially moved the existing completion system over to `AttributeCompletionDescription`. There's more work that needs to be done here to be able to delete Razor.VSCode's description info types in favor of Razor's. - Expanded the completion endpoint to understand `Directive`s, `DirectiveAttribute`s and `DirectiveAttributeParameter`s. - Updated the `RazorDiagnosticPublisher` to handle cases when the underlying `RazorCodeDocument` has been garbage collected. Razor no longer caches these objects. - Added and updated loads of tests. dotnet/aspnetcore#6364
1 parent ab251b3 commit 087256b

25 files changed

+1169
-316
lines changed

build/dependencies.props

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
<PropertyGroup Label="Package Versions">
33
<MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>3.0.0-preview3.19120.3</MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion>
44
<InternalAspNetCoreSdkPackageVersion>3.0.0-alpha1-20181108.5</InternalAspNetCoreSdkPackageVersion>
5-
<MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>3.0.0-preview5.19208.5</MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>
6-
<MicrosoftAspNetCoreMvcRazorExtensionsVersion1_XPackageVersion>3.0.0-preview5.19208.5</MicrosoftAspNetCoreMvcRazorExtensionsVersion1_XPackageVersion>
7-
<MicrosoftAspNetCoreMvcRazorExtensionsVersion2_XPackageVersion>3.0.0-preview5.19208.5</MicrosoftAspNetCoreMvcRazorExtensionsVersion2_XPackageVersion>
5+
<MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>3.0.0-preview7.19303.4</MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>
6+
<MicrosoftAspNetCoreMvcRazorExtensionsVersion1_XPackageVersion>3.0.0-preview7.19303.4</MicrosoftAspNetCoreMvcRazorExtensionsVersion1_XPackageVersion>
7+
<MicrosoftAspNetCoreMvcRazorExtensionsVersion2_XPackageVersion>3.0.0-preview7.19303.4</MicrosoftAspNetCoreMvcRazorExtensionsVersion2_XPackageVersion>
88
<MicrosoftAspNetCoreTestingPackageVersion>3.0.0-alpha1-10643</MicrosoftAspNetCoreTestingPackageVersion>
99
<MicrosoftBuildPackageVersion>15.9.20</MicrosoftBuildPackageVersion>
1010
<MicrosoftCodeAnalysisCSharpPackageVersion>3.0.0-beta4-final</MicrosoftCodeAnalysisCSharpPackageVersion>
1111
<MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>3.0.0-beta4-final</MicrosoftCodeAnalysisCSharpWorkspacesPackageVersion>
1212
<MicrosoftCodeAnalysisCSharpFeaturesPackageVersion>3.0.0-beta4-final</MicrosoftCodeAnalysisCSharpFeaturesPackageVersion>
13-
<MicrosoftCodeAnalysisRazorWorkspacesPackageVersion>3.0.0-preview5.19208.5</MicrosoftCodeAnalysisRazorWorkspacesPackageVersion>
13+
<MicrosoftCodeAnalysisRazorWorkspacesPackageVersion>3.0.0-preview7.19303.4</MicrosoftCodeAnalysisRazorWorkspacesPackageVersion>
1414
<MicrosoftCodeAnalysisVisualBasicFeaturesPackageVersion>3.0.0-beta4-final</MicrosoftCodeAnalysisVisualBasicFeaturesPackageVersion>
1515
<MicrosoftCodeAnalysisWorkspacesCommonPackageVersion>3.0.0-beta4-final</MicrosoftCodeAnalysisWorkspacesCommonPackageVersion>
1616
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>3.0.0-preview4.19155.3</MicrosoftExtensionsLoggingAbstractionsPackageVersion>

build/sources.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<RestoreSources Condition="'$(DotNetBuildOffline)' != 'true' AND '$(AspNetUniverseBuildOffline)' != 'true' ">
77
$(RestoreSources);
88
https://dotnet.myget.org/F/dotnet-core/api/v3/index.json;
9-
https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json;
9+
https://dotnetfeed.blob.core.windows.net/aspnet-aspnetcore-tooling/index.json;
1010
https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json;
1111
https://dotnet.myget.org/F/roslyn/api/v3/index.json;
1212
https://dotnet.myget.org/F/roslyn-tools/api/v3/index.json;

src/Microsoft.AspNetCore.Razor.LanguageServer.Common/Serialization/TagHelperDescriptorJsonConverter.cs

Lines changed: 96 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s
133133
writer.WriteEndObject();
134134
}
135135

136-
private void WriteAllowedChildTags(JsonWriter writer, AllowedChildTagDescriptor allowedChildTag, JsonSerializer serializer)
136+
private static void WriteAllowedChildTags(JsonWriter writer, AllowedChildTagDescriptor allowedChildTag, JsonSerializer serializer)
137137
{
138138
writer.WriteStartObject();
139139

@@ -149,7 +149,7 @@ private void WriteAllowedChildTags(JsonWriter writer, AllowedChildTagDescriptor
149149
writer.WriteEndObject();
150150
}
151151

152-
private void WriteBoundAttribute(JsonWriter writer, BoundAttributeDescriptor boundAttribute, JsonSerializer serializer)
152+
private static void WriteBoundAttribute(JsonWriter writer, BoundAttributeDescriptor boundAttribute, JsonSerializer serializer)
153153
{
154154
writer.WriteStartObject();
155155

@@ -180,6 +180,42 @@ private void WriteBoundAttribute(JsonWriter writer, BoundAttributeDescriptor bou
180180
writer.WritePropertyName(nameof(BoundAttributeDescriptor.Metadata));
181181
WriteMetadata(writer, boundAttribute.Metadata);
182182

183+
writer.WritePropertyName(nameof(BoundAttributeDescriptor.BoundAttributeParameters));
184+
writer.WriteStartArray();
185+
foreach (var boundAttributeParameter in boundAttribute.BoundAttributeParameters)
186+
{
187+
WriteBoundAttributeParameter(writer, boundAttributeParameter, serializer);
188+
}
189+
writer.WriteEndArray();
190+
191+
writer.WriteEndObject();
192+
}
193+
194+
private static void WriteBoundAttributeParameter(JsonWriter writer, BoundAttributeParameterDescriptor boundAttributeParameter, JsonSerializer serializer)
195+
{
196+
writer.WriteStartObject();
197+
198+
writer.WritePropertyName(nameof(BoundAttributeParameterDescriptor.Kind));
199+
writer.WriteValue(boundAttributeParameter.Kind);
200+
201+
writer.WritePropertyName(nameof(BoundAttributeParameterDescriptor.Name));
202+
writer.WriteValue(boundAttributeParameter.Name);
203+
204+
writer.WritePropertyName(nameof(BoundAttributeParameterDescriptor.TypeName));
205+
writer.WriteValue(boundAttributeParameter.TypeName);
206+
207+
writer.WritePropertyName(nameof(BoundAttributeParameterDescriptor.IsEnum));
208+
writer.WriteValue(boundAttributeParameter.IsEnum);
209+
210+
writer.WritePropertyName(nameof(BoundAttributeParameterDescriptor.Documentation));
211+
writer.WriteValue(boundAttributeParameter.Documentation);
212+
213+
writer.WritePropertyName(nameof(BoundAttributeParameterDescriptor.Diagnostics));
214+
serializer.Serialize(writer, boundAttributeParameter.Diagnostics);
215+
216+
writer.WritePropertyName(nameof(BoundAttributeParameterDescriptor.Metadata));
217+
WriteMetadata(writer, boundAttributeParameter.Metadata);
218+
183219
writer.WriteEndObject();
184220
}
185221

@@ -194,7 +230,7 @@ private static void WriteMetadata(JsonWriter writer, IReadOnlyDictionary<string,
194230
writer.WriteEndObject();
195231
}
196232

197-
private void WriteTagMatchingRule(JsonWriter writer, TagMatchingRuleDescriptor ruleDescriptor, JsonSerializer serializer)
233+
private static void WriteTagMatchingRule(JsonWriter writer, TagMatchingRuleDescriptor ruleDescriptor, JsonSerializer serializer)
198234
{
199235
writer.WriteStartObject();
200236

@@ -221,7 +257,7 @@ private void WriteTagMatchingRule(JsonWriter writer, TagMatchingRuleDescriptor r
221257
writer.WriteEndObject();
222258
}
223259

224-
private void WriteRequiredAttribute(JsonWriter writer, RequiredAttributeDescriptor requiredAttribute, JsonSerializer serializer)
260+
private static void WriteRequiredAttribute(JsonWriter writer, RequiredAttributeDescriptor requiredAttribute, JsonSerializer serializer)
225261
{
226262
writer.WriteStartObject();
227263

@@ -240,10 +276,13 @@ private void WriteRequiredAttribute(JsonWriter writer, RequiredAttributeDescript
240276
writer.WritePropertyName(nameof(RequiredAttributeDescriptor.Diagnostics));
241277
serializer.Serialize(writer, requiredAttribute.Diagnostics);
242278

279+
writer.WritePropertyName(nameof(RequiredAttributeDescriptor.Metadata));
280+
WriteMetadata(writer, requiredAttribute.Metadata);
281+
243282
writer.WriteEndObject();
244283
}
245284

246-
private void ReadTagMatchingRule(TagMatchingRuleDescriptorBuilder builder, JObject rule, JsonSerializer serializer)
285+
private static void ReadTagMatchingRule(TagMatchingRuleDescriptorBuilder builder, JObject rule, JsonSerializer serializer)
247286
{
248287
var tagName = rule[nameof(TagMatchingRuleDescriptor.TagName)].Value<string>();
249288
var attributes = rule[nameof(TagMatchingRuleDescriptor.Attributes)].Value<JArray>();
@@ -269,13 +308,14 @@ private void ReadTagMatchingRule(TagMatchingRuleDescriptorBuilder builder, JObje
269308
}
270309
}
271310

272-
private void ReadRequiredAttribute(RequiredAttributeDescriptorBuilder builder, JObject attribute, JsonSerializer serializer)
311+
private static void ReadRequiredAttribute(RequiredAttributeDescriptorBuilder builder, JObject attribute, JsonSerializer serializer)
273312
{
274313
var name = attribute[nameof(RequiredAttributeDescriptor.Name)].Value<string>();
275314
var nameComparison = attribute[nameof(RequiredAttributeDescriptor.NameComparison)].Value<int>();
276315
var value = attribute[nameof(RequiredAttributeDescriptor.Value)].Value<string>();
277316
var valueComparison = attribute[nameof(RequiredAttributeDescriptor.ValueComparison)].Value<int>();
278317
var diagnostics = attribute[nameof(RequiredAttributeDescriptor.Diagnostics)].Value<JArray>();
318+
var metadata = attribute[nameof(RequiredAttributeDescriptor.Metadata)].Value<JObject>();
279319

280320
builder.Name = name;
281321
builder.NameComparisonMode = (RequiredAttributeDescriptor.NameComparisonMode)nameComparison;
@@ -288,9 +328,16 @@ private void ReadRequiredAttribute(RequiredAttributeDescriptorBuilder builder, J
288328
var diagnosticObject = serializer.Deserialize<RazorDiagnostic>(diagnosticReader);
289329
builder.Diagnostics.Add(diagnosticObject);
290330
}
331+
332+
var metadataReader = metadata.CreateReader();
333+
var metadataValue = serializer.Deserialize<Dictionary<string, string>>(metadataReader);
334+
foreach (var item in metadataValue)
335+
{
336+
builder.Metadata[item.Key] = item.Value;
337+
}
291338
}
292339

293-
private void ReadAllowedChildTag(AllowedChildTagDescriptorBuilder builder, JObject childTag, JsonSerializer serializer)
340+
private static void ReadAllowedChildTag(AllowedChildTagDescriptorBuilder builder, JObject childTag, JsonSerializer serializer)
294341
{
295342
var name = childTag[nameof(AllowedChildTagDescriptor.Name)].Value<string>();
296343
var displayName = childTag[nameof(AllowedChildTagDescriptor.DisplayName)].Value<string>();
@@ -307,7 +354,7 @@ private void ReadAllowedChildTag(AllowedChildTagDescriptorBuilder builder, JObje
307354
}
308355
}
309356

310-
private void ReadBoundAttribute(BoundAttributeDescriptorBuilder builder, JObject attribute, JsonSerializer serializer)
357+
private static void ReadBoundAttribute(BoundAttributeDescriptorBuilder builder, JObject attribute, JsonSerializer serializer)
311358
{
312359
var descriptorKind = attribute[nameof(BoundAttributeDescriptor.Kind)].Value<string>();
313360
var name = attribute[nameof(BoundAttributeDescriptor.Name)].Value<string>();
@@ -318,6 +365,7 @@ private void ReadBoundAttribute(BoundAttributeDescriptorBuilder builder, JObject
318365
var documentation = attribute[nameof(BoundAttributeDescriptor.Documentation)].Value<string>();
319366
var diagnostics = attribute[nameof(BoundAttributeDescriptor.Diagnostics)].Value<JArray>();
320367
var metadata = attribute[nameof(BoundAttributeDescriptor.Metadata)].Value<JObject>();
368+
var boundAttributeParameters = attribute[nameof(BoundAttributeDescriptor.BoundAttributeParameters)].Value<JArray>();
321369

322370
builder.Name = name;
323371
builder.TypeName = typeName;
@@ -346,6 +394,46 @@ private void ReadBoundAttribute(BoundAttributeDescriptorBuilder builder, JObject
346394
{
347395
builder.Metadata[item.Key] = item.Value;
348396
}
397+
398+
foreach (var boundAttributeParameter in boundAttributeParameters)
399+
{
400+
var parameter = boundAttributeParameter.Value<JObject>();
401+
builder.BindAttributeParameter(b => ReadBoundAttributeParameter(b, parameter, serializer));
402+
}
403+
}
404+
405+
private static void ReadBoundAttributeParameter(BoundAttributeParameterDescriptorBuilder builder, JObject parameter, JsonSerializer serializer)
406+
{
407+
var descriptorKind = parameter[nameof(BoundAttributeParameterDescriptor.Kind)].Value<string>();
408+
var name = parameter[nameof(BoundAttributeParameterDescriptor.Name)].Value<string>();
409+
var typeName = parameter[nameof(BoundAttributeParameterDescriptor.TypeName)].Value<string>();
410+
var isEnum = parameter[nameof(BoundAttributeParameterDescriptor.IsEnum)].Value<bool>();
411+
var documentation = parameter[nameof(BoundAttributeParameterDescriptor.Documentation)].Value<string>();
412+
var diagnostics = parameter[nameof(BoundAttributeParameterDescriptor.Diagnostics)].Value<JArray>();
413+
var metadata = parameter[nameof(BoundAttributeParameterDescriptor.Metadata)].Value<JObject>();
414+
415+
builder.Name = name;
416+
builder.TypeName = typeName;
417+
builder.Documentation = documentation;
418+
419+
if (isEnum)
420+
{
421+
builder.IsEnum = true;
422+
}
423+
424+
foreach (var diagnostic in diagnostics)
425+
{
426+
var diagnosticReader = diagnostic.CreateReader();
427+
var diagnosticObject = serializer.Deserialize<RazorDiagnostic>(diagnosticReader);
428+
builder.Diagnostics.Add(diagnosticObject);
429+
}
430+
431+
var metadataReader = metadata.CreateReader();
432+
var metadataValue = serializer.Deserialize<Dictionary<string, string>>(metadataReader);
433+
foreach (var item in metadataValue)
434+
{
435+
builder.Metadata[item.Key] = item.Value;
436+
}
349437
}
350438
}
351439
}

src/Microsoft.AspNetCore.Razor.LanguageServer/AttributeDescriptionInfo.cs renamed to src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/AttributeDescriptionInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
using System;
55
using System.Collections.Generic;
66

7-
namespace Microsoft.AspNetCore.Razor.LanguageServer
7+
namespace Microsoft.AspNetCore.Razor.LanguageServer.Completion
88
{
99
internal class AttributeDescriptionInfo
1010
{
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using Microsoft.CodeAnalysis.Razor.Completion;
6+
using Newtonsoft.Json.Linq;
7+
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
8+
9+
namespace Microsoft.AspNetCore.Razor.LanguageServer.Completion
10+
{
11+
internal static class CompletionItemExtensions
12+
{
13+
private const string TagHelperElementDataKey = "_TagHelperElementData_";
14+
private const string TagHelperAttributeDataKey = "_TagHelperAttributes_";
15+
private const string AttributeCompletionDataKey = "_AttributeCompletion_";
16+
private const string RazorCompletionItemKind = "_CompletionItemKind_";
17+
18+
public static void SetRazorCompletionKind(this CompletionItem completion, RazorCompletionItemKind completionItemKind)
19+
{
20+
if (completion is null)
21+
{
22+
throw new ArgumentNullException(nameof(completion));
23+
}
24+
25+
var data = completion.Data ?? new JObject();
26+
data[RazorCompletionItemKind] = JToken.FromObject(completionItemKind);
27+
completion.Data = data;
28+
}
29+
30+
public static bool TryGetRazorCompletionKind(this CompletionItem completion, out RazorCompletionItemKind completionItemKind)
31+
{
32+
if (completion is null)
33+
{
34+
throw new ArgumentNullException(nameof(completion));
35+
}
36+
37+
if (completion.Data is JObject data && data.ContainsKey(RazorCompletionItemKind))
38+
{
39+
completionItemKind = data[RazorCompletionItemKind].ToObject<RazorCompletionItemKind>();
40+
return true;
41+
}
42+
43+
completionItemKind = default;
44+
return false;
45+
}
46+
47+
public static bool IsTagHelperElementCompletion(this CompletionItem completion)
48+
{
49+
if (completion.Data is JObject data && data.ContainsKey(TagHelperElementDataKey))
50+
{
51+
return true;
52+
}
53+
54+
return false;
55+
}
56+
57+
public static bool IsTagHelperAttributeCompletion(this CompletionItem completion)
58+
{
59+
if (completion.Data is JObject data && data.ContainsKey(TagHelperAttributeDataKey))
60+
{
61+
return true;
62+
}
63+
64+
return false;
65+
}
66+
67+
public static void SetDescriptionInfo(this CompletionItem completion, ElementDescriptionInfo elementDescriptionInfo)
68+
{
69+
var data = completion.Data ?? new JObject();
70+
data[TagHelperElementDataKey] = JObject.FromObject(elementDescriptionInfo);
71+
completion.Data = data;
72+
}
73+
74+
public static void SetDescriptionInfo(this CompletionItem completion, AttributeDescriptionInfo attributeDescriptionInfo)
75+
{
76+
var data = completion.Data ?? new JObject();
77+
data[TagHelperAttributeDataKey] = JObject.FromObject(attributeDescriptionInfo);
78+
completion.Data = data;
79+
}
80+
81+
public static void SetDescriptionInfo(this CompletionItem completion, AttributeCompletionDescription attributeDescriptionInfo)
82+
{
83+
if (completion is null)
84+
{
85+
throw new ArgumentNullException(nameof(completion));
86+
}
87+
88+
if (attributeDescriptionInfo is null)
89+
{
90+
throw new ArgumentNullException(nameof(attributeDescriptionInfo));
91+
}
92+
93+
var data = completion.Data ?? new JObject();
94+
data[AttributeCompletionDataKey] = JObject.FromObject(attributeDescriptionInfo);
95+
completion.Data = data;
96+
}
97+
98+
public static ElementDescriptionInfo GetElementDescriptionInfo(this CompletionItem completion)
99+
{
100+
if (completion.Data is JObject data && data.ContainsKey(TagHelperElementDataKey))
101+
{
102+
var descriptionInfo = data[TagHelperElementDataKey].ToObject<ElementDescriptionInfo>();
103+
return descriptionInfo;
104+
}
105+
106+
return ElementDescriptionInfo.Default;
107+
}
108+
109+
public static AttributeDescriptionInfo GetTagHelperAttributeDescriptionInfo(this CompletionItem completion)
110+
{
111+
if (completion.Data is JObject data && data.ContainsKey(TagHelperAttributeDataKey))
112+
{
113+
var descriptionInfo = data[TagHelperAttributeDataKey].ToObject<AttributeDescriptionInfo>();
114+
return descriptionInfo;
115+
}
116+
117+
return AttributeDescriptionInfo.Default;
118+
}
119+
120+
public static AttributeCompletionDescription GetAttributeDescriptionInfo(this CompletionItem completion)
121+
{
122+
if (completion is null)
123+
{
124+
throw new ArgumentNullException(nameof(completion));
125+
}
126+
127+
if (completion.Data is JObject data && data.ContainsKey(AttributeCompletionDataKey))
128+
{
129+
var descriptionInfo = data[AttributeCompletionDataKey].ToObject<AttributeCompletionDescription>();
130+
return descriptionInfo;
131+
}
132+
133+
return null;
134+
}
135+
}
136+
}

0 commit comments

Comments
 (0)