Skip to content

Add signature parser based on Roslyn doc comments#1197

Merged
sbomer merged 9 commits into
dotnet:masterfrom
sbomer:sigParser
May 27, 2020
Merged

Add signature parser based on Roslyn doc comments#1197
sbomer merged 9 commits into
dotnet:masterfrom
sbomer:sigParser

Conversation

@sbomer
Copy link
Copy Markdown
Member

@sbomer sbomer commented May 16, 2020

This adds a parser for the format described at https://github.com/dotnet/csharplang/blob/master/spec/documentation-comments.md#id-string-format, which we plan to use for UnconditionalSuppressMessageAttribute (#1147) and probably also DynamicDependencyAttribute.

It's adapted from Roslyn, with some changes to allow for resolving from metadata instead of sources. This doesn't support the legacy fxcop format, and it also doesn't allow some special cases that Roslyn has - see comments in the sources. The Roslyn implementation uses a visitor pattern, where symbols in their syntax tree implement accept methods. This seemed hard to adapt to our use case, and I don't think we need the full generality of this pattern, so this parser follows the same structure without truly using the visitor pattern.

@sbomer sbomer requested a review from marek-safar as a code owner May 16, 2020 04:47
// This includes '`n' for mangled generic types
builder.Append (typeReference.Name);

if (typeReference.HasGenericParameters || !typeReference.IsGenericInstance)
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 this condition correct?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I think so - unless I missed a case in cecil. Non-generics don't need more work, and uninstantiated generics are already mangled. I added a clarifying comment.

Comment thread src/linker/Linker/SignatureParser.cs Outdated
Comment thread src/linker/Linker/TypeReferenceExtensions.cs Outdated
Comment thread src/linker/Linker/SignatureParser.cs Outdated
sbomer added 3 commits May 18, 2020 15:59
- SignatureParser -> DocumentationSignatureParser
- GetSignaturePart extension moved to DocumentationSignatureParser
- Inverted a condition
- Added a clarifying comment about generics
To let it build on mono
sbomer added 2 commits May 18, 2020 21:33
And add comments clarifying their behavior
There were two issues:
- Nunit doesn't like assertions inside of a TestCaseSource method.
- On mono, the test infra failed to resolve the new assertion attributes
Comment thread src/linker/Linker/DocumentationSignatureGenerator.PartVisitor.cs
Comment thread src/linker/Linker/DocumentationSignatureGenerator.cs
Comment thread src/linker/Linker/DocumentationSignatureGenerator.cs Outdated
Comment thread src/linker/Linker/DocumentationSignatureParser.cs Outdated
Comment thread src/linker/Linker/DocumentationSignatureParser.cs Outdated
Comment thread src/linker/Linker/DocumentationSignatureParser.cs Outdated
Comment thread src/linker/Linker/DocumentationSignatureParser.cs Outdated
Comment thread test/Mono.Linker.Tests/Tests/DocumentationSignatureParserTests.cs Outdated
Copy link
Copy Markdown
Member

@vitek-karas vitek-karas left a comment

Choose a reason for hiding this comment

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

I think we should make the prefix optional (the T: prefix and similar). You mentioned that Roslyn also makes it optional effectively. It would make the format pretty straightforward for simple cases.

If Roslyn doesn't support the ID without the prefix, then I'm fine we also require it - as we need to use the same syntax as Roslyn.

Copy link
Copy Markdown
Member

@vitek-karas vitek-karas left a comment

Choose a reason for hiding this comment

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

I think we should make the prefix optional (the T: prefix and similar). You mentioned that Roslyn also makes it optional effectively. It would make the format pretty straightforward for simple cases.

If Roslyn doesn't support the ID without the prefix, then I'm fine we also require it - as we need to use the same syntax as Roslyn.

if (PeekNextChar (id, index) == '{') {
typeArguments = new List<string> ();
if (!ParseTypeArguments (id, ref index, typeParameterContext, typeArguments)) {
continue;
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.

Should we output a warning in places where the parsing fails?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ideally yes, but I'm not sure in this case. Roslyn doesn't raise a warning when this is malformed in SuppressMessage - it simply ignores it in that case. So I think linker should do the same in this case.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Agreed it would be nice. Currently the way it will be done is that the caller of the parser gets to decide what kind of warnings/errors to log - which unfortunately doesn't distinguish between syntax errors and resolution errors. I initially tried to separate those two cases, but ended up just following the Roslyn implementation.

sbomer added 2 commits May 26, 2020 18:21
- Allow parsing a signature without a member type prefix
- Allow parsing a member without a type name
- Allow matching multiple member kinds
- Rename some public methods to more closely match linker terminology
- Add a few more tests for edge cases
- License headers
- Don't use string interpolation
- Don't use extension method for GetSignaturePart
- Remove unnecessary nullable context
- Remove unnecessary IndexOf
@sbomer sbomer merged commit 0e38c61 into dotnet:master May 27, 2020
tkapin pushed a commit to tkapin/runtime that referenced this pull request Jan 31, 2023
* Add signature parser based on Roslyn doc comments

* Fix formatting

* PR feedback

- SignatureParser -> DocumentationSignatureParser
- GetSignaturePart extension moved to DocumentationSignatureParser
- Inverted a condition
- Added a clarifying comment about generics

* Avoid ImmutableArray

To let it build on mono

* Rename test attributes

And add comments clarifying their behavior

* Fix mono test failure

There were two issues:
- Nunit doesn't like assertions inside of a TestCaseSource method.
- On mono, the test infra failed to resolve the new assertion attributes

* Factor parser for use from DynamicDependencyAttribute

- Allow parsing a signature without a member type prefix
- Allow parsing a member without a type name
- Allow matching multiple member kinds
- Rename some public methods to more closely match linker terminology
- Add a few more tests for edge cases

* PR feedback

- License headers
- Don't use string interpolation
- Don't use extension method for GetSignaturePart
- Remove unnecessary nullable context
- Remove unnecessary IndexOf

* Update link for edge cases

Commit migrated from dotnet/linker@0e38c61
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants