Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wasm] Fix JSExport on struct and records #74763

Merged
merged 11 commits into from
Aug 31, 2022
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ private static bool ShouldVisitNode(SyntaxNode syntaxNode)
// Verify the method has no generic types or defined implementation
// and is marked static and partial.
if (methodSyntax.TypeParameterList is not null
|| methodSyntax.Body is null
|| (methodSyntax.Body is null && methodSyntax.ExpressionBody is null)
|| !methodSyntax.Modifiers.Any(SyntaxKind.StaticKeyword)
|| methodSyntax.Modifiers.Any(SyntaxKind.PartialKeyword))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;

using Microsoft.CodeAnalysis;
Expand All @@ -16,6 +18,15 @@ namespace Microsoft.Interop.JavaScript
{
internal sealed class JSSignatureContext : IEquatable<JSSignatureContext>
{
private static SymbolDisplayFormat typeNameFormat { get; } = new SymbolDisplayFormat(
maraf marked this conversation as resolved.
Show resolved Hide resolved
globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Omitted,
typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypes,
genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters,
miscellaneousOptions:
SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers |
SymbolDisplayMiscellaneousOptions.UseSpecialTypes
maraf marked this conversation as resolved.
Show resolved Hide resolved
);

internal static readonly string GeneratorName = typeof(JSImportGenerator).Assembly.GetName().Name;

internal static readonly string GeneratorVersion = typeof(JSImportGenerator).Assembly.GetName().Version.ToString();
Expand Down Expand Up @@ -118,14 +129,8 @@ public static JSSignatureContext Create(
};
int typesHash = Math.Abs((int)hash);



var fullName = $"{method.ContainingType.ToDisplayString()}.{method.Name}";
string qualifiedName;
var ns = string.Join(".", method.ContainingType.ToDisplayParts().Where(p => p.Kind == SymbolDisplayPartKind.NamespaceName).Select(x => x.ToString()).ToArray());
var cn = string.Join("/", method.ContainingType.ToDisplayParts().Where(p => p.Kind == SymbolDisplayPartKind.ClassName).Select(x => x.ToString()).ToArray());
var qclasses = method.ContainingType.ContainingNamespace == null ? ns : ns + "." + cn;
qualifiedName = $"[{env.Compilation.AssemblyName}]{qclasses}:{method.Name}";
string qualifiedName = GetFullyQualifiedMethodName(env, method);

return new JSSignatureContext()
{
Expand All @@ -143,6 +148,17 @@ public static JSSignatureContext Create(
};
}

private static string GetFullyQualifiedMethodName(StubEnvironment env, IMethodSymbol method)
{
// Mono style nested class name format.
string typeName = method.ContainingType.ToDisplayString(typeNameFormat).Replace(".", "/");

if (!method.ContainingType.ContainingNamespace.IsGlobalNamespace)
typeName = $"{method.ContainingType.ContainingNamespace.ToDisplayString()}.{typeName}";

return $"[{env.Compilation.AssemblyName}]{typeName}:{method.Name}";
}

private static (ImmutableArray<TypePositionInfo>, IMarshallingGeneratorFactory) GenerateTypeInformation(IMethodSymbol method, GeneratorDiagnostics diagnostics, StubEnvironment env)
{
var jsMarshallingAttributeParser = new JSMarshallingAttributeInfoParser(env.Compilation, diagnostics, method);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1199,7 +1199,62 @@ public void JsExportString(string value)
public void JsExportStringNoNs()
{
var actual = JavaScriptTestHelper.invoke2_String("test", nameof(JavaScriptTestHelperNoNamespace.EchoString));
Assert.Equal("test!", actual);
Assert.Equal("test51", actual);
}

[Fact]
public void JsExportStructClassRecords()
{
var actual = JavaScriptTestHelper.invokeStructClassRecords("test");
Assert.Equal(48, actual.Length);
Assert.Equal("test11", actual[0]);
Assert.Equal("test12", actual[1]);
Assert.Equal("test13", actual[2]);
Assert.Equal("test14", actual[3]);
Assert.Equal("test15", actual[4]);
Assert.Equal("test16", actual[5]);
Assert.Equal("test17", actual[6]);
Assert.Equal("test18", actual[7]);
Assert.Equal("test19", actual[8]);
Assert.Equal("test21", actual[9]);
Assert.Equal("test22", actual[10]);
Assert.Equal("test23", actual[11]);
Assert.Equal("test24", actual[12]);
Assert.Equal("test25", actual[13]);
Assert.Equal("test31", actual[14]);
Assert.Equal("test32", actual[15]);
Assert.Equal("test33", actual[16]);
Assert.Equal("test34", actual[17]);
Assert.Equal("test35", actual[18]);
Assert.Equal("test41", actual[19]);
Assert.Equal("test42", actual[20]);
Assert.Equal("test43", actual[21]);
Assert.Equal("test44", actual[22]);
Assert.Equal("test45", actual[23]);
Assert.Equal("test51", actual[24]);
Assert.Equal("test52", actual[25]);
Assert.Equal("test53", actual[26]);
Assert.Equal("test54", actual[27]);
Assert.Equal("test55", actual[28]);
Assert.Equal("test56", actual[29]);
Assert.Equal("test57", actual[30]);
Assert.Equal("test58", actual[31]);
Assert.Equal("test59", actual[32]);
Assert.Equal("test61", actual[33]);
Assert.Equal("test62", actual[34]);
Assert.Equal("test63", actual[35]);
Assert.Equal("test64", actual[36]);
Assert.Equal("test65", actual[37]);
Assert.Equal("test71", actual[38]);
Assert.Equal("test72", actual[39]);
Assert.Equal("test73", actual[40]);
Assert.Equal("test74", actual[41]);
Assert.Equal("test75", actual[42]);
Assert.Equal("test81", actual[43]);
Assert.Equal("test82", actual[44]);
Assert.Equal("test83", actual[45]);
Assert.Equal("test84", actual[46]);
Assert.Equal("test85", actual[47]);
}

[Fact]
Expand Down
Loading