Skip to content
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

Basic handling of function pointer types in the IDE #44564

Merged
merged 17 commits into from
May 29, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.BinaryPattern(Microsoft.CodeA
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ImplicitObjectCreationExpression() -> Microsoft.CodeAnalysis.CSharp.Syntax.ImplicitObjectCreationExpressionSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ImplicitObjectCreationExpression(Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax argumentList, Microsoft.CodeAnalysis.CSharp.Syntax.InitializerExpressionSyntax initializer) -> Microsoft.CodeAnalysis.CSharp.Syntax.ImplicitObjectCreationExpressionSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ImplicitObjectCreationExpression(Microsoft.CodeAnalysis.SyntaxToken newKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax argumentList, Microsoft.CodeAnalysis.CSharp.Syntax.InitializerExpressionSyntax initializer) -> Microsoft.CodeAnalysis.CSharp.Syntax.ImplicitObjectCreationExpressionSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ParseTypeName(string text, int offset = 0, Microsoft.CodeAnalysis.ParseOptions options = null, bool consumeFullText = true) -> Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ParseTypeName(string text, int offset, bool consumeFullText) -> Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax
virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitFunctionPointerType(Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax node) -> void
virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor<TResult>.VisitFunctionPointerType(Microsoft.CodeAnalysis.CSharp.Syntax.FunctionPointerTypeSyntax node) -> TResult
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ParenthesizedPattern(Microsoft.CodeAnalysis.CSharp.Syntax.PatternSyntax pattern) -> Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedPatternSyntax
Expand All @@ -122,6 +124,7 @@ static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.UnaryPattern(Microsoft.CodeAn
*REMOVED*Microsoft.CodeAnalysis.CSharp.Syntax.ObjectCreationExpressionSyntax.ArgumentList.get -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax
*REMOVED*Microsoft.CodeAnalysis.CSharp.Syntax.ObjectCreationExpressionSyntax.Initializer.get -> Microsoft.CodeAnalysis.CSharp.Syntax.InitializerExpressionSyntax
*REMOVED*Microsoft.CodeAnalysis.CSharp.Syntax.ObjectCreationExpressionSyntax.NewKeyword.get -> Microsoft.CodeAnalysis.SyntaxToken
*REMOVED*static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ParseTypeName(string text, int offset = 0, bool consumeFullText = true) -> Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax
Copy link
Contributor

@AlekseyTs AlekseyTs May 29, 2020

Choose a reason for hiding this comment

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

Shouldn't we keep this API? #Closed

Copy link
Contributor

Choose a reason for hiding this comment

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

Or is the only change that we removed default values for parameters?


In reply to: 432672190 [](ancestors = 432672190)

virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitBinaryPattern(Microsoft.CodeAnalysis.CSharp.Syntax.BinaryPatternSyntax node) -> void
virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitImplicitObjectCreationExpression(Microsoft.CodeAnalysis.CSharp.Syntax.ImplicitObjectCreationExpressionSyntax node) -> void
virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitParenthesizedPattern(Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedPatternSyntax node) -> void
Expand Down
14 changes: 12 additions & 2 deletions src/Compilers/CSharp/Portable/Syntax/SyntaxFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1693,9 +1693,19 @@ public static NameSyntax ParseName(string text, int offset = 0, bool consumeFull
/// <summary>
/// Parse a TypeNameSyntax node using the grammar rule for type names.
/// </summary>
public static TypeSyntax ParseTypeName(string text, int offset = 0, bool consumeFullText = true)
// Backcompat overload, do not remove
[EditorBrowsable(EditorBrowsableState.Never)]
public static TypeSyntax ParseTypeName(string text, int offset, bool consumeFullText)
CyrusNajmabadi marked this conversation as resolved.
Show resolved Hide resolved
{
using (var lexer = MakeLexer(text, offset))
return ParseTypeName(text, offset, options: null, consumeFullText);
}

/// <summary>
/// Parse a TypeNameSyntax node using the grammar rule for type names.
/// </summary>
public static TypeSyntax ParseTypeName(string text, int offset = 0, ParseOptions? options = null, bool consumeFullText = true)
Copy link
Contributor

@AlekseyTs AlekseyTs May 29, 2020

Choose a reason for hiding this comment

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

options [](start = 90, length = 7)

Why is this needed? #Closed

Copy link
Contributor

@AlekseyTs AlekseyTs May 29, 2020

Choose a reason for hiding this comment

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

ParseOptions [](start = 76, length = 12)

Should this be CSharpParseOptions as in ParseCompilationUnit? #Closed

Copy link
Member Author

@333fred 333fred May 29, 2020

Choose a reason for hiding this comment

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

We seem to be inconsistent as to whether we take a ParseOptions or a CSharpParseOptions, but given that this (and the rest where we take a ParseOptions) just casts immediately I'll make it CSharpParseOptions.


In reply to: 432679991 [](ancestors = 432679991)

Copy link
Contributor

@AlekseyTs AlekseyTs May 29, 2020

Choose a reason for hiding this comment

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

ParseTypeName [](start = 33, length = 13)

Please add targeted compiler test for this API #Closed

{
using (var lexer = MakeLexer(text, offset, (CSharpParseOptions?)options))
using (var parser = MakeParser(lexer))
{
var node = parser.ParseTypeName();
Expand Down
4 changes: 3 additions & 1 deletion src/Compilers/VisualBasic/Portable/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@

Shared Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory.ParseTypeName(text As String, offset As Integer = 0, options As Microsoft.CodeAnalysis.ParseOptions = Nothing, consumeFullText As Boolean = True) -> Microsoft.CodeAnalysis.VisualBasic.Syntax.TypeSyntax
Shared Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory.ParseTypeName(text As String, offset As Integer, consumeFullText As Boolean) -> Microsoft.CodeAnalysis.VisualBasic.Syntax.TypeSyntax
*REMOVED*Shared Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory.ParseTypeName(text As String, offset As Integer = 0, consumeFullText As Boolean = True) -> Microsoft.CodeAnalysis.VisualBasic.Syntax.TypeSyntax
16 changes: 14 additions & 2 deletions src/Compilers/VisualBasic/Portable/Syntax/SyntaxNodeFactories.vb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Imports Microsoft.CodeAnalysis.VisualBasic.SyntaxFacts
Imports InternalSyntax = Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax
Imports Microsoft.CodeAnalysis.Syntax
Imports System.Collections.Immutable
Imports System.ComponentModel
Copy link
Contributor

@AlekseyTs AlekseyTs May 29, 2020

Choose a reason for hiding this comment

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

Is this needed? #Closed

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, it's for the EditorBrowsableAttribute.


In reply to: 432677987 [](ancestors = 432677987)


Namespace Microsoft.CodeAnalysis.VisualBasic

Expand Down Expand Up @@ -191,14 +192,25 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
''' </summary>
''' <param name="text">The input string</param>
''' <param name="offset">The starting offset in the string</param>
Public Shared Function ParseTypeName(text As String, Optional offset As Integer = 0, Optional consumeFullText As Boolean = True) As TypeSyntax
Using p = New InternalSyntax.Parser(MakeSourceText(text, offset), VisualBasicParseOptions.Default)
Public Shared Function ParseTypeName(text As String, Optional offset As Integer = 0, Optional options As ParseOptions = Nothing, Optional consumeFullText As Boolean = True) As TypeSyntax
Copy link
Contributor

@AlekseyTs AlekseyTs May 29, 2020

Choose a reason for hiding this comment

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

ParseOptions [](start = 113, length = 12)

Should this be VisualBasicParseOptions as in ParseCompilationUnit and other similar APIs? #Closed

Copy link
Contributor

@AlekseyTs AlekseyTs May 29, 2020

Choose a reason for hiding this comment

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

ParseTypeName [](start = 31, length = 13)

Please add targeted compiler test for this API #Closed

Using p = New InternalSyntax.Parser(MakeSourceText(text, offset), If(DirectCast(options, VisualBasicParseOptions), VisualBasicParseOptions.Default))
p.GetNextToken()
Dim node = p.ParseGeneralType()
Return DirectCast(If(consumeFullText, p.ConsumeUnexpectedTokens(node), node).CreateRed(Nothing, 0), TypeSyntax)
End Using
End Function

'' Backcompat overload, do not touch
''' <summary>
''' Parse a type name.
''' </summary>
''' <param name="text">The input string</param>
''' <param name="offset">The starting offset in the string</param>
<EditorBrowsable(EditorBrowsableState.Never)>
Public Shared Function ParseTypeName(text As String, offset As Integer, consumeFullText As Boolean) As TypeSyntax
Return ParseTypeName(text, offset, options:=Nothing, consumeFullText)
End Function

''' <summary>
''' Parse an expression.
''' </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public override bool CheckOpeningPoint(IBraceCompletionSession session, Cancella
// type argument or parameter list
if (!token.CheckParent<TypeParameterListSyntax>(n => n.LessThanToken == token) &&
!token.CheckParent<TypeArgumentListSyntax>(n => n.LessThanToken == token) &&
!token.CheckParent<FunctionPointerTypeSyntax>(n => n.LessThanToken == token) &&
333fred marked this conversation as resolved.
Show resolved Hide resolved
!PossibleTypeArgument(snapshot, token, cancellationToken))
{
return false;
Expand Down
84 changes: 72 additions & 12 deletions src/EditorFeatures/CSharpTest/ExtractMethod/ExtractMethodTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11109,17 +11109,17 @@ public async Task ExtractMethodInInterface()
var code = @"
interface Program
{
void Foo();
void Goo();

void Test()
{
[|Foo();|]
[|Goo();|]
}
}";
var expected = @"
interface Program
{
void Foo();
void Goo();

void Test()
{
Expand All @@ -11128,7 +11128,7 @@ void Test()

void NewMethod()
{
Foo();
Goo();
}
}";
await TestExtractMethodAsync(code, expected);
Expand All @@ -11139,18 +11139,18 @@ void NewMethod()
public async Task ExtractMethodInExpressionBodiedConstructors()
{
var code = @"
class Foo
class Goo
{
private readonly string _bar;

private Foo(string bar) => _bar = [|bar|];
private Goo(string bar) => _bar = [|bar|];
}";
var expected = @"
class Foo
class Goo
{
private readonly string _bar;

private Foo(string bar) => _bar = GetBar(bar);
private Goo(string bar) => _bar = GetBar(bar);

private static string GetBar(string bar)
{
Expand All @@ -11165,18 +11165,18 @@ private static string GetBar(string bar)
public async Task ExtractMethodInExpressionBodiedFinalizers()
{
var code = @"
class Foo
class Goo
{
bool finalized;

~Foo() => finalized = [|true|];
~Goo() => finalized = [|true|];
}";
var expected = @"
class Foo
class Goo
{
bool finalized;

~Foo() => finalized = NewMethod();
~Goo() => finalized = NewMethod();

private static bool NewMethod()
{
Expand All @@ -11185,5 +11185,65 @@ private static bool NewMethod()
}";
await TestExtractMethodAsync(code, expected);
}

[Fact, Trait(Traits.Feature, Traits.Features.ExtractMethod)]
public async Task ExtractMethodInvolvingFunctionPointer()
{
var code = @"
class C
{
void M(delegate*<delegate*<ref string, ref readonly int>> ptr1)
{
string s = null;
_ = [|ptr1()|](ref s);
}
}";

var expected = @"
class C
{
void M(delegate*<delegate*<ref string, ref readonly int>> ptr1)
{
string s = null;
_ = NewMethod(ptr1)(ref s);
}

private static delegate*<ref string, ref readonly int> NewMethod(delegate*<delegate*<ref string, ref readonly int>> ptr1)
333fred marked this conversation as resolved.
Show resolved Hide resolved
{
return ptr1();
}
}";

await TestExtractMethodAsync(code, expected);
}

[Fact, Trait(Traits.Feature, Traits.Features.ExtractMethod)]
public async Task ExtractMethodInvolvingFunctionPointerWithTypeParameter()
{
var code = @"
class C
{
void M<T1, T2>(delegate*<T1, T2> ptr1)
{
_ = [|ptr1|]();
}
}";

var expected = @"
class C
{
void M<T1, T2>(delegate*<T1, T2> ptr1)
{
_ = GetPtr1(ptr1)();
}

private static delegate*<T1, T2> GetPtr1<T1, T2>(delegate*<T1, T2> ptr1)
{
return ptr1;
}
}";

await TestExtractMethodAsync(code, expected);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -716,5 +716,41 @@ void Method()
}
}");
}

[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestInFunctionPointerType()
{
await VerifyKeywordAsync(@"
class C
{
delegate*<$$");
}

[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestInFunctionPointerTypeAfterComma()
{
await VerifyKeywordAsync(@"
class C
{
delegate*<int, $$");
}

[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestInFunctionPointerTypeAfterModifier()
{
await VerifyKeywordAsync(@"
class C
{
delegate*<ref $$");
}

[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestNotAfterDelegateAsterisk()
{
await VerifyAbsenceAsync(@"
class C
{
delegate*$$");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,42 @@ void Method()
}
}");
}

[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestInFunctionPointerType()
{
await VerifyKeywordAsync(@"
class C
{
delegate*<$$");
}

[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestInFunctionPointerTypeAfterComma()
{
await VerifyKeywordAsync(@"
class C
{
delegate*<int, $$");
}

[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestInFunctionPointerTypeAfterModifier()
{
await VerifyKeywordAsync(@"
class C
{
delegate*<ref $$");
}

[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestNotAfterDelegateAsterisk()
{
await VerifyAbsenceAsync(@"
class C
{
delegate*$$");
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -767,5 +767,41 @@ void Method()
}
}");
}

[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestInFunctionPointerType()
{
await VerifyKeywordAsync(@"
class C
{
delegate*<$$");
}

[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestInFunctionPointerTypeAfterComma()
{
await VerifyKeywordAsync(@"
class C
{
delegate*<int, $$");
}

[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestInFunctionPointerTypeAfterModifier()
{
await VerifyKeywordAsync(@"
class C
{
delegate*<ref $$");
}

[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestNotAfterDelegateAsterisk()
{
await VerifyAbsenceAsync(@"
class C
{
delegate*$$");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -732,5 +732,41 @@ void Method()
}
}");
}

[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestInFunctionPointerType()
{
await VerifyKeywordAsync(@"
class C
{
delegate*<$$");
333fred marked this conversation as resolved.
Show resolved Hide resolved
}

[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestInFunctionPointerTypeAfterComma()
{
await VerifyKeywordAsync(@"
class C
{
delegate*<int, $$");
}

[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestInFunctionPointerTypeAfterModifier()
{
await VerifyKeywordAsync(@"
class C
{
delegate*<ref $$");
}

[Fact, Trait(Traits.Feature, Traits.Features.KeywordRecommending)]
public async Task TestNotAfterDelegateAsterisk()
{
await VerifyAbsenceAsync(@"
class C
{
delegate*$$");
}
}
}
Loading