Skip to content

Commit

Permalink
Merge pull request #52 from naminodarie/feature/partial_not_embedded
Browse files Browse the repository at this point in the history
NotEmbeddingSourceAttribute targets all
  • Loading branch information
kzrnm authored Mar 15, 2021
2 parents d280384 + 8a48a8f commit 2d15517
Show file tree
Hide file tree
Showing 3 changed files with 262 additions and 11 deletions.
8 changes: 1 addition & 7 deletions Source/SourceExpander.Embedder/CompileTimeTypeMaker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,7 @@ public static class CompileTimeTypeMaker
namespace SourceExpander
{
[AttributeUsage(
AttributeTargets.Class |
AttributeTargets.Struct |
AttributeTargets.Enum |
AttributeTargets.Interface |
AttributeTargets.Delegate,
Inherited = false, AllowMultiple = false)]
[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
[System.Diagnostics.Conditional(""COMPILE_TIME_ONLY"")]
[NotEmbeddingSource]
internal sealed class NotEmbeddingSourceAttribute : Attribute
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,28 @@ internal class TypeFindAndUnusedUsingRemover : CSharpSyntaxRewriter
private readonly ImmutableHashSet<string>.Builder rootUsingsBuilder = ImmutableHashSet.CreateBuilder<string>();
public ImmutableHashSet<string> RootUsings() => rootUsingsBuilder.ToImmutable();

private readonly INamedTypeSymbol? NotEmbeddingSourceAttributeSymbol;

public TypeFindAndUnusedUsingRemover(SemanticModel model, CancellationToken cancellationToken)
{
this.model = model;
NotEmbeddingSourceAttributeSymbol = model.Compilation.GetTypeByMetadataName("SourceExpander.NotEmbeddingSourceAttribute");
this.cancellationToken = cancellationToken;
diagnostics = model.GetDiagnostics(cancellationToken: cancellationToken);
}

private bool HasNotEmbeddingSourceAttribute(SyntaxNode? node)
{
if (node is MemberDeclarationSyntax declarationSyntax)

foreach (var attributeListSyntax in declarationSyntax.AttributeLists)
foreach (var attribute in attributeListSyntax.Attributes)
if (model.GetTypeInfo(attribute).Type is ITypeSymbol atSymbol
&& SymbolEqualityComparer.Default.Equals(NotEmbeddingSourceAttributeSymbol, atSymbol))
return true;
return false;
}

/// <summary>
/// Find Type or skip
/// </summary>
Expand All @@ -35,10 +50,6 @@ private bool FindDeclaredType(MemberDeclarationSyntax node)
if (model.GetDeclaredSymbol(node, cancellationToken) is not ITypeSymbol symbol)
return false;

if (symbol.GetAttributes()
.Any(at => at.AttributeClass?.ToString() == "SourceExpander.NotEmbeddingSourceAttribute"))
return false;

var typeName = symbol?.ToDisplayString();
if (typeName is not null)
{
Expand All @@ -50,6 +61,8 @@ private bool FindDeclaredType(MemberDeclarationSyntax node)

public override SyntaxNode? Visit(SyntaxNode? node)
{
if (HasNotEmbeddingSourceAttribute(node))
return null;
if (node is BaseTypeDeclarationSyntax typeDeclaration)
{
if (!FindDeclaredType(typeDeclaration))
Expand Down
244 changes: 244 additions & 0 deletions Test/SourceExpander.Embedder.Test/Generate/SkipTypeTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,250 @@ public enum NumType
.Should()
.BeEquivalentTo(embeddedFiles);
}

[Fact]
public async Task Partial()
{
var embeddedFiles = ImmutableArray.Create(
new SourceFileInfo
(
"TestProject>Program.cs",
new string[] { "Program" },
ImmutableArray.Create("using System;"),
ImmutableArray.Create<string>(),
@"partial class Program{static void Main()=>Console.WriteLine(1);}"
));
const string embeddedSourceCode = "[{\"CodeBody\":\"partial class Program{static void Main()=>Console.WriteLine(1);}\",\"Dependencies\":[],\"FileName\":\"TestProject>Program.cs\",\"TypeNames\":[\"Program\"],\"Usings\":[\"using System;\"]}]";

var test = new Test
{
TestState =
{
AdditionalFiles =
{
enableMinifyJson,
},
Sources = {
(
"/home/source/Program.cs",
@"using System;
partial class Program
{
static void Main() => Console.WriteLine(1);
}
[SourceExpander.NotEmbeddingSource]
partial class Program
{
static void M() => Console.WriteLine(2);
}
"
),
},
ExpectedDiagnostics =
{
DiagnosticResult.CompilerError("CS0234").WithSpan("/home/source/Program.cs", 6, 17, 6, 35).WithArguments("NotEmbeddingSource", "SourceExpander"),
DiagnosticResult.CompilerError("CS0234").WithSpan("/home/source/Program.cs", 6, 17, 6, 35).WithArguments("NotEmbeddingSourceAttribute", "SourceExpander"),
},
GeneratedSources =
{
(typeof(EmbedderGenerator), "EmbeddedSourceCode.Metadata.cs", @$"using System.Reflection;
[assembly: AssemblyMetadataAttribute(""SourceExpander.EmbedderVersion"",""{EmbedderVersion}"")]
[assembly: AssemblyMetadataAttribute(""SourceExpander.EmbeddedLanguageVersion"",""{EmbeddedLanguageVersion}"")]
[assembly: AssemblyMetadataAttribute(""SourceExpander.EmbeddedSourceCode"",{embeddedSourceCode.ToLiteral()})]
"),
}
}
};
await test.RunAsync();
Newtonsoft.Json.JsonConvert.DeserializeObject<SourceFileInfo[]>(embeddedSourceCode)
.Should()
.BeEquivalentTo(embeddedFiles);
System.Text.Json.JsonSerializer.Deserialize<SourceFileInfo[]>(embeddedSourceCode)
.Should()
.BeEquivalentTo(embeddedFiles);
}

[Fact]
public async Task Field()
{
var embeddedFiles = ImmutableArray.Create(
new SourceFileInfo
(
"TestProject>Program.cs",
new string[] { "Program" },
ImmutableArray.Create("using System;"),
ImmutableArray.Create<string>(),
@"class Program{static void Main()=>Console.WriteLine(1);}"
));
const string embeddedSourceCode = "[{\"CodeBody\":\"class Program{static void Main()=>Console.WriteLine(1);}\",\"Dependencies\":[],\"FileName\":\"TestProject>Program.cs\",\"TypeNames\":[\"Program\"],\"Usings\":[\"using System;\"]}]";

var test = new Test
{
TestState =
{
AdditionalFiles =
{
enableMinifyJson,
},
Sources = {
(
"/home/source/Program.cs",
@"using System;
class Program
{
static void Main() => Console.WriteLine(1);
[SourceExpander.NotEmbeddingSource]
static int num = 2;
}
"
),
},
ExpectedDiagnostics =
{
DiagnosticResult.CompilerError("CS0234").WithSpan("/home/source/Program.cs", 5, 21, 5, 39).WithArguments("NotEmbeddingSource", "SourceExpander"),
DiagnosticResult.CompilerError("CS0234").WithSpan("/home/source/Program.cs", 5, 21, 5, 39).WithArguments("NotEmbeddingSourceAttribute", "SourceExpander"),
},
GeneratedSources =
{
(typeof(EmbedderGenerator), "EmbeddedSourceCode.Metadata.cs", @$"using System.Reflection;
[assembly: AssemblyMetadataAttribute(""SourceExpander.EmbedderVersion"",""{EmbedderVersion}"")]
[assembly: AssemblyMetadataAttribute(""SourceExpander.EmbeddedLanguageVersion"",""{EmbeddedLanguageVersion}"")]
[assembly: AssemblyMetadataAttribute(""SourceExpander.EmbeddedSourceCode"",{embeddedSourceCode.ToLiteral()})]
"),
}
}
};
await test.RunAsync();
Newtonsoft.Json.JsonConvert.DeserializeObject<SourceFileInfo[]>(embeddedSourceCode)
.Should()
.BeEquivalentTo(embeddedFiles);
System.Text.Json.JsonSerializer.Deserialize<SourceFileInfo[]>(embeddedSourceCode)
.Should()
.BeEquivalentTo(embeddedFiles);
}


[Fact]
public async Task Property()
{
var embeddedFiles = ImmutableArray.Create(
new SourceFileInfo
(
"TestProject>Program.cs",
new string[] { "Program" },
ImmutableArray.Create("using System;"),
ImmutableArray.Create<string>(),
@"class Program{static void Main()=>Console.WriteLine(1);}"
));
const string embeddedSourceCode = "[{\"CodeBody\":\"class Program{static void Main()=>Console.WriteLine(1);}\",\"Dependencies\":[],\"FileName\":\"TestProject>Program.cs\",\"TypeNames\":[\"Program\"],\"Usings\":[\"using System;\"]}]";

var test = new Test
{
TestState =
{
AdditionalFiles =
{
enableMinifyJson,
},
Sources = {
(
"/home/source/Program.cs",
@"using System;
class Program
{
static void Main() => Console.WriteLine(1);
[SourceExpander.NotEmbeddingSource]
static int num => 2;
[SourceExpander.NotEmbeddingSource]
static string text { get; set; }
}
"
),
},
ExpectedDiagnostics =
{
DiagnosticResult.CompilerError("CS0234").WithSpan("/home/source/Program.cs", 5, 21, 5, 39).WithArguments("NotEmbeddingSource", "SourceExpander"),
DiagnosticResult.CompilerError("CS0234").WithSpan("/home/source/Program.cs", 5, 21, 5, 39).WithArguments("NotEmbeddingSourceAttribute", "SourceExpander"),
DiagnosticResult.CompilerError("CS0234").WithSpan("/home/source/Program.cs", 7, 21, 7, 39).WithArguments("NotEmbeddingSource", "SourceExpander"),
DiagnosticResult.CompilerError("CS0234").WithSpan("/home/source/Program.cs", 7, 21, 7, 39).WithArguments("NotEmbeddingSourceAttribute", "SourceExpander"),
},
GeneratedSources =
{
(typeof(EmbedderGenerator), "EmbeddedSourceCode.Metadata.cs", @$"using System.Reflection;
[assembly: AssemblyMetadataAttribute(""SourceExpander.EmbedderVersion"",""{EmbedderVersion}"")]
[assembly: AssemblyMetadataAttribute(""SourceExpander.EmbeddedLanguageVersion"",""{EmbeddedLanguageVersion}"")]
[assembly: AssemblyMetadataAttribute(""SourceExpander.EmbeddedSourceCode"",{embeddedSourceCode.ToLiteral()})]
"),
}
}
};
await test.RunAsync();
Newtonsoft.Json.JsonConvert.DeserializeObject<SourceFileInfo[]>(embeddedSourceCode)
.Should()
.BeEquivalentTo(embeddedFiles);
System.Text.Json.JsonSerializer.Deserialize<SourceFileInfo[]>(embeddedSourceCode)
.Should()
.BeEquivalentTo(embeddedFiles);
}

[Fact]
public async Task Method()
{
var embeddedFiles = ImmutableArray.Create(
new SourceFileInfo
(
"TestProject>Program.cs",
new string[] { "Program" },
ImmutableArray.Create("using System;"),
ImmutableArray.Create<string>(),
@"class Program{static void Main()=>Console.WriteLine(1);}"
));
const string embeddedSourceCode = "[{\"CodeBody\":\"class Program{static void Main()=>Console.WriteLine(1);}\",\"Dependencies\":[],\"FileName\":\"TestProject>Program.cs\",\"TypeNames\":[\"Program\"],\"Usings\":[\"using System;\"]}]";

var test = new Test
{
TestState =
{
AdditionalFiles =
{
enableMinifyJson,
},
Sources = {
(
"/home/source/Program.cs",
@"using System;
class Program
{
static void Main() => Console.WriteLine(1);
[SourceExpander.NotEmbeddingSource]
static void M() => Console.WriteLine(2);
}
"
),
},
ExpectedDiagnostics =
{
DiagnosticResult.CompilerError("CS0234").WithSpan("/home/source/Program.cs", 5, 21, 5, 39).WithArguments("NotEmbeddingSource", "SourceExpander"),
DiagnosticResult.CompilerError("CS0234").WithSpan("/home/source/Program.cs", 5, 21, 5, 39).WithArguments("NotEmbeddingSourceAttribute", "SourceExpander"),
},
GeneratedSources =
{
(typeof(EmbedderGenerator), "EmbeddedSourceCode.Metadata.cs", @$"using System.Reflection;
[assembly: AssemblyMetadataAttribute(""SourceExpander.EmbedderVersion"",""{EmbedderVersion}"")]
[assembly: AssemblyMetadataAttribute(""SourceExpander.EmbeddedLanguageVersion"",""{EmbeddedLanguageVersion}"")]
[assembly: AssemblyMetadataAttribute(""SourceExpander.EmbeddedSourceCode"",{embeddedSourceCode.ToLiteral()})]
"),
}
}
};
await test.RunAsync();
Newtonsoft.Json.JsonConvert.DeserializeObject<SourceFileInfo[]>(embeddedSourceCode)
.Should()
.BeEquivalentTo(embeddedFiles);
System.Text.Json.JsonSerializer.Deserialize<SourceFileInfo[]>(embeddedSourceCode)
.Should()
.BeEquivalentTo(embeddedFiles);
}
}
}

0 comments on commit 2d15517

Please sign in to comment.