mirror of https://github.com/icsharpcode/ILSpy.git
20 changed files with 282 additions and 66 deletions
@ -0,0 +1,51 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using System.Threading.Tasks; |
||||||
|
using NUnit.Framework; |
||||||
|
using ICSharpCode.ILSpy.Analyzers; |
||||||
|
using ICSharpCode.ILSpy.Analyzers.Builtin; |
||||||
|
using ICSharpCode.Decompiler.TypeSystem; |
||||||
|
using System.Windows; |
||||||
|
|
||||||
|
namespace ICSharpCode.ILSpy.Tests.Analyzers |
||||||
|
{ |
||||||
|
[TestFixture, Parallelizable(ParallelScope.All)] |
||||||
|
public class MethodUsesAnalyzerTests |
||||||
|
{ |
||||||
|
AssemblyList assemblyList; |
||||||
|
CSharpLanguage language; |
||||||
|
LoadedAssembly testAssembly; |
||||||
|
ICompilation testAssemblyTypeSystem; |
||||||
|
ITypeDefinition typeDefinition; |
||||||
|
|
||||||
|
[OneTimeSetUp] |
||||||
|
public void Setup() |
||||||
|
{ |
||||||
|
new Application(); |
||||||
|
Options.DecompilerSettingsPanel.TestSetup(new Decompiler.DecompilerSettings()); |
||||||
|
assemblyList = new AssemblyList("Test"); |
||||||
|
testAssembly = assemblyList.OpenAssembly(typeof(MethodUsesAnalyzerTests).Assembly.Location); |
||||||
|
assemblyList.OpenAssembly(typeof(void).Assembly.Location); |
||||||
|
testAssemblyTypeSystem = testAssembly.GetTypeSystemOrNull(); |
||||||
|
language = new CSharpLanguage(); |
||||||
|
typeDefinition = testAssemblyTypeSystem.FindType(typeof(TestCases.Main.MainAssembly)).GetDefinition(); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void MainAssemblyUsesSystemStringEmpty() |
||||||
|
{ |
||||||
|
var context = new AnalyzerContext { AssemblyList = assemblyList, Language = language }; |
||||||
|
IMethod symbol = typeDefinition.Methods.First(m => m.Name == "UsesSystemStringEmpty"); |
||||||
|
|
||||||
|
var results = new MethodUsesAnalyzer().Analyze(symbol, context).ToList(); |
||||||
|
|
||||||
|
Assert.IsTrue(results.Count == 1); |
||||||
|
var field = results.Single() as IField; |
||||||
|
Assert.IsNotNull(field); |
||||||
|
Assert.IsFalse(field.MetadataToken.IsNil); |
||||||
|
Assert.AreEqual(field.FullName, "System.String.Empty"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using System.Threading.Tasks; |
||||||
|
|
||||||
|
namespace ICSharpCode.ILSpy.Tests.Analyzers.TestCases.Main |
||||||
|
{ |
||||||
|
class MainAssembly |
||||||
|
{ |
||||||
|
public string UsesSystemStringEmpty() |
||||||
|
{ |
||||||
|
return string.Empty; |
||||||
|
} |
||||||
|
|
||||||
|
public int UsesInt32() |
||||||
|
{ |
||||||
|
return int.Parse("1234"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,66 @@ |
|||||||
|
// Copyright (c) 2020 Siegfried Pammer
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||||
|
// software and associated documentation files (the "Software"), to deal in the Software
|
||||||
|
// without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||||
|
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||||
|
// to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all copies or
|
||||||
|
// substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||||
|
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using System.Threading.Tasks; |
||||||
|
using System.Windows; |
||||||
|
using ICSharpCode.Decompiler.TypeSystem; |
||||||
|
using ICSharpCode.Decompiler.TypeSystem.Implementation; |
||||||
|
using ICSharpCode.ILSpy.Analyzers; |
||||||
|
using ICSharpCode.ILSpy.Analyzers.Builtin; |
||||||
|
using NUnit.Framework; |
||||||
|
|
||||||
|
namespace ICSharpCode.ILSpy.Tests.Analyzers |
||||||
|
{ |
||||||
|
[TestFixture, Parallelizable(ParallelScope.All)] |
||||||
|
public class TypeUsedByAnalyzerTests |
||||||
|
{ |
||||||
|
AssemblyList assemblyList; |
||||||
|
CSharpLanguage language; |
||||||
|
LoadedAssembly testAssembly; |
||||||
|
ICompilation testAssemblyTypeSystem; |
||||||
|
|
||||||
|
[OneTimeSetUp] |
||||||
|
public void Setup() |
||||||
|
{ |
||||||
|
new Application(); |
||||||
|
Options.DecompilerSettingsPanel.TestSetup(new Decompiler.DecompilerSettings()); |
||||||
|
assemblyList = new AssemblyList("Test"); |
||||||
|
testAssembly = assemblyList.OpenAssembly(typeof(MethodUsesAnalyzerTests).Assembly.Location); |
||||||
|
testAssemblyTypeSystem = new SimpleCompilation(testAssembly.GetPEFileOrNull(), assemblyList.OpenAssembly(typeof(void).Assembly.Location).GetPEFileOrNull()); |
||||||
|
language = new CSharpLanguage(); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void SystemInt32UsedByMainAssembly() |
||||||
|
{ |
||||||
|
var context = new AnalyzerContext { AssemblyList = assemblyList, Language = language }; |
||||||
|
var symbol = testAssemblyTypeSystem.FindType(typeof(int)).GetDefinition(); |
||||||
|
|
||||||
|
var results = new TypeUsedByAnalyzer().Analyze(symbol, context).ToList(); |
||||||
|
|
||||||
|
Assert.IsNotEmpty(results); |
||||||
|
var method = results.OfType<IMethod>().SingleOrDefault(m => m.FullName == "ICSharpCode.ILSpy.Tests.Analyzers.TestCases.Main.MainAssembly.UsesInt32"); |
||||||
|
Assert.IsNotNull(method); |
||||||
|
Assert.IsFalse(method.MetadataToken.IsNil); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,70 @@ |
|||||||
|
// Copyright (c) 2018 Siegfried Pammer
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||||
|
// software and associated documentation files (the "Software"), to deal in the Software
|
||||||
|
// without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||||
|
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||||
|
// to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all copies or
|
||||||
|
// substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||||
|
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Concurrent; |
||||||
|
using System.Reflection.Metadata; |
||||||
|
using System.Threading; |
||||||
|
using ICSharpCode.Decompiler.Metadata; |
||||||
|
using ICSharpCode.Decompiler.TypeSystem; |
||||||
|
|
||||||
|
namespace ICSharpCode.ILSpy.Analyzers |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Provides additional context for analyzers.
|
||||||
|
/// </summary>
|
||||||
|
public class AnalyzerContext |
||||||
|
{ |
||||||
|
public AssemblyList AssemblyList { get; internal set; } |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// CancellationToken. Currently Analyzers do not support cancellation from the UI, but it should be checked nonetheless.
|
||||||
|
/// </summary>
|
||||||
|
public CancellationToken CancellationToken { get; internal set; } |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Currently used language.
|
||||||
|
/// </summary>
|
||||||
|
public Language Language { get; internal set; } |
||||||
|
|
||||||
|
public MethodBodyBlock GetMethodBody(IMethod method) |
||||||
|
{ |
||||||
|
if (!method.HasBody || method.MetadataToken.IsNil) |
||||||
|
return null; |
||||||
|
var module = method.ParentModule.PEFile; |
||||||
|
var md = module.Metadata.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken); |
||||||
|
try { |
||||||
|
return module.Reader.GetMethodBody(md.RelativeVirtualAddress); |
||||||
|
} catch (BadImageFormatException) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public AnalyzerScope GetScopeOf(IEntity entity) |
||||||
|
{ |
||||||
|
return new AnalyzerScope(AssemblyList, entity); |
||||||
|
} |
||||||
|
|
||||||
|
readonly ConcurrentDictionary<PEFile, DecompilerTypeSystem> typeSystemCache = new ConcurrentDictionary<PEFile, DecompilerTypeSystem>(); |
||||||
|
|
||||||
|
public DecompilerTypeSystem GetOrCreateTypeSystem(PEFile module) |
||||||
|
{ |
||||||
|
return typeSystemCache.GetOrAdd(module, m => new DecompilerTypeSystem(m, m.GetAssemblyResolver())); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue