Skip to content

Commit

Permalink
[wasm] Fix JSExport on structs, records and expression bodied methos (#…
Browse files Browse the repository at this point in the history
…74763)

- Fix generating qualified name for JSExport on structs, record classes and record structs.
- Fix using expression bodied methods for JSExport.
- Add unit test using all these variants with and without namespace and nested types.
- Rewrite concatenating method name.
  • Loading branch information
maraf authored Aug 31, 2022
1 parent c30cfbb commit 7922d61
Show file tree
Hide file tree
Showing 5 changed files with 425 additions and 11 deletions.
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,11 @@ namespace Microsoft.Interop.JavaScript
{
internal sealed class JSSignatureContext : IEquatable<JSSignatureContext>
{
private static SymbolDisplayFormat s_typeNameFormat { get; } = new SymbolDisplayFormat(
globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Omitted,
typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypes
);

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 +125,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 +144,17 @@ public static JSSignatureContext Create(
};
}

private static string GetFullyQualifiedMethodName(StubEnvironment env, IMethodSymbol method)
{
// Mono style nested class name format.
string typeName = method.ContainingType.ToDisplayString(s_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)
{
ImmutableArray<IUseSiteAttributeParser> useSiteAttributeParsers = ImmutableArray.Create<IUseSiteAttributeParser>(new JSMarshalAsAttributeParser(env.Compilation));
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

0 comments on commit 7922d61

Please sign in to comment.