Skip to content
Open
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
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceRoot}/src/IlViewer.WebApi/bin/Debug/netcoreapp1.0/IlViewer.WebApi.dll",
"program": "${workspaceRoot}/src/IlViewer.WebApi/bin/Debug/net6.0/ilViewer.WebApi.dll",
"args": [],
"cwd": "${workspaceRoot}",
"stopAtEntry": false,
Expand Down
17 changes: 11 additions & 6 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
{
"version": "0.1.0",
"version": "2.0.0",
"command": "dotnet",
"isShellCommand": true,
"args": [],
"tasks": [
{
"taskName": "build",
"label": "build",
"type": "shell",
"command": "dotnet",
"args": [
"${workspaceRoot}/src/IlViewer.WebApi/project.json"
"build",
"${workspaceRoot}/src/IlViewer.WebApi"
],
"isBuildCommand": true,
"problemMatcher": "$msCompile"
"problemMatcher": "$msCompile",
"group": {
"_id": "build",
"isDefault": false
}
}
]
}
4 changes: 0 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ Simply open a .cs file which you'd like to inspect, right-click and select `Insp
More features coming soon.


## Requirements

Currently only works on .NET Core apps using project.json. Support for .csproj is coming very soon.

## Reporting Issues

As this is an early version there will likely be issues. Please feel free to raise any issues you run into in the [issues section](https://github.com/JosephWoodward/VSCodeILViewer/issues).
Expand Down
4 changes: 0 additions & 4 deletions global.json

This file was deleted.

4 changes: 1 addition & 3 deletions src/IlViewer.Core/CSharpLanguage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CSharp.RuntimeBinder;
using Binder = Microsoft.CSharp.RuntimeBinder.Binder;

namespace IlViewer.Core
{
Expand All @@ -22,9 +23,6 @@ public class CSharpLanguage
MetadataReference.CreateFromFile(typeof(ValueTuple<>).GetTypeInfo().Assembly.Location)
};


private readonly IReadOnlyDictionary<string, string> _features;

public CSharpLanguage()
{

Expand Down
11 changes: 0 additions & 11 deletions src/IlViewer.Core/ExampleClass.cs

This file was deleted.

17 changes: 0 additions & 17 deletions src/IlViewer.Core/ILDecompiler.cs

This file was deleted.

133 changes: 59 additions & 74 deletions src/IlViewer.Core/IlGeneration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
using System.Linq;
using IlViewer.Core.ResultOutput;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.Extensions.Logging;
using Mono.Cecil;
using Mono.Cecil.Cil;
Expand All @@ -13,20 +15,64 @@ namespace IlViewer.Core
{
public static class IlGeneration
{
public static InspectionResult ExtractIl(string projectJsonPath, string classFilename)
public static InspectionResult ExtractIl(string projectPath, string classFileName)
{
if (string.IsNullOrEmpty(projectJsonPath))
throw new ArgumentNullException(nameof(projectJsonPath));
if (string.IsNullOrEmpty(projectPath))
{
throw new ArgumentNullException(nameof(projectPath));
}

if (string.IsNullOrEmpty(classFileName))
{
throw new ArgumentNullException(nameof(classFileName));
}

if (string.IsNullOrEmpty(classFilename))
throw new ArgumentNullException(nameof(classFilename));
var d = new DirectoryInfo(projectPath);
var fileToCompile = d.EnumerateFiles("*.cs", SearchOption.AllDirectories)
.Select(a => a.FullName)
.FirstOrDefault(f => f.Contains(classFileName));
var dllFiles = d.EnumerateFiles("*.dll", SearchOption.AllDirectories)
.Select(f => f.FullName).ToArray();
var references = new List<PortableExecutableReference>();
foreach (var dllFile in dllFiles)
{
var newRef = MetadataReference.CreateFromFile(dllFile);
references.Add(newRef);
}

Compilation workspaceCompilation = WorkspaceManager.LoadWorkspace(projectJsonPath);
var assemblyPath = Path.GetDirectoryName(typeof(object).Assembly.Location);
references.Add(MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Private.CoreLib.dll")));
var code = File.ReadAllText(fileToCompile);
var tree = CSharpSyntaxTree.ParseText(code);
var compilation = CSharpCompilation.Create("new").AddSyntaxTrees(tree);
var usings = compilation.SyntaxTrees.Select(tree => tree.GetRoot().ChildNodes().OfType<UsingDirectiveSyntax>()).SelectMany(s => s).ToArray();
foreach (var u in usings)
{
try
{

references.Add(MetadataReference.CreateFromFile(Path.Combine(assemblyPath, u.Name.ToString() + ".dll")));
}
catch
{
// ToDo log not absent .dll for usings
}
}

//ToDo support global usings
var sysRef = MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.dll"));
references.Add(sysRef);
references.Add(MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.IO.dll")));
references.Add(MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Linq.dll")));
references.Add(MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Net.Http.dll")));
references.Add(MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Threading.dll")));
references.Add(MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Threading.Tasks.dll")));
var finalCompilation = compilation.AddReferences(references);

var inspectionResult = new InspectionResult();
using (var stream = new MemoryStream())
using (var assemblyStream = new MemoryStream())
{
var compilationResult = workspaceCompilation.Emit(stream);
var compilationResult = finalCompilation.Emit(assemblyStream);
if (!compilationResult.Success)
{
var errors = compilationResult.Diagnostics.Where(x => x.Severity == DiagnosticSeverity.Error).ToList();
Expand All @@ -36,90 +82,29 @@ public static InspectionResult ExtractIl(string projectJsonPath, string classFil
Console.WriteLine(error.ToString());
}

if (inspectionResult.HasErrors)
return inspectionResult;
if (inspectionResult.HasErrors) return inspectionResult;
}

stream.Seek(0, SeekOrigin.Begin);

//AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(stream);
PortableExecutableReference ref2 = MetadataReference.CreateFromStream(stream);

var syntaxTree2 = workspaceCompilation.SyntaxTrees.Where(x => x.FilePath.Contains(classFilename));
var trees = workspaceCompilation.SyntaxTrees.ToList();

var allTrees = trees.Where(x => x.FilePath.Contains(classFilename + ".cs")).ToList();
//TODO: optimise this

var syntaxTree = allTrees.FirstOrDefault(x => x.FilePath.Contains("\\" + classFilename + ".cs"));
if (syntaxTree == null)
syntaxTree = allTrees.FirstOrDefault(x => x.FilePath.Contains("/" + classFilename + ".cs"));

var sourceCode = syntaxTree.GetText().ToString();

var metadataReferences = workspaceCompilation.References.ToList();
var res3 = ref2.GetMetadata();
metadataReferences.Add(ref2);

InspectionResult finalResult = CompileInMemory(sourceCode, metadataReferences, classFilename, inspectionResult);
assemblyStream.Seek(0, SeekOrigin.Begin);
InspectionResult finalResult = new InspectionResult { IlResults = GenerateIlFromStream (assemblyStream, classFileName) };
return finalResult;
}
}

private static InspectionResult CompileInMemory(string sourceCode, IEnumerable<MetadataReference> metadataReferences, string classFilename, InspectionResult inspectionResult)
{
var sourceLanguage = new CSharpLanguage();
var syntaxTree = sourceLanguage.ParseText(sourceCode, SourceCodeKind.Regular);

var stream = new MemoryStream();
Compilation compilation = sourceLanguage
.CreateLibraryCompilation("ExampleAssembly", false)
.AddReferences(metadataReferences)
.AddReferences()
.AddSyntaxTrees(syntaxTree);

var emitResult = compilation.Emit(stream);
if (!emitResult.Success)
{
var errors = emitResult.Diagnostics.Where(x => x.Severity == DiagnosticSeverity.Error);
foreach (var error in errors)
{
inspectionResult.AddError(error.GetMessage());
Console.WriteLine(error.ToString());
}

if (inspectionResult.HasErrors)
return inspectionResult;
}

stream.Seek(0, SeekOrigin.Begin);

//var resultWriter = new StringWriter();
//var decompiler = new ILDecompiler();
//decompiler.Decompile(stream, resultWriter);

var ilResult = GenerateIlFromStream(stream, classFilename);
inspectionResult.IlResults = ilResult;

return inspectionResult;
}

private static IList<InstructionResult> GenerateIlFromStream(Stream stream, string typeFullName)
{
var assembly = AssemblyDefinition.ReadAssembly(stream);

Dictionary<string, Collection<Instruction>> result;
var result = new Dictionary<string, Collection<Instruction>>();
try
{
result = RoslynClass.GetiLInstructionsFromAssembly(assembly, typeFullName);
result = RoslynClass.GetiLInstructionsFromAssembly(assembly, typeFullName);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}


var output = new List<InstructionResult>();
foreach(var item in result)
{
Expand Down
23 changes: 23 additions & 0 deletions src/IlViewer.Core/IlViewer.Core.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<DebugType>portable</DebugType>
<AssemblyName>IlViewer.Core</AssemblyName>
<PackageId>IlViewer.Core</PackageId>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.4.0" />
<PackageReference Include="Microsoft.DotNet.ProjectModel" Version="1.0.0-rc3-003121" />
<PackageReference Include="Microsoft.DotNet.ProjectModel.Workspaces" Version="1.0.0-preview2-003121" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="7.0.0" />
<PackageReference Include="Mono.Cecil" Version="0.11.4" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="System.Reflection.Metadata" Version="7.0.0" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
</ItemGroup>

</Project>
21 changes: 0 additions & 21 deletions src/IlViewer.Core/IlViewer.Core.xproj

This file was deleted.

5 changes: 2 additions & 3 deletions src/IlViewer.Core/RoslynClass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public static Dictionary<string, Collection<Instruction>> GetiLInstructionsFromA
var ilInstructions = new Dictionary<string, Collection<Instruction>>();
var typeDefinitions = assembly.MainModule.GetTypes().ToList();

TypeDefinition typeDefinition = typeDefinitions.FirstOrDefault(x => x.Name == typeName) ?? typeDefinitions.FirstOrDefault(x => x.Name.Contains(typeName) && x.HasGenericParameters);
var typeDefinition = typeDefinitions.FirstOrDefault(x => x.Name == typeName) ?? typeDefinitions.FirstOrDefault(x => x.Name.Contains(typeName) && x.HasGenericParameters);
if (typeDefinition != null)
{
foreach (var method in typeDefinition.Methods)
Expand All @@ -39,8 +39,7 @@ public static Dictionary<string, Collection<Instruction>> GetiLInstructionsFromA
}
else
{
ModuleDefinition module = assembly.MainModule;

var module = assembly.MainModule;
var ilProcessor = module?.EntryPoint?.Body?.GetILProcessor();
if (ilProcessor != null)
{
Expand Down
29 changes: 0 additions & 29 deletions src/IlViewer.Core/WorkspaceManager.cs

This file was deleted.

Loading