Skip to content

Commit

Permalink
Added support for custom type declaration sources.
Browse files Browse the repository at this point in the history
  • Loading branch information
IEvangelist committed Apr 7, 2022
1 parent 9a443c6 commit 972658f
Show file tree
Hide file tree
Showing 15 changed files with 252 additions and 133 deletions.
7 changes: 5 additions & 2 deletions src/Blazor.LocalStorage/ILocalStorageService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@

namespace Microsoft.JSInterop;

/// <summary></summary>
[JSAutoInterop(
TypeName = "Storage",
Implementation = "window.localStorage",
HostingModel = BlazorHostingModel.Server,
OnlyGeneratePureJS = true,
Url = "https://developer.mozilla.org/docs/Web/API/Window/localStorage")]
Url = "https://developer.mozilla.org/docs/Web/API/Window/localStorage",
TypeDeclarationSources = new[]
{
"https://raw.githubusercontent.com/microsoft/TypeScript/main/lib/lib.dom.d.ts"
})]
public partial interface ILocalStorageService
{
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// Copyright (c) David Pine. All rights reserved.
// Licensed under the MIT License.



namespace Blazor.SourceGenerators.Extensions;

static class AttributeSyntaxExtensions
Expand Down Expand Up @@ -49,6 +47,10 @@ internal static GeneratorOptions GetGeneratorOptions(
{
PureJavaScriptOverrides = ParseArray(arg.Expression.ToString())
},
nameof(options.TypeDeclarationSources) => options with
{
TypeDeclarationSources = ParseArray(arg.Expression.ToString())
},

_ => options
};
Expand Down
44 changes: 23 additions & 21 deletions src/Blazor.SourceGenerators/JavaScriptInteropGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ namespace Blazor.SourceGenerators;
[Generator]
internal sealed partial class JavaScriptInteropGenerator : ISourceGenerator
{
private readonly LibDomParser _libDomParser = new();
private readonly HashSet<(string FileName, string SourceCode)> _sourceCodeToAdd = new()
{
(nameof(RecordCompat).ToGeneratedFileName(), RecordCompat),
Expand Down Expand Up @@ -63,27 +62,30 @@ public void Execute(GeneratorExecutionContext context)
continue;
}

var result = _libDomParser.ParseTargetType(options.TypeName!);
if (result.Status == ParserResultStatus.SuccessfullyParsed &&
result.Value is not null)
foreach (var parser in options.Parsers)
{
var namespaceString =
(typeSymbol.ContainingNamespace.ToDisplayString(), classDeclaration.Parent) switch
{
(string { Length: > 0 } containingNamespace, _) => containingNamespace,
(_, BaseNamespaceDeclarationSyntax namespaceDeclaration) => namespaceDeclaration.Name.ToString(),
_ => null
};
var @interface =
options.Implementation.ToInterfaceName();
var implementation =
options.Implementation.ToImplementationName();

var topLevelObject = result.Value;
context.AddDependentTypesSource(topLevelObject)
.AddInterfaceSource(topLevelObject, @interface, options, namespaceString)
.AddImplementationSource(topLevelObject, implementation, options, namespaceString)
.AddDependencyInjectionExtensionsSource(topLevelObject, implementation, options);
var result = parser.ParseTargetType(options.TypeName!);
if (result.Status == ParserResultStatus.SuccessfullyParsed &&
result.Value is not null)
{
var namespaceString =
(typeSymbol.ContainingNamespace.ToDisplayString(), classDeclaration.Parent) switch
{
(string { Length: > 0 } containingNamespace, _) => containingNamespace,
(_, BaseNamespaceDeclarationSyntax namespaceDeclaration) => namespaceDeclaration.Name.ToString(),
_ => null
};
var @interface =
options.Implementation.ToInterfaceName();
var implementation =
options.Implementation.ToImplementationName();

var topLevelObject = result.Value;
context.AddDependentTypesSource(topLevelObject)
.AddInterfaceSource(topLevelObject, @interface, options, namespaceString)
.AddImplementationSource(topLevelObject, implementation, options, namespaceString)
.AddDependencyInjectionExtensionsSource(topLevelObject, implementation, options);
}
}
}
}
Expand Down
31 changes: 30 additions & 1 deletion src/Blazor.SourceGenerators/Options/GeneratorOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
/// <param name="Url">The optional URL to the corresponding API.</param>
/// <param name="GenericMethodDescriptors">The optional generic method descriptors value from the parsed <c>JSAutoGenericInteropAttribute.GenericMethodDescriptors</c>.</param>
/// <param name="PureJavaScriptOverrides">Overrides pure JavaScript calls. A custom impl must exist.</param>
/// <param name="TypeDeclarationSources">An optional array of TypeScript type declarations sources. Valid values are URLs or file paths.</param>
/// <param name="IsWebAssembly">
/// A value indicating whether to generate targeting WASM:
/// When <c>true</c>: Synchronous extensions are generated on the <c>IJSInProcessRuntime</c> type.
Expand All @@ -24,4 +25,32 @@ internal sealed record GeneratorOptions(
string? Url = null,
string[]? GenericMethodDescriptors = null,
string[]? PureJavaScriptOverrides = null,
bool IsWebAssembly = true);
string[]? TypeDeclarationSources = null,
bool IsWebAssembly = true)
{
ISet<TypeDeclarationParser>? _parsers;

/// <summary>
/// Get <see cref="GeneratorOptions"/> instance maps its
/// <see cref="TypeDeclarationSources"/> into a set of parsers.
/// When <see cref="TypeDeclarationSources"/> is null, or empty,
/// the default lib.dom.d.ts parser is used.
/// </summary>
internal ISet<TypeDeclarationParser> Parsers
{
get
{
_parsers ??= new HashSet<TypeDeclarationParser>();

foreach (var source in
TypeDeclarationSources?.Select(TypeDeclarationReader.Factory)
?.Select(reader => new TypeDeclarationParser(reader))
?? new[] { TypeDeclarationParser.Default })
{
_parsers.Add(source);
}

return _parsers;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Blazor.SourceGenerators.Parsers;

internal sealed partial class LibDomParser
internal sealed partial class TypeDeclarationParser
{
internal CSharpObject? ToObject(string typeScriptTypeDeclaration)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,17 @@

namespace Blazor.SourceGenerators.Parsers;

internal sealed partial class LibDomParser
internal sealed partial class TypeDeclarationParser
{
private readonly LibDomReader _reader = new();
static readonly Lazy<TypeDeclarationParser> s_defaultParser =
new(
valueFactory: () => new TypeDeclarationParser(TypeDeclarationReader.Default));

readonly TypeDeclarationReader _reader;

internal static TypeDeclarationParser Default => s_defaultParser.Value;

internal TypeDeclarationParser(TypeDeclarationReader reader) => _reader = reader;

public ParserResult<CSharpTopLevelObject> ParseTargetType(string typeName)
{
Expand Down
98 changes: 0 additions & 98 deletions src/Blazor.SourceGenerators/Readers/LibDomReader.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright (c) David Pine. All rights reserved.
// Licensed under the MIT License.

namespace Blazor.SourceGenerators.Readers;

internal sealed partial class TypeDeclarationReader
{
static readonly ConcurrentDictionary<string, TypeDeclarationReader> s_readerCache =
new(StringComparer.OrdinalIgnoreCase);

internal static TypeDeclarationReader Factory(string source)
{
var uri = new Uri(source);
var sourceKey = uri.IsFile ? uri.LocalPath : uri.OriginalString;

var reader =
s_readerCache.GetOrAdd(
sourceKey, _ => new TypeDeclarationReader(uri));

return reader;
}

internal static TypeDeclarationReader Default
{
get
{
var sourceKey = s_defaultTypeDeclarationSource.OriginalString;
var reader =
s_readerCache.GetOrAdd(
sourceKey, _ => new TypeDeclarationReader(s_defaultTypeDeclarationSource));

return reader;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright (c) David Pine. All rights reserved.
// Licensed under the MIT License.

namespace Blazor.SourceGenerators.Readers;

internal sealed partial class TypeDeclarationReader
{
string GetLocalFileText(string filePath) => File.ReadAllText(filePath);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) David Pine. All rights reserved.
// Licensed under the MIT License.

namespace Blazor.SourceGenerators.Readers;

internal sealed partial class TypeDeclarationReader
{
static readonly HttpClient s_httpClient = new();
static readonly Uri s_defaultTypeDeclarationSource =
new("https://raw.githubusercontent.com/microsoft/TypeScript/main/lib/lib.dom.d.ts");

string GetRemoteFileText(string url)
{
var typeDeclarationText =
s_httpClient.GetStringAsync(url)
.ConfigureAwait(false)
.GetAwaiter()
.GetResult();

return typeDeclarationText;
}
}
Loading

0 comments on commit 972658f

Please sign in to comment.