Matching Roslyn SourceMemberMethodSymbol with a 'RetargetingMethodSymbol' - vb.net

I've been putting some 'find references' code together using Roslyn to search for all method declarations that match a particular signature, and then locate all uses of those methods elsewhere.
It's working in 99% of cases, but I've got an issue where an InvocationExpressionSyntax.Symbol is an instance of Microsoft.CodeAnalysis.VisualBasic.Symbols.Retargeting.RetargetingMethodSymbol instead of a regular Microsoft.CodeAnalysis.VisualBasic.Symbols.SourceMemberMethodSymbol. As a consequence this particular call to a target method isn't found (using ISymbol.Equals, which uses reference equality). RetargetingMethodSymbol has an UnderlyingMethod property whose value is the target method I'd expect, but this type is internal and that property isn't exposed.
What is a RetargetingMethodSymbol, and how can I see if it corresponds to a MethodBlockSyntax.Symbol?

What is a RetargetingMethodSymbol?
Consider a method M(object o) that is defined in project A, which targets .NET 2.0.
Project B targets .NET 4.0, and has a reference to A. In the context of project B, M will be wrapped in a RetargetingMethodSymbol, since the object that it refers to in this context isn't the same one that it refers to in the context of A.
How can I see if it corresponds to a MethodBlockSyntax.Symbol?
I don't know what you mean by MethodBlockSyntax.Symbol, but the VS IDE code uses SymbolFinder.FindSourceDefinitionAsync() to find the "original" symbol in cases like this (and also if A was written in C# and B in VB or vice versa).

Related

ILMerge fails to merge: The assembly 'xxx' was not merged in correctly

Problem
Using ILMerge I am trying to merge three assemblies: A, B and C. It fails with the following errormessage. I really need to help to solve this.
"ILMerge.Merge: The assembly 'B' was not merged in correctly. It is still listed as an external reference in the target assembly."
Assembly A does not reference the other two. B references A. C references A and B.
Command line: ilmerge /v2 /target:library /out:test.dll a.dll b.dll c.dll
What I have tried
Use /closed argument. Does not make any difference.
Different versions of ILMerge, I get the same error with both version 3.0.21.3911 and 2.14.1208.
Merge A and B first and the merge in C with the A+B merge. This does not produce any error message but the resulting file is broken. It does not run and when I run in through .NET Obfuscator it complains about it.
Some background
The project is larger than the three assemblies but I have managed to reduce the problem down to these. If I dont include assembly C and only merge A and B the problem goes away.
In the previous version I did not have this problem. Between these two versions there is only non functional changes, like renames (not assembly or namespaces, only classes, methods etc) and reordering of access modifiers (static internal->internal static)
From the documentation
A common problem is that after merging some assemblies, you get an error message
stating that an input assembly was not merged in correctly because it is still listed as an
external reference in the merged assembly. The most common cause of this problem is
that one of the input assemblies, B, has an external reference to the incorrectly merged
assembly, A, and also an external reference to another assembly, C, that itself has an
external reference to A. Suppose the reference to C is to a method that takes an argument
whose type is defined in A. Then the type signature of the method call to the method in C
still refers to the type from A even in the merged assembly. After all, ILMerge cannot go
and modify the assembly C so that it now depends on the type as it is defined in the
output assembly after it has been merged!
The solution is to use the closed option (Section 2.6) to have ILMerge compute the
transitive closure of the input assemblies to prevent this kind of “dangling reference”. In
the example, that would result in all three assemblies A, B, and C, being merged. There is
no way to merge just A and B without there still being an external reference to A.

Distinguish two functions with the same name

I want to use multiple external CMake files in my project. Unfortunately two different files use the same CMake function name foo. I don't want to modify these external files.
Is there a way to call one specific function or will CMake error out? Would it help if one of the functions has a named parameter, i.e., foo(a b c …) and foo(DESTINATION a b c …)?
New function's definition replaces the previous one with the same name. So access to the previous function is lost.
If different functions (but with the same name) are used in different subprojects, you may try to build one subproject as ExternalProject, so function's collision wouldn't occure.
In CMake any function definitions contains the only piece of information for the caller - minimal number of parameters which should be passed to the function. By using this information it is impossible to resolve function's overloading, if it would be implemented.

ABAP type pool: program with type code TYPP but with name longer than five characters

We are writing a tool in Java that parses and transforms ABAP code. We therefore have no intention to write new ABAP code but our tool has to handle all of ABAP, even obsolete statements. Furthermore, I'm not an ABAP expert.
ABAP programs can use type groups, introduced by key word TYPE-POOL. Names of type groups have a maximal length of five (internally eight, if you count the prefix "% C"), their type code is TYPP. In the past, relying on these assumptions worked well for us.
Recently, we see ABAP programs with type code TYPP but with name longer than 5, e.g., 'OIA===========================P'. Furthermore, for each of those, there is another, empty object with same name but type code INCL. These new objects are referenced only if a regular type group is, too.
These new objects may be internal ones and irrelevant for us - I haven't seen any reference to them in the ABAP Keyword Documentation. On the other hand, they are confusing us because we see them.
Can someone explain to me the meaning of these objects and point me to some documentation?
Edit: Here examples from an EHP7 for SAP ERP 6.0 system
An example object. Entries in D010INC look fine:
The same object now using type pool mrm. Where do the additional includes come from?
These objects are introduced through inclusions, extensions and switched objects. To read along:
Check type pool MRM, type mrm_idoc_data_ers - that type contains a statement to include rmrm_idoc_data_ers_sbo. A similar include statement pulls rmrm_upd_arseg_nfm into mrm_upd_arseg. That explains the last two lines. Your parser should have caught that.
RMRM_IDOC_DATA_ERS_SBO contains an enhancement point named RMRM_IDOC_DATA_ERS_SBO_02 that belongs to an enhancement spot ES_RMRM_IDOC_DATA_ERS_SBO. Similarly, RMRM_UPD_ARSEG_NFM contains an enhancement point RMRM_UPD_ARSEG_NFM_01 that belongs to the enhancement spot ES_RMRM_UPD_ARSEG_NFM.
For ES_RMRM_IDOC_DATA_ERS_SBO, an enhancement implementation named ISAUTO_MRM_RMRM_IDOC_DATA_ERS exists. For ES_RMRM_UPD_ARSEG_NFM, an implementation named /NFM/MM_RMRM_UPD_ARSEG_NFM exists. That explains the references ending with =E
The implementation ISAUTO_MRM_RMRM_IDOC_DATA_ERS is located in the package ISAUTO_MRM. The implementation /NFM/MM_RMRM_UPD_ARSEG_NFM is located in the package /NFM/MM. That explains the references ending with =P. Obviously, these references are not generated for every package:
The package ISAUTO_MRM is controlled by the switch AM_ERS, the package /NFM/MM is controlled by the switch /NFM/MM. That explains the references ending in =S.
Ultimately, these references can be used to determine which programs need to be re-generated when the state of a switch is changed.

Which is the correct form for a C++-CLI copy constructor?

I have some code like this:
MyClass::MyClass(MyClass^ objToCopyFrom);
Which is producing an error:
'type' : ref class does not have a user-defined copy constructor
When I look up the error, it suggests my code should look like this:
MyClass::MyClass(MyClass% objToCopyFrom);
My question is therefore, which version is correct or are they both correct?
Only your second version is correct:
MyClass::MyClass(MyClass% objToCopyFrom);
or its variant:
MyClass::MyClass(const MyClass% objToCopyFrom);
MyClass% is a so-called Tracking Reference which is the conceptual equivalence of a reference in native C++, only for CLR types.
While copy constructors in native C++ can have a number of different signatures, what they all have in common is that the other object that's being copied is passed in as a reference. C++/CLI stays close to that principle, but uses its own type of object references, a tracking reference.

Empty Structures compile in VB 10+

This is at least a documentation error, if not a bug.
In VB.NET prior to .NET 4.0 (i.e. VB.NET 7 through 9) an empty Structure declaration fails at compile-time with
error BC30281: Structure 'MySimpleEmpty' must contain at least one instance member variable or Event declaration.
E.g. The following two structures compile successfully in VB10, and not prior:
Structure MySimpleEmpty
End Structure
Public Structure AnotherEmpty
Public Const StillEmpty As Boolean = True
End Structure
I note the documentation for the Error BC30281 stops at VB9, but the documentation for the Structure statement still has the datamemberdeclarations as required even as of VB11 (.NET 4.5 VS2012).
These two Structures compile in VB11 (VS2012) as well. (Thanks John Woo.)
Is there some blog entry or documentation confirming this is an intended change or a bug in VB10 and later?
Microsoft have marked this as a fixed bug, without actually stating what was fixed.
The VB11 (VS2012) documentation now says the datamemberdeclarations are optional in the grammar, but in the Parts table it says "Required. Zero or more..."!
I guess that's a fix... The VB10 (VS2010) documentation hasn't been changed.