-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
C#: Roslyn-based stub generation #14095
Conversation
if (symbol.IsAbstract) | ||
{ | ||
if ( | ||
// exclude interface declarations | ||
(symbol is not INamedTypeSymbol type || type.TypeKind != TypeKind.Interface) && | ||
// exclude non-static interface members | ||
(symbol.ContainingType is not INamedTypeSymbol containingType || containingType.TypeKind != TypeKind.Interface || symbol.IsStatic)) | ||
{ | ||
stubWriter.Write("abstract "); | ||
} | ||
} |
Check notice
Code scanning / CodeQL
Nested 'if' statements can be combined Note
if (symbol.IsSealed) | ||
{ | ||
if (!(symbol is INamedTypeSymbol type && (type.TypeKind == TypeKind.Enum || type.TypeKind == TypeKind.Delegate || type.TypeKind == TypeKind.Struct))) | ||
stubWriter.Write("sealed "); | ||
} |
Check notice
Code scanning / CodeQL
Nested 'if' statements can be combined Note
csharp/extractor/Semmle.Extraction.CSharp.StubGenerator/StubGenerator.cs
Fixed
Show fixed
Hide fixed
|
||
private void StubModifiers(ISymbol symbol, bool skipAccessibility = false) | ||
{ | ||
if (symbol.ContainingType is ITypeSymbol containing && containing.TypeKind == TypeKind.Interface) |
Check warning
Code scanning / CodeQL
Useless type test Warning
INamedTypeSymbol
ITypeSymbol
db4d1c3
to
73075e3
Compare
type is INamedTypeSymbol named && (named.IsTupleType || named.TypeArguments.Any(ContainsTupleType)) || | ||
type is IArrayTypeSymbol array && ContainsTupleType(array.ElementType) || | ||
type is IPointerTypeSymbol pointer && ContainsTupleType(pointer.PointedAtType); |
Check notice
Code scanning / CodeQL
Complex condition Note
SymbolEqualityComparer.Default.Equals(t1, t2) || | ||
( | ||
t1 is INamedTypeSymbol named1 && | ||
t2 is INamedTypeSymbol named2 && | ||
EqualsModuloTupleElementNames(named1.ConstructedFrom, named2.ConstructedFrom) && | ||
named1.TypeArguments.Length == named2.TypeArguments.Length && | ||
named1.TypeArguments.Zip(named2.TypeArguments).All(p => EqualsModuloTupleElementNames(p.First, p.Second)) | ||
) || | ||
( | ||
t1 is IArrayTypeSymbol array1 && | ||
t2 is IArrayTypeSymbol array2 && | ||
EqualsModuloTupleElementNames(array1.ElementType, array2.ElementType) | ||
) || | ||
( | ||
t1 is IPointerTypeSymbol pointer1 && | ||
t2 is IPointerTypeSymbol pointer2 && | ||
EqualsModuloTupleElementNames(pointer1.PointedAtType, pointer2.PointedAtType) | ||
); |
Check notice
Code scanning / CodeQL
Complex condition Note
73075e3
to
aff8207
Compare
e806ae9
to
f8ace6a
Compare
f8ace6a
to
c06b515
Compare
c06b515
to
2beb829
Compare
6db4dc5
to
591f055
Compare
3381f33
to
b3ac833
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me. I've added some comments/questions.
One general question: we're not explicitly ordering the printed members. Do we know if the roslyn provided order is stable? If we used alphabetical ordering, then we would probably match what the previous stub generator did, and then verifying the correctness of the newly generated stubs would be easy.
csharp/extractor/Semmle.Extraction.CSharp.DependencyStubGenerator/Program.cs
Show resolved
Hide resolved
csharp/extractor/Semmle.Extraction.CSharp.DependencyStubGenerator/Program.cs
Outdated
Show resolved
Hide resolved
csharp/extractor/Semmle.Extraction.CSharp.StubGenerator/StubGenerator.cs
Show resolved
Hide resolved
csharp/extractor/Semmle.Extraction.CSharp.StubGenerator/StubGenerator.cs
Outdated
Show resolved
Hide resolved
csharp/extractor/Semmle.Extraction.CSharp.StubGenerator/StubGenerator.cs
Outdated
Show resolved
Hide resolved
csharp/extractor/Semmle.Extraction.CSharp.StubGenerator/StubGenerator.cs
Outdated
Show resolved
Hide resolved
csharp/extractor/Semmle.Extraction.CSharp.StubGenerator/StubVisitor.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approximately half way through. Will continue later today.
This looks really really cool @hvitved . Really great (and impressive) work!
Besides the inlined questions and comments:
- Maybe run DCA since we change existing production code.
- Is it possible to make some unit tests somehow of the StubVisitor?
csharp/extractor/Semmle.Extraction.CSharp.StubGenerator/StubGenerator.cs
Outdated
Show resolved
Hide resolved
csharp/extractor/Semmle.Extraction.CSharp.StubGenerator/StubGenerator.cs
Outdated
Show resolved
Hide resolved
csharp/extractor/Semmle.Extraction.CSharp.StubGenerator/StubVisitor.cs
Outdated
Show resolved
Hide resolved
csharp/extractor/Semmle.Extraction.CSharp.StubGenerator/StubVisitor.cs
Outdated
Show resolved
Hide resolved
csharp/extractor/Semmle.Extraction.CSharp.StubGenerator/StubVisitor.cs
Outdated
Show resolved
Hide resolved
b3ac833
to
e14898c
Compare
I have addressed your comments, and the members are now sorted alphabetically. I simply updated the original stub regeneration commits with the newly generated stubs, instead of adding extra commits. |
e14898c
to
04c4e73
Compare
Thanks :-) I have (force) pushed changes to address your comments as well.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have addressed your comments, and the members are now sorted alphabetically. I simply updated the original stub regeneration commits with the newly generated stubs, instead of adding extra commits.
Thanks. It looks like the original stub generator did a bit more than ordering alphabetically. ( I think it might have generated the full signatures in memory, and then order them before writing.) I think it would be difficult to repro this based on Roslyn, which is a shame, it would have been great to compare the original and new stubs. (BTW, we might not have a stable order for overloads either.)
I've added some comments where I found differences between the old and new stubs.
...ubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authentication.Abstractions.cs
Show resolved
Hide resolved
...ubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authentication.Abstractions.cs
Outdated
Show resolved
Hide resolved
...urces/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authentication.Core.cs
Show resolved
Hide resolved
.../stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Components.Authorization.cs
Outdated
Show resolved
Hide resolved
...esources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Components.Forms.cs
Show resolved
Hide resolved
csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.AppContext.cs
Outdated
Show resolved
Hide resolved
.../ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.InteropServices.cs
Show resolved
Hide resolved
Indeed, that is what the QL based stub generator does, and we very much don't want to first compute things in memory and then write to disk later. |
csharp/extractor/Semmle.Extraction.CSharp.StubGenerator/StubVisitor.cs
Outdated
Show resolved
Hide resolved
csharp/extractor/Semmle.Extraction.CSharp.StubGenerator/StubVisitor.cs
Outdated
Show resolved
Hide resolved
csharp/extractor/Semmle.Extraction.CSharp.StubGenerator/StubVisitor.cs
Outdated
Show resolved
Hide resolved
6b11ee0
to
208616e
Compare
208616e
to
f07d02b
Compare
csharp/extractor/Semmle.Extraction.CSharp.StubGenerator/StubVisitor.cs
Outdated
Show resolved
Hide resolved
csharp/extractor/Semmle.Extraction.CSharp.StubGenerator/StubGenerator.cs
Outdated
Show resolved
Hide resolved
csharp/extractor/Semmle.Extraction.CSharp.StubGenerator/StubGenerator.cs
Show resolved
Hide resolved
d8a806a
to
0108aef
Compare
0108aef
to
831baa8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
How much faster is this solution than the previous QL based one?
public ANTLRStringStream(System.Char[] data, int numberOfActualCharsInArray) => throw null; | ||
protected ANTLRStringStream() => throw null; | ||
public virtual int CharPositionInLine { get => throw null; set => throw null; } | ||
public virtual int CharPositionInLine { get => throw null; set { } } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
set
doesn't throw null?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No reason to, it is just a matter of making the stubs as simple as possible in terms of generated code.
Yeah, I am also really curious! |
It takes just a few seconds to generate stubs for the full standard library, so definitely much faster, but I don't have actual numbers from before. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work Tom!
LGTM 👍
Non-blocking question:
Are you planning on making it unit testable or introduce some integration like tests for? We do have tests for the queries used by the old stub generator.
Generating stubs for |
Unit tests, no. But I was thinking about adding an integration test. |
This PR introduced a Roslyn-based stub generator, based on the existing (but much much slower) QL based stub generator. The
make_stubs_nuget.py
script is updated to use the new generator, and this PR updates some of the existing stubs with newly generated stubs.Commit-by-commit review is suggested.