From 73a916da185802ec15174cb5cfceeb68c0839c86 Mon Sep 17 00:00:00 2001 From: Ravi Chande Date: Fri, 20 Feb 2015 12:54:20 -0800 Subject: [PATCH 1/2] Show 'else' within Ifs within Elses When recommending "Else" we walk all the way up the tree to determine if the position is nested inside an Else block. This means we don't recommend "Else" inside an If block nested within an Else block. When walking up the tree, we should stop at the If/ElseIf block. --- .../Statements/ElseKeywordRecommenderTests.vb | 31 +++++++++++++++++++ .../Statements/ElseKeywordRecommender.vb | 20 +++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/EditorFeatures/VisualBasicTest/Recommendations/Statements/ElseKeywordRecommenderTests.vb b/src/EditorFeatures/VisualBasicTest/Recommendations/Statements/ElseKeywordRecommenderTests.vb index adaf8740eee79..b4bcd46c00008 100644 --- a/src/EditorFeatures/VisualBasicTest/Recommendations/Statements/ElseKeywordRecommenderTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Recommendations/Statements/ElseKeywordRecommenderTests.vb @@ -233,6 +233,37 @@ Select Case x Select Case x Case | Case 1 +, "Else") + End Sub + + + + Public Sub ElseWithinIfWithinElse() + VerifyRecommendationsContain( + +If True Then + +Else + If False Then + | + End If +End If +, "Else") + End Sub + + + + Public Sub ElseWithinElseIfWithinElse() + VerifyRecommendationsContain( + +If True Then + +Else + If False Then + ElseIf True + | + End If +End If , "Else") End Sub End Class diff --git a/src/Features/VisualBasic/Completion/KeywordRecommenders/Statements/ElseKeywordRecommender.vb b/src/Features/VisualBasic/Completion/KeywordRecommenders/Statements/ElseKeywordRecommender.vb index 94616f330b50c..81a816b969af2 100644 --- a/src/Features/VisualBasic/Completion/KeywordRecommenders/Statements/ElseKeywordRecommender.vb +++ b/src/Features/VisualBasic/Completion/KeywordRecommenders/Statements/ElseKeywordRecommender.vb @@ -24,7 +24,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Stat If context.IsSingleLineStatementContext AndAlso context.IsInStatementBlockOfKind(SyntaxKind.MultiLineIfBlock, SyntaxKind.ElseIfBlock) AndAlso - Not context.IsInStatementBlockOfKind(SyntaxKind.ElseBlock) Then + IsNotDirectlyInElseBlock(context) Then Return SpecializedCollections.SingletonEnumerable(New RecommendedKeyword("Else", VBFeaturesResources.ElseKeywordToolTip)) End If @@ -45,5 +45,23 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Stat Return SpecializedCollections.EmptyEnumerable(Of RecommendedKeyword)() End Function + + Private Function IsNotDirectlyInElseBlock(context As VisualBasicSyntaxContext) As Boolean + Dim parent = context.TargetToken.Parent + Do While parent IsNot Nothing + If parent.IsKind(SyntaxKind.MultiLineIfBlock, SyntaxKind.ElseIfBlock) Then + Return True + End If + + If parent.IsKind(SyntaxKind.ElseBlock) Then + Return False + End If + + parent = parent.Parent + Loop + + ' We already know we're inside a Multiline If or ElseIf + Throw ExceptionUtilities.Unreachable + End Function End Class End Namespace From 769a863479a9a6be6a3f9c2c16600308a487464f Mon Sep 17 00:00:00 2001 From: Ravi Chande Date: Fri, 20 Feb 2015 15:00:33 -0800 Subject: [PATCH 2/2] Don't walk up the tree to find the if/elseif block --- .../Statements/ElseKeywordRecommenderTests.vb | 14 ++++++++++ .../Statements/ElseKeywordRecommender.vb | 26 +++++++------------ 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/EditorFeatures/VisualBasicTest/Recommendations/Statements/ElseKeywordRecommenderTests.vb b/src/EditorFeatures/VisualBasicTest/Recommendations/Statements/ElseKeywordRecommenderTests.vb index b4bcd46c00008..227e7b5c13ec0 100644 --- a/src/EditorFeatures/VisualBasicTest/Recommendations/Statements/ElseKeywordRecommenderTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Recommendations/Statements/ElseKeywordRecommenderTests.vb @@ -264,7 +264,21 @@ Else | End If End If +, "Else") + End Sub + + + + Public Sub ElseNotWithinDo() + VerifyRecommendationsMissing( + +If True Then +Do While True + | +End While +End If , "Else") End Sub End Class + End Namespace diff --git a/src/Features/VisualBasic/Completion/KeywordRecommenders/Statements/ElseKeywordRecommender.vb b/src/Features/VisualBasic/Completion/KeywordRecommenders/Statements/ElseKeywordRecommender.vb index 81a816b969af2..b168f401bda4d 100644 --- a/src/Features/VisualBasic/Completion/KeywordRecommenders/Statements/ElseKeywordRecommender.vb +++ b/src/Features/VisualBasic/Completion/KeywordRecommenders/Statements/ElseKeywordRecommender.vb @@ -23,8 +23,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Stat End If If context.IsSingleLineStatementContext AndAlso - context.IsInStatementBlockOfKind(SyntaxKind.MultiLineIfBlock, SyntaxKind.ElseIfBlock) AndAlso - IsNotDirectlyInElseBlock(context) Then + IsDirectlyInIfOrElseIf(context) Then Return SpecializedCollections.SingletonEnumerable(New RecommendedKeyword("Else", VBFeaturesResources.ElseKeywordToolTip)) End If @@ -46,22 +45,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion.KeywordRecommenders.Stat Return SpecializedCollections.EmptyEnumerable(Of RecommendedKeyword)() End Function - Private Function IsNotDirectlyInElseBlock(context As VisualBasicSyntaxContext) As Boolean - Dim parent = context.TargetToken.Parent - Do While parent IsNot Nothing - If parent.IsKind(SyntaxKind.MultiLineIfBlock, SyntaxKind.ElseIfBlock) Then - Return True - End If - - If parent.IsKind(SyntaxKind.ElseBlock) Then - Return False - End If - - parent = parent.Parent - Loop + Private Function IsDirectlyInIfOrElseIf(context As VisualBasicSyntaxContext) As Boolean + ' Maybe we're after the Then keyword + If context.TargetToken.IsKind(SyntaxKind.ThenKeyword) AndAlso + context.TargetToken.Parent?.Parent.IsKind(SyntaxKind.MultiLineIfBlock, SyntaxKind.ElseIfBlock) Then + Return True + End If - ' We already know we're inside a Multiline If or ElseIf - Throw ExceptionUtilities.Unreachable + Dim statement = context.TargetToken.Parent.GetAncestor(Of StatementSyntax) + Return If(statement?.Parent.IsKind(SyntaxKind.MultiLineIfBlock, SyntaxKind.ElseIfBlock), False) End Function End Class End Namespace