@@ -641,9 +641,14 @@ public override async Task<SyntaxList<StatementSyntax>> VisitGoToStatement(VBSyn
641641 public override async Task < SyntaxList < StatementSyntax > > VisitSelectBlock ( VBSyntax . SelectBlockSyntax node )
642642 {
643643 var vbExpr = node . SelectStatement . Expression ;
644- var wrapAllCases = CommonConversions . VisualBasicEqualityComparison . OptionCompareTextCaseInsensitive &&
645- _semanticModel . GetTypeInfo ( vbExpr ) . ConvertedType ? . SpecialType == SpecialType . System_String ;
644+ var vbEquality = CommonConversions . VisualBasicEqualityComparison ;
646645 var ( csExpr , stmts , csExprWithSourceMapping ) = await GetExpressionWithoutSideEffectsAsync ( vbExpr , "switchExpr" ) ;
646+ var switchExprTypeInfo = _semanticModel . GetTypeInfo ( vbExpr ) ;
647+ var isStringComparison = switchExprTypeInfo . ConvertedType ? . SpecialType == SpecialType . System_String ;
648+ var caseInsensitiveStringComparison = vbEquality . OptionCompareTextCaseInsensitive &&
649+ isStringComparison ;
650+ csExpr = vbEquality . VbCoerceToNonNullString ( vbExpr , csExpr , switchExprTypeInfo ) ;
651+
647652 var usedConstantValues = new HashSet < object > ( ) ;
648653 var sections = new List < SwitchSectionSyntax > ( ) ;
649654 foreach ( var block in node . CaseBlocks ) {
@@ -655,22 +660,30 @@ public override async Task<SyntaxList<StatementSyntax>> VisitSelectBlock(VBSynta
655660 var typeConversionKind = CommonConversions . TypeConversionAnalyzer . AnalyzeConversion ( s . Value ) ;
656661 var correctTypeExpressionSyntax = CommonConversions . TypeConversionAnalyzer . AddExplicitConversion ( s . Value , originalExpressionSyntax , typeConversionKind , true , true ) ;
657662 var constantValue = _semanticModel . GetConstantValue ( s . Value ) ;
663+ var caseTypeInfo = _semanticModel . GetTypeInfo ( s . Value ) ;
658664 var notAlreadyUsed = ! constantValue . HasValue || usedConstantValues . Add ( constantValue . Value ) ;
659- var caseSwitchLabelSyntax = ! wrapAllCases && correctTypeExpressionSyntax . IsConst && notAlreadyUsed
660- ? ( SwitchLabelSyntax ) SyntaxFactory . CaseSwitchLabel ( correctTypeExpressionSyntax . Expr )
661- : WrapInCasePatternSwitchLabelSyntax ( node , correctTypeExpressionSyntax . Expr ) ;
665+ var csCase = correctTypeExpressionSyntax . Expr ;
666+
667+ // Pass both halves in case we can optimize away the check based on the switch expr
668+ if ( isStringComparison && ! caseInsensitiveStringComparison ) {
669+ csCase = vbEquality . VbCoerceToNonNullString ( vbExpr , csExpr , switchExprTypeInfo , s . Value , correctTypeExpressionSyntax . Expr , caseTypeInfo ) . rhs ;
670+ }
671+ var caseSwitchLabelSyntax = ! caseInsensitiveStringComparison && correctTypeExpressionSyntax . IsConst && notAlreadyUsed
672+ ? ( SwitchLabelSyntax ) SyntaxFactory . CaseSwitchLabel ( csCase )
673+ : WrapInCasePatternSwitchLabelSyntax ( node , s . Value , csCase , caseInsensitiveStringComparison ) ;
662674 labels . Add ( caseSwitchLabelSyntax ) ;
663675 } else if ( c is VBSyntax . ElseCaseClauseSyntax ) {
664676 labels . Add ( SyntaxFactory . DefaultSwitchLabel ( ) ) ;
665677 } else if ( c is VBSyntax . RelationalCaseClauseSyntax relational ) {
666678 var operatorKind = VBasic . VisualBasicExtensions . Kind ( relational ) ;
667- var binaryExp = SyntaxFactory . BinaryExpression ( operatorKind . ConvertToken ( TokenContext . Local ) , csExpr , ( ExpressionSyntax ) await relational . Value . AcceptAsync ( _expressionVisitor ) ) ;
668- labels . Add ( WrapInCasePatternSwitchLabelSyntax ( node , binaryExp , treatAsBoolean : true ) ) ;
679+ var relationalValue = ( ExpressionSyntax ) await relational . Value . AcceptAsync ( _expressionVisitor ) ;
680+ var binaryExp = SyntaxFactory . BinaryExpression ( operatorKind . ConvertToken ( TokenContext . Local ) , csExpr , relationalValue ) ;
681+ labels . Add ( WrapInCasePatternSwitchLabelSyntax ( node , relational . Value , binaryExp , caseInsensitiveStringComparison , treatAsBoolean : true ) ) ;
669682 } else if ( c is VBSyntax . RangeCaseClauseSyntax range ) {
670683 var lowerBoundCheck = SyntaxFactory . BinaryExpression ( SyntaxKind . LessThanOrEqualExpression , ( ExpressionSyntax ) await range . LowerBound . AcceptAsync ( _expressionVisitor ) , csExpr ) ;
671684 var upperBoundCheck = SyntaxFactory . BinaryExpression ( SyntaxKind . LessThanOrEqualExpression , csExpr , ( ExpressionSyntax ) await range . UpperBound . AcceptAsync ( _expressionVisitor ) ) ;
672685 var withinBounds = SyntaxFactory . BinaryExpression ( SyntaxKind . LogicalAndExpression , lowerBoundCheck , upperBoundCheck ) ;
673- labels . Add ( WrapInCasePatternSwitchLabelSyntax ( node , withinBounds , treatAsBoolean : true ) ) ;
686+ labels . Add ( WrapInCasePatternSwitchLabelSyntax ( node , range . LowerBound , withinBounds , caseInsensitiveStringComparison , treatAsBoolean : true ) ) ;
674687 } else throw new NotSupportedException ( c . Kind ( ) . ToString ( ) ) ;
675688 }
676689
@@ -722,7 +735,7 @@ private async Task<bool> IsNeverMutatedAsync(VBSyntax.NameSyntax ns)
722735 return symbol . MatchesKind ( SymbolKind . Parameter , SymbolKind . Local ) && await CommonConversions . Document . Project . Solution . IsNeverWrittenAsync ( symbol , allowedLocation ) ;
723736 }
724737
725- private CasePatternSwitchLabelSyntax WrapInCasePatternSwitchLabelSyntax ( VBSyntax . SelectBlockSyntax node , ExpressionSyntax expression , bool treatAsBoolean = false )
738+ private CasePatternSwitchLabelSyntax WrapInCasePatternSwitchLabelSyntax ( VBSyntax . SelectBlockSyntax node , VBSyntax . ExpressionSyntax vbCase , ExpressionSyntax expression , bool caseInsensitiveTextComparison , bool treatAsBoolean = false )
726739 {
727740 var typeInfo = _semanticModel . GetTypeInfo ( node . SelectStatement . Expression ) ;
728741
@@ -736,7 +749,13 @@ private CasePatternSwitchLabelSyntax WrapInCasePatternSwitchLabelSyntax(VBSyntax
736749 //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"
737750 patternMatch = SyntaxFactory . DeclarationPattern (
738751 ValidSyntaxFactory . VarType , SyntaxFactory . SingleVariableDesignation ( varName ) ) ;
739- expression = SyntaxFactory . BinaryExpression ( SyntaxKind . EqualsExpression , SyntaxFactory . IdentifierName ( varName ) , expression ) ;
752+ ExpressionSyntax csLeft = SyntaxFactory . IdentifierName ( varName ) , csRight = expression ;
753+ if ( caseInsensitiveTextComparison ) {
754+ ( csLeft , csRight ) = CommonConversions . VisualBasicEqualityComparison
755+ . AdjustForVbStringComparison ( node . SelectStatement . Expression , csLeft , typeInfo , vbCase , expression , _semanticModel . GetTypeInfo ( vbCase ) ) ;
756+ }
757+ expression = SyntaxFactory . BinaryExpression ( SyntaxKind . EqualsExpression , csLeft , csRight ) ;
758+
740759 }
741760
742761 var casePatternSwitchLabelSyntax = SyntaxFactory . CasePatternSwitchLabel ( patternMatch ,
0 commit comments