@@ -642,13 +642,14 @@ public override async Task<SyntaxList<StatementSyntax>> VisitSelectBlock(VBSynta
642642 {
643643 var vbExpr = node . SelectStatement . Expression ;
644644 var vbEquality = CommonConversions . VisualBasicEqualityComparison ;
645- var ( csExprToReuse , stmts , csSwitchExpr ) = await GetExpressionWithoutSideEffectsAsync ( vbExpr , "switchExpr" ) ;
645+
646+ var csSwitchExpr = ( ExpressionSyntax ) await vbExpr . AcceptAsync ( _expressionVisitor ) ;
647+ csSwitchExpr = CommonConversions . TypeConversionAnalyzer . AddExplicitConversion ( vbExpr , csSwitchExpr ) ;
646648 var switchExprTypeInfo = _semanticModel . GetTypeInfo ( vbExpr ) ;
647649 var isStringComparison = switchExprTypeInfo . ConvertedType ? . SpecialType == SpecialType . System_String || switchExprTypeInfo . ConvertedType ? . IsArrayOf ( SpecialType . System_Char ) == true ;
648650 var caseInsensitiveStringComparison = vbEquality . OptionCompareTextCaseInsensitive &&
649651 isStringComparison ;
650652 if ( isStringComparison ) {
651- csExprToReuse = vbEquality . VbCoerceToNonNullString ( vbExpr , csExprToReuse , switchExprTypeInfo ) ;
652653 csSwitchExpr = vbEquality . VbCoerceToNonNullString ( vbExpr , csSwitchExpr , switchExprTypeInfo ) ;
653654 }
654655
@@ -668,26 +669,31 @@ public override async Task<SyntaxList<StatementSyntax>> VisitSelectBlock(VBSynta
668669
669670 // Pass both halves in case we can optimize away the check based on the switch expr
670671 var wrapForStringComparison = isStringComparison && ( caseInsensitiveStringComparison ||
671- vbEquality . VbCoerceToNonNullString ( vbExpr , csExprToReuse , switchExprTypeInfo , true , s . Value , originalExpressionSyntax , caseTypeInfo , false ) . rhs != originalExpressionSyntax ) ;
672+ vbEquality . VbCoerceToNonNullString ( vbExpr , csSwitchExpr , switchExprTypeInfo , true , s . Value , originalExpressionSyntax , caseTypeInfo , false ) . rhs != originalExpressionSyntax ) ;
672673
673674 var csExpressionToUse = wrapForStringComparison ? originalExpressionSyntax : correctTypeExpressionSyntax . Expr ;
674675
675676 var caseSwitchLabelSyntax = ! wrapForStringComparison && correctTypeExpressionSyntax . IsConst && notAlreadyUsed
676677 ? ( SwitchLabelSyntax ) SyntaxFactory . CaseSwitchLabel ( csExpressionToUse )
677- : WrapInCasePatternSwitchLabelSyntax ( node , s . Value , csExpressionToUse , caseInsensitiveStringComparison ) ;
678+ : WrapInCasePatternSwitchLabelSyntax ( node , s . Value , csExpressionToUse ) ;
678679 labels . Add ( caseSwitchLabelSyntax ) ;
679680 } else if ( c is VBSyntax . ElseCaseClauseSyntax ) {
680681 labels . Add ( SyntaxFactory . DefaultSwitchLabel ( ) ) ;
681682 } else if ( c is VBSyntax . RelationalCaseClauseSyntax relational ) {
683+
684+ var varName = CommonConversions . CsEscapedIdentifier ( GetUniqueVariableNameInScope ( node , "case" ) ) ;
685+ ExpressionSyntax csLeft = SyntaxFactory . IdentifierName ( varName ) ;
682686 var operatorKind = VBasic . VisualBasicExtensions . Kind ( relational ) ;
683687 var relationalValue = ( ExpressionSyntax ) await relational . Value . AcceptAsync ( _expressionVisitor ) ;
684- var binaryExp = SyntaxFactory . BinaryExpression ( operatorKind . ConvertToken ( TokenContext . Local ) , csExprToReuse , relationalValue ) ;
685- labels . Add ( WrapInCasePatternSwitchLabelSyntax ( node , relational . Value , binaryExp , caseInsensitiveStringComparison , treatAsBoolean : true ) ) ;
688+ var binaryExp = SyntaxFactory . BinaryExpression ( operatorKind . ConvertToken ( TokenContext . Local ) , csLeft , relationalValue ) ;
689+ labels . Add ( VarWhen ( varName , binaryExp ) ) ;
686690 } else if ( c is VBSyntax . RangeCaseClauseSyntax range ) {
687- var lowerBoundCheck = SyntaxFactory . BinaryExpression ( SyntaxKind . LessThanOrEqualExpression , ( ExpressionSyntax ) await range . LowerBound . AcceptAsync ( _expressionVisitor ) , csExprToReuse ) ;
688- var upperBoundCheck = SyntaxFactory . BinaryExpression ( SyntaxKind . LessThanOrEqualExpression , csExprToReuse , ( ExpressionSyntax ) await range . UpperBound . AcceptAsync ( _expressionVisitor ) ) ;
691+ var varName = CommonConversions . CsEscapedIdentifier ( GetUniqueVariableNameInScope ( node , "case" ) ) ;
692+ ExpressionSyntax csLeft = SyntaxFactory . IdentifierName ( varName ) ;
693+ var lowerBoundCheck = SyntaxFactory . BinaryExpression ( SyntaxKind . LessThanOrEqualExpression , ( ExpressionSyntax ) await range . LowerBound . AcceptAsync ( _expressionVisitor ) , csLeft ) ;
694+ var upperBoundCheck = SyntaxFactory . BinaryExpression ( SyntaxKind . LessThanOrEqualExpression , csLeft , ( ExpressionSyntax ) await range . UpperBound . AcceptAsync ( _expressionVisitor ) ) ;
689695 var withinBounds = SyntaxFactory . BinaryExpression ( SyntaxKind . LogicalAndExpression , lowerBoundCheck , upperBoundCheck ) ;
690- labels . Add ( WrapInCasePatternSwitchLabelSyntax ( node , range . LowerBound , withinBounds , caseInsensitiveStringComparison , treatAsBoolean : true ) ) ;
696+ labels . Add ( VarWhen ( varName , withinBounds ) ) ;
691697 } else throw new NotSupportedException ( c . Kind ( ) . ToString ( ) ) ;
692698 }
693699
@@ -701,7 +707,14 @@ public override async Task<SyntaxList<StatementSyntax>> VisitSelectBlock(VBSynta
701707 }
702708
703709 var switchStatementSyntax = ValidSyntaxFactory . SwitchStatement ( csSwitchExpr , sections ) ;
704- return stmts . Add ( switchStatementSyntax ) ;
710+ return SingleStatement ( switchStatementSyntax ) ;
711+ }
712+
713+ private static CasePatternSwitchLabelSyntax VarWhen ( SyntaxToken varName , ExpressionSyntax binaryExp )
714+ {
715+ var patternMatch = ValidSyntaxFactory . VarPattern ( varName ) ;
716+ return SyntaxFactory . CasePatternSwitchLabel ( patternMatch ,
717+ SyntaxFactory . WhenClause ( binaryExp ) , SyntaxFactory . Token ( SyntaxKind . ColonToken ) ) ;
705718 }
706719
707720 private async Task < ( ExpressionSyntax Reusable , SyntaxList < StatementSyntax > Statements , ExpressionSyntax SingleUse ) > GetExpressionWithoutSideEffectsAsync ( VBSyntax . ExpressionSyntax vbExpr , string variableNameBase , bool forceVariable = false )
@@ -739,7 +752,7 @@ private async Task<bool> IsNeverMutatedAsync(VBSyntax.NameSyntax ns)
739752 return symbol . MatchesKind ( SymbolKind . Parameter , SymbolKind . Local ) && await CommonConversions . Document . Project . Solution . IsNeverWrittenAsync ( symbol , allowedLocation ) ;
740753 }
741754
742- private CasePatternSwitchLabelSyntax WrapInCasePatternSwitchLabelSyntax ( VBSyntax . SelectBlockSyntax node , VBSyntax . ExpressionSyntax vbCase , ExpressionSyntax expression , bool caseInsensitiveTextComparison , bool treatAsBoolean = false )
755+ private CasePatternSwitchLabelSyntax WrapInCasePatternSwitchLabelSyntax ( VBSyntax . SelectBlockSyntax node , VBSyntax . ExpressionSyntax vbCase , ExpressionSyntax expression , bool treatAsBoolean = false )
743756 {
744757 var typeInfo = _semanticModel . GetTypeInfo ( node . SelectStatement . Expression ) ;
745758
@@ -750,9 +763,7 @@ private CasePatternSwitchLabelSyntax WrapInCasePatternSwitchLabelSyntax(VBSyntax
750763 SyntaxFactory . DiscardDesignation ( ) ) ;
751764 } else {
752765 var varName = CommonConversions . CsEscapedIdentifier ( GetUniqueVariableNameInScope ( node , "case" ) ) ;
753- //CodeAnalysis upgrade to 3.0.0 needed for VarPattern. Correct text comes out, but tree is invalid so the tests this will generate "CS0825: The contextual keyword 'var' may only appear within a local variable declaration or in script code"
754- patternMatch = SyntaxFactory . DeclarationPattern (
755- ValidSyntaxFactory . VarType , SyntaxFactory . SingleVariableDesignation ( varName ) ) ;
766+ patternMatch = ValidSyntaxFactory . VarPattern ( varName ) ;
756767 ExpressionSyntax csLeft = SyntaxFactory . IdentifierName ( varName ) , csRight = expression ;
757768 var caseTypeInfo = _semanticModel . GetTypeInfo ( vbCase ) ;
758769 var vbEquality = CommonConversions . VisualBasicEqualityComparison ;
0 commit comments