ILSpy icon indicating copy to clipboard operation
ILSpy copied to clipboard

Feature Request: Add support for extern aliases

Open siegfriedpammer opened this issue 3 years ago • 10 comments

Discussed in https://github.com/icsharpcode/ILSpy/discussions/2441

Originally posted by aBaechtold June 24, 2021 Hi,

I was recently reviewing an assembly that relies on assembly aliases (see also extern alias (C# Reference)) to access types in assemblies having the same fully qualified name but of different version. I noticed that ILSpy displays the types of the different versions to look exactly the same i.e. couldn't tell that they were different while they were. Clicking each of them with the mouse pointer navigated to the correct version, so that is good.

I wondered whether this could be an improvement and before submitting an issue wanted to ask if others think similarly. I did not find an issue or discussion that seems to cover this topic already, hence the new discussion. It's nothing critical as using assembly aliases is not a common thing I guess. It's also not showing something incorrectly, it's just ambiguity in the UI.

Details:

ILSpy version 7.1.0.6543 .NET version 4.8.4300.0

ILSpy disassembly:

private void _GenerateListOfConfigModels()
	{
		List<VConfigInfo> list = new List<VConfigInfo>
		{
			new VConfigInfo
			{
				VersionString = new VConfig().ExpectedConfigVersion,
				ConfigType = typeof(VConfig)   //<=Here...
			},
			new VConfigInfo
			{
				VersionString = new VConfig().ExpectedConfigVersion,
				ConfigType = typeof(VConfig)  //<=and here
			}
		};
		...
	}

Actual code:

...
extern alias v1;
extern alias v2;
...
using VConfig_v1               = v1::VConfig;
using VConfig_v2               = v2::VConfig;
...
private void _GenerateList() 
   {
      List<VConfigInfo> list = new List<VConfigInfo>
          {
               new VConfigInfo {VersionString = new VConfig_v1().ExpectedConfigVersion, ConfigType = typeof(VConfig_v1)},
               new VConfigInfo {VersionString = new VConfig_v2().ExpectedConfigVersion, ConfigType = typeof(VConfig_v2)}
                ...
          };
     ...
    }

siegfriedpammer avatar Jun 24 '21 14:06 siegfriedpammer

Thank you for the suggestion! Currently there is no support for extern aliases in ILSpy's decompiler engine, although the type system and syntax tree have some kind of support for this. Would you happen to know whether the fact that some assemblies have an extern alias is somehow manifested in the compiled assembly/metadata?

If not, ILSpy would have to detect whether there are types in different assemblies that have the exact same full type name. Adding full support for extern aliases does seem like a fair amount of work. Not sure, when we will be able to add this.

Of course, after an implementation has been specified, this could be contributed by anyone.

siegfriedpammer avatar Jun 24 '21 14:06 siegfriedpammer

Hi Siegfried, Sorry, I missed your question. Unfortunately I don't know if that aspect is reflected in the assemblies meta data somehow. I'd need to do some research. I'll try to follow up on that.

aBaechtold avatar Nov 04 '21 12:11 aBaechtold

I did a bit of testing and it looks like the exact alias is not retained in the assembly (meta data). There will be just multiple assembly references (AssemblyRef) that are the same despite the version part and the code will reference the corresponding parent. In such situations, what one could do is to just generate some clever alias (whatever clever means in that context). An alias in IL is present by means of 'as' in the AssemblyRef (see ECMA-335).

ildasm does something like that. Here's an example: Note: There are two different assemblies with a type SomeClass.SomeClass that each implement a different GetText method. image image

Here is what ILSpy shows (ILSpy version 7.2.0.6651-preview1, .NET version 4.8.4360.0): Note: Needed to load the dependencies manually as the automation failed. image image

Is there some way I can share my test console application (for which the above screenshots were taken) ?

aBaechtold avatar Nov 10 '21 21:11 aBaechtold

Is there some way I can share my test console application (for which the above screenshots were taken) ?

You can just attach the file to an issue comment or please send it to [email protected]. Thanks!

siegfriedpammer avatar Nov 10 '21 21:11 siegfriedpammer

After some trial an error to provide you the files (both as comment attachments or via email - Gmail declined all attachments) figured out that I should more carefully read the error message when uploading data to the comment. The issue was that I used 7Z or TAR archives which are not supported, but ZIP is. Thus here we go with the ZIP file :-) ExampleConsoleApp.zip

aBaechtold avatar Nov 11 '21 16:11 aBaechtold

I could try to provide a suggestion (code changes) from my end, but might take a while...

aBaechtold avatar Nov 11 '21 16:11 aBaechtold

A quick list of TODOs (from the top of my head):

  • [ ] ReflectionDisassembler: check if there are name collisions in the list of references, and generate aliases of the form assembly.name_N where N is a counter >= 2 as needed, also make sure to use these aliases when printing member references.
  • [ ] type system: MetadataModule might need extensions to support extern aliases
  • [ ] the IntroduceUsingDeclarations transform will have to emit extern alias directives and apply them in the decompiled code

siegfriedpammer avatar Nov 11 '21 17:11 siegfriedpammer

I could try to provide a suggestion (code changes) from my end, but might take a while...

If you want to implement this feature, let me know... I can help you, if you have any questions. Thanks!

siegfriedpammer avatar Nov 13 '21 12:11 siegfriedpammer

If you don't mind me being slow, then sure, I'd like to help if I can. As far as I can judge this is rather an exotic edge case not commonly found and the existing behavior is not broken, it's just not optimal, so a quick implementation might not be required.

So far I cloned the repository and was able to compile the solution. I will need to setup local code formatting to be as you outlined (tabs).

I was a bit overwhelmed by the existing code and looked in the Wiki if there are any guidelines or design concept descriptions, but have not exactly found something like that. I take it that I could use your TODO list above as a pointer into the code.

aBaechtold avatar Nov 15 '21 21:11 aBaechtold

I take it that I could use your TODO list above as a pointer into the code.

Yes, sorry for the non-existing documentation. If you have any questions or get stuck somewhere, please feel free to ask.

siegfriedpammer avatar Nov 15 '21 22:11 siegfriedpammer