Skip to content

C#: Extract the metadata handle#590

Merged
hvitved merged 7 commits into
github:nextfrom
calumgrant:cs/metadata-handles2
Jan 3, 2019
Merged

C#: Extract the metadata handle#590
hvitved merged 7 commits into
github:nextfrom
calumgrant:cs/metadata-handles2

Conversation

@calumgrant
Copy link
Copy Markdown
Contributor

@calumgrant calumgrant commented Nov 30, 2018

This is a fix for the rather unsatisfactory getLabel() solution we use when matching C# and CIL types/methods etc. Instead, populate a metadata_handle/3 extensional which records the metadata handle (a unique integer in an assembly) for each extracted entity in both the CIL and C# extractors.

The pair (assembly, handle) can be used to uniquely and efficiently identify the corresponding C#/CIL method.

The dbstats are needed to ensure the suitable join order (handle,assembly).

Note that #29460 on Semmle/code is needed to bump the db and submodule.

@calumgrant calumgrant requested a review from a team as a code owner November 30, 2018 13:56
@calumgrant calumgrant added the C# label Nov 30, 2018
@pavgust
Copy link
Copy Markdown
Contributor

pavgust commented Nov 30, 2018

This pull request introduces 1 alert when merging 74945bd into 044dcfb - view on LGTM.com

new alerts:

  • 1 for Missed 'readonly' opportunity

Comment posted by LGTM.com

Copy link
Copy Markdown
Contributor

@hvitved hvitved left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A very nice addition, and this should certainly make data flow analysis faster/more accurate.

internal static Tuple locations_default(ISourceLocation label, IFile file, int startLine, int startCol, int endLine, int endCol) =>
new Tuple("locations_default", label, file, startLine, startCol, endLine, endCol);

internal static Tuple metadata_handle(IEntity entity, Assembly assembly, int handleValue) =>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about changing the type of handleValue to Handle, and then call handleValue.GetHashCode() here rather than at all the call sites?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't do that because I didn't want to put population logic into the Tuples methods.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK.

@callable | @value_or_ref_type | @void_type;

#keyset[entity, location]
metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is #keyset[location, handle] also valid?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, because there are 1-2 entities for each (location,handle) - the CIL one and the C# one.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense.

}

query predicate tooManyMatchingHandles(MetadataEntity e) {
count(MetadataEntity e2 | e.matchesHandle(e2))>2
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can use strictcount

count(MetadataEntity e2 | e.matchesHandle(e2))>2
}

query predicate missingCil(Element e) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change type to MetadataEntity and remove infix cast below

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then I would need an infix cast in a different place - I think on the fromLibrary.

get
{
var propertyInfo = symbol.GetType().GetProperty("Handle",
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetProperty);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:-(

}
}

return new Handle(); // A nil handle
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change the return type to Handle? and use null here instead? Then the check !handle.IsNil above will be handle.HasValue, which is more standard.

{
return (MethodDefinitionHandle)value;
}
else if(value is TypeDefinitionHandle)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

space after if, and below

{
var value = propertyInfo.GetValue(symbol);

if (value is MethodDefinitionHandle)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use pattern matching to avoid cast, and same in the other cases below.

hvitved
hvitved previously approved these changes Dec 20, 2018
@hvitved hvitved merged commit 5452000 into github:next Jan 3, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants