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

Invalid Renaming in Project Level Workspace #46

Merged
merged 9 commits into from
Mar 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 60 additions & 1 deletion .github/workflows/dotnet-compilation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ permissions:
pull-requests: write

jobs:
build:
build-on-solution:
strategy:
fail-fast: false
matrix:
Expand Down Expand Up @@ -73,3 +73,62 @@ jobs:
! git diff-index --quiet HEAD

git --no-pager diff --ignore-all-space --ignore-blank-lines

build-on-project:
strategy:
fail-fast: false
matrix:
plugins:
- "--shuffle-declarations"
- "--rename-symbols --rename-namespaces --rename-classes --rename-properties --rename-fields --rename-methods --rename-variables"
- "--disable-console-output --disable-symbols=T:System.Console,T:System.Diagnostics.Debug"
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4

- name: Setup .NET tools
uses: actions/setup-dotnet@v4
with:
dotnet-version: "8.0.x"

- name: Restore NuGet dependencies
run: |
dotnet restore ./src/Plana.sln

- name: Phase.1 -- Build Original Source
run: |
dotnet build ./src/Plana.sln --no-restore --configuration=Release /p:WarningLevel=0

mkdir -p ./src/Plana.CLI/bin/Releases/net8.0/plugins
cp ./src/Plana.Composition.Extensions/bin/Release/net8.0/Plana.Composition.Extensions.dll ./src/Plana.CLI/bin/Releases/net8.0/plugins
cp ./src/Plana.Composition.DisableConsoleOutput/bin/Release/net8.0/Plana.Composition.DisableConsoleOutput.dll ./src/Plana.CLI/bin/Releases/net8.0/plugins
cp ./src/Plana.Composition.RenameSymbols/bin/Release/net8.0/Plana.Composition.RenameSymbols.dll ./src/Plana.CLI/bin/Releases/net8.0/plugins
cp ./src/Plana.Composition.ShuffleDeclarations/bin/Release/net8.0/Plana.Composition.ShuffleDeclarations.dll ./src/Plana.CLI/bin/Releases/net8.0/plugins

dotnet ./src/Plana.CLI/bin/Release/net8.0/Plana.CLI.dll obfuscate --log-level verbose --workspace ./src/Plana.CLI/Plana.CLI.csproj --plugins ./src/Plana.CLI/bin/Releases/net8.0/plugins --write ${{ matrix.plugins }}

- name: Phase.2 -- Re-Build Obfuscated Source
run: |
! git diff-index --quiet HEAD

dotnet build ./src/Plana.sln --no-restore --configuration=Release /p:WarningLevel=0

mkdir -p ./src/Plana.CLI/bin/Releases/net8.0/plugins
cp ./src/Plana.Composition.Extensions/bin/Release/net8.0/Plana.Composition.Extensions.dll ./src/Plana.CLI/bin/Releases/net8.0/plugins
cp ./src/Plana.Composition.DisableConsoleOutput/bin/Release/net8.0/Plana.Composition.DisableConsoleOutput.dll ./src/Plana.CLI/bin/Releases/net8.0/plugins
cp ./src/Plana.Composition.RenameSymbols/bin/Release/net8.0/Plana.Composition.RenameSymbols.dll ./src/Plana.CLI/bin/Releases/net8.0/plugins
cp ./src/Plana.Composition.ShuffleDeclarations/bin/Release/net8.0/Plana.Composition.ShuffleDeclarations.dll ./src/Plana.CLI/bin/Releases/net8.0/plugins

git add -A
git stash save

- name: Phase.3 -- Re-Test with obfuscated source
run: |
# --log-level=verbose cannot be used because the target class has been obfuscated and renamed.
# It will be possible to control it by adding the PublicAPI attribute.
dotnet ./src/Plana.CLI/bin/Release/net8.0/Plana.CLI.dll obfuscate --workspace ./src/Plana.CLI/Plana.CLI.csproj --plugins ./src/Plana.CLI/bin/Releases/net8.0/plugins --write ${{ matrix.plugins }}

! git diff-index --quiet HEAD

git --no-pager diff --ignore-all-space --ignore-blank-lines
7 changes: 6 additions & 1 deletion src/Plana.CLI/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,16 @@
"commandLineArgs": "obfuscate --workspace ./Plana.sln --output \"../dist\" --log-level verbose --plugins ./Plana.CLI/bin/Debug/net8.0/plugins --rename-symbols --retrieve-args",
"workingDirectory": "../"
},
"Plana.CLI - Obfuscate": {
"Plana.CLI - Obfuscate (Solution)": {
"commandName": "Project",
"commandLineArgs": "obfuscate --workspace ./Plana.sln --output \"../dist\" --log-level verbose --plugins ./Plana.CLI/bin/Debug/net8.0/plugins --rename-symbols --rename-namespaces --rename-classes --rename-properties --rename-fields --rename-methods --rename-variables",
"workingDirectory": "../"
},
"Plana.CLI - Obfuscate (Project)": {
"commandName": "Project",
"commandLineArgs": "obfuscate --workspace ./Plana.CLI/Plana.CLI.csproj --output \"../dist\" --log-level verbose --plugins ./Plana.CLI/bin/Debug/net8.0/plugins --rename-symbols --rename-namespaces --rename-classes --rename-properties --rename-fields --rename-methods --rename-variables",
"workingDirectory": "../"
},
"Plana.CLI - Obfuscate (--rename-namespaces)": {
"commandName": "Project",
"commandLineArgs": "obfuscate --workspace ./Plana.sln --output \"../dist\" --log-level verbose --plugins ./Plana.CLI/bin/Debug/net8.0/plugins --rename-symbols --rename-namespaces",
Expand Down
50 changes: 48 additions & 2 deletions src/Plana.Composition.Extensions/ISymbolExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@

using Microsoft.CodeAnalysis;

using Plana.Composition.Abstractions.Analysis;

namespace Plana.Composition.Extensions;

#pragma warning disable CS8619
#pragma warning disable CS8622 // Nullability of reference types in type of parameter doesn't match the target delegate (possibly because of nullability attributes).

// ReSharper disable once InconsistentNaming
public static class ISymbolExtensions
{
#pragma warning disable CS8619
private static readonly string[] Autogenerated = ["<auto-generated", "<autogenerated"];

public static ISymbol? GetInterfaceSymbol(this ISymbol symbol)
{
if (symbol.Kind != SymbolKind.Method && symbol.Kind != SymbolKind.Property && symbol.Kind != SymbolKind.Event)
Expand All @@ -31,7 +37,47 @@ public static class ISymbolExtensions

return implementations.FirstOrDefault(w => w.Implementation?.Equals(symbol, SymbolEqualityComparer.Default) == true).Interface;
}
#pragma warning restore CS8619

public static bool IsAllDeclarationIsInWorkspace(this ISymbol symbol, ISolution solution)
{
var sources = symbol.OriginalDefinition.Locations.Where(w => !IsDocumentIsAutoGeneratedAsync(w.SourceTree))
.Select(w => w.SourceTree?.FilePath)
.Where(w => w != null)
.Select(Path.GetFullPath)
.ToList();

var targets = solution.Projects.SelectMany(w => w.Documents)
.Select(w => Path.GetFullPath(w.Path))
.ToList();

return sources.All(w => targets.Contains(w));
}

public static bool IsAnyDeclarationIsNotInWorkspace(this ISymbol symbol, ISolution solution)
{
return !IsAllDeclarationIsInWorkspace(symbol, solution);
}

private static bool IsDocumentIsAutoGeneratedAsync(SyntaxTree? tree)
{
if (tree == null)
return false;

var node = tree.GetRoot();
if (node is { HasLeadingTrivia: true })
{
var leading = node.GetLeadingTrivia();
foreach (var trivia in leading)
{
var text = trivia.ToFullString();
if (Autogenerated.Any(w => text.Contains(w)))
return true;
}
}

return false;
}


/*
// Licensed to the .NET Foundation under one or more agreements.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public bool Equals(ISymbol? x, ISymbol? y)
case IPropertySymbol:
case IMethodSymbol:
case IFieldSymbol:
case IParameterSymbol:
return x.ToDisplayString(SymbolDisplayFormat) == y.ToDisplayString(SymbolDisplayFormat);
}

Expand All @@ -68,6 +69,19 @@ public int GetHashCode(ISymbol obj)
case IMethodSymbol:
case IFieldSymbol:
return obj.ToDisplayString(SymbolDisplayFormat).GetHashCode();

case IParameterSymbol parameter:
{
if (parameter.ContainingSymbol is IMethodSymbol m)
{
var a = (m.IsExtensionMethod ? m.ReducedFrom ?? m.OriginalDefinition : m).ToDisplayString(SymbolDisplayFormat);
var b = obj.ToDisplayString(SymbolDisplayFormat);

return HashCode.Combine(a, b);
}

break;
}
}

return SymbolEqualityComparer.Default.GetHashCode(obj);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
using Plana.Composition.Extensions;
using Plana.Testing;

using CSharpSyntaxNodeExtensions = Plana.Composition.Extensions.CSharpSyntaxNodeExtensions;

namespace Plana.Composition.RenameSymbols.Tests;

public partial class RenameSymbolsPluginTest
Expand All @@ -26,15 +28,14 @@ public async Task RenameClasses_Attribute()
var reference = await container.GetSourceByTypeAsync(typeof(RenameSymbolsPlugin));

// PlanaPluginAttribute -> _0x35add3ac
const string identifier = "_0x35add3ac";

var declaration = await implementation.GetFirstSyntax<ClassDeclarationSyntax>((@class, sm) =>
{
var symbol = sm.GetDeclaredSymbol(@class);
return symbol?.BaseType != null && symbol.BaseType.Equals(typeof(Attribute).ToSymbol(sm), SymbolEqualityComparer.Default);
});

Assert.Equal($"{identifier}Attribute", declaration.Identifier.ToFullString());
var identifier = declaration.Identifier.ToIdentifier();
Assert.True(declaration.Identifier.ToHaveHexadecimalLikeString(suffix: "Attribute"));

var attribute = await reference.GetFirstSyntax<AttributeSyntax>((w, sm) =>
{
Expand All @@ -46,7 +47,9 @@ public async Task RenameClasses_Attribute()

return true;
});
Assert.Equal(identifier, attribute.Name.ToFullString());

Assert.True(attribute.Name.ToHaveHexadecimalLikeString());
Assert.Equal(identifier[.. ^"Attribute".Length], attribute.Name.ToIdentifier());
}

[Fact]
Expand All @@ -60,16 +63,15 @@ public async Task RenameClasses_Class()
var extends = await container.GetSourceByPathAsync("Plana.Testing/PlanaContainer.cs");

// PlanaContainer<T> -> _0xdb120989
const string identifier = "_0xdb120989";

var a = await implementation.GetFirstSyntax<ClassDeclarationSyntax>();
Assert.Equal(identifier, a.Identifier.ToString());
var identifier = a.Identifier.ToIdentifier();
Assert.True(a.Identifier.ToHaveHexadecimalLikeString());

var b = await reference.GetFirstSyntax<ObjectCreationExpressionSyntax>();
Assert.Equal(identifier, ((b.Type as GenericNameSyntax)?.Identifier).ToString());
Assert.Equal(identifier, ((b.Type as GenericNameSyntax)?.Identifier).ToIdentifier());

var c = await extends.GetFirstSyntax<ClassDeclarationSyntax>();
Assert.Equal(identifier, ((c.BaseList?.Types[0].Type as GenericNameSyntax)?.Identifier).ToString());
Assert.Equal(identifier, ((c.BaseList?.Types[0].Type as GenericNameSyntax)?.Identifier).ToIdentifier());
}

[Fact]
Expand All @@ -81,13 +83,12 @@ public async Task RenameClasses_Constructor()
var reference = await container.GetSourceByPathAsync("Plana.Composition.Extensions/PlanaPluginOption.cs");

// PlanaPluginOption -> _0xb93c4da5
const string identifier = "_0xb93c4da5";

var @class = await reference.GetFirstSyntax<ClassDeclarationSyntax>();
Assert.Equal(identifier, @class.Identifier.ToFullString());
var identifier = @class.Identifier.ToIdentifier();
Assert.True(@class.Identifier.ToHaveHexadecimalLikeString());

var constructor = await reference.GetFirstSyntax<ConstructorDeclarationSyntax>();
Assert.Equal(identifier, constructor.Identifier.ToFullString());
Assert.Equal(identifier, constructor.Identifier.ToIdentifier());
}

[Fact]
Expand All @@ -99,20 +100,18 @@ public async Task RenameClasses_HasTypeParameters()
var reference = await container.GetSourceByPathAsync("Plana.Composition.RenameSymbols.Tests/RenameSymbolsPluginTest_Classes.cs");

// PlanaContainer -> _0xdb120989
const string identifier1 = "_0xdb120989";

var implementation = await container.GetSourceByPathAsync("Plana.Testing/PlanaContainer{T}.cs");
var a = await implementation.GetFirstSyntax<ClassDeclarationSyntax>();
var identifier1 = a.Identifier.ToIdentifier();

Assert.Equal(identifier1, a.Identifier.ToString());
Assert.True(a.Identifier.ToHaveHexadecimalLikeString());

// RenameSymbolsPlugin -> _0xe2407d3d
const string identifier2 = "_0xe2407d3d";

var parameter = await container.GetSourceByTypeAsync(typeof(RenameSymbolsPlugin));
var b = await parameter.GetFirstSyntax<ClassDeclarationSyntax>();
var identifier2 = b.Identifier.ToIdentifier();

Assert.Equal(identifier2, b.Identifier.ToString());
Assert.True(b.Identifier.ToHaveHexadecimalLikeString());

var invocation = await reference.GetFirstSyntax<ObjectCreationExpressionSyntax>(w => w.Type.IsKind(SyntaxKind.GenericName));
var generics = invocation.Type as GenericNameSyntax;
Expand All @@ -133,16 +132,15 @@ public async Task RenameClasses_Interface()
var reference = await container.GetSourceByTypeAsync(typeof(CSharpSymbolsWalker));

// IPlanaSecureRandom -> _0x32fad750
const string identifier = "_0x32fad750";

var a = await declaration.GetFirstSyntax<InterfaceDeclarationSyntax>();
Assert.Equal(identifier, a.Identifier.ToString());
var identifier = a.Identifier.ToIdentifier();
Assert.True(a.Identifier.ToHaveHexadecimalLikeString());

var b = await implementation.GetFirstSyntax<ClassDeclarationSyntax>();
Assert.Equal(identifier, b.BaseList?.Types[0].Type.ToString());

var c = await reference.GetFirstSyntax<ClassDeclarationSyntax>();
Assert.Equal(identifier, c.ParameterList?.Parameters[1].Type?.ToString());
Assert.Equal(identifier, c.ParameterList?.Parameters[2].Type?.ToString());
}

[Fact]
Expand All @@ -155,11 +153,9 @@ public async Task RenameClasses_Record()
var reference = await container.GetSourceByTypeAsync(typeof(CSharpSyntaxNodeExtensions));

// AnnotationComment -> _0xd9d2dd2a
const string identifier = "_0xd9d2dd2a";

var a = await declaration.GetFirstSyntax<RecordDeclarationSyntax>();
Assert.Equal(identifier, a.Identifier.ToString());

var identifier = a.Identifier.ToIdentifier();
Assert.True(a.Identifier.ToHaveHexadecimalLikeString());

var b = await reference.GetFirstSyntax<MemberAccessExpressionSyntax>(w =>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,9 @@ public async Task RenameFields_ExternalReference()
var reference = await container.GetSourceByPathAsync("Plana.Composition.RenameSymbols.Tests/RenameSymbolsPluginTest.cs");

// IsEnableClassNameRenaming -> _0x935f5b12
const string identifier = "_0x935f5b12";

var declaration = await implementation.GetFirstSyntax<FieldDeclarationSyntax>(w => w.HasModifier(SyntaxKind.InternalKeyword));
Assert.Equal(identifier, declaration.Declaration.Variables[0].Identifier.ToString());
var identifier = declaration.Declaration.Variables[0].Identifier.ToIdentifier();
Assert.True(declaration.Declaration.Variables[0].Identifier.ToHaveHexadecimalLikeString());

var m = await reference.GetFirstSyntax<MemberAccessExpressionSyntax>((w, sm) =>
{
Expand Down Expand Up @@ -57,10 +56,9 @@ public async Task RenameFields_InternalReference()
var implementation = await container.GetSourceByTypeAsync(typeof(MeaningEqualitySymbolComparator));

// SymbolDisplayFormat -> _0xcb375677
const string identifier = "_0xcb375677";

var declaration = await implementation.GetFirstSyntax<FieldDeclarationSyntax>(w => w.HasModifiers(SyntaxKind.PrivateKeyword, SyntaxKind.StaticKeyword, SyntaxKind.ReadOnlyKeyword));
Assert.Equal(identifier, declaration.Declaration.Variables[0].Identifier.ToString());
var identifier = declaration.Declaration.Variables[0].Identifier.ToIdentifier();
Assert.True(declaration.Declaration.Variables[0].Identifier.ToHaveHexadecimalLikeString());

var reference = await implementation.GetFirstSyntax<IdentifierNameSyntax>((w, sm) =>
{
Expand Down
Loading
Loading