1414using Microsoft . CodeAnalysis . Editing ;
1515using Microsoft . CodeAnalysis . FindSymbols ;
1616using Microsoft . CodeAnalysis . Operations ;
17- using Microsoft . CodeAnalysis . VisualBasic ;
18- using Microsoft . CodeAnalysis . VisualBasic . Syntax ;
17+ using VBasic = Microsoft . CodeAnalysis . VisualBasic ;
18+ using VBSyntax = Microsoft . CodeAnalysis . VisualBasic . Syntax ;
1919using ArgumentListSyntax = Microsoft . CodeAnalysis . VisualBasic . Syntax . ArgumentListSyntax ;
2020using ArrayRankSpecifierSyntax = Microsoft . CodeAnalysis . CSharp . Syntax . ArrayRankSpecifierSyntax ;
2121using ArrayTypeSyntax = Microsoft . CodeAnalysis . CSharp . Syntax . ArrayTypeSyntax ;
2727using TypeSyntax = Microsoft . CodeAnalysis . CSharp . Syntax . TypeSyntax ;
2828using VariableDeclaratorSyntax = Microsoft . CodeAnalysis . VisualBasic . Syntax . VariableDeclaratorSyntax ;
2929using VisualBasicExtensions = Microsoft . CodeAnalysis . VisualBasic . VisualBasicExtensions ;
30- using VBSyntax = Microsoft . CodeAnalysis . VisualBasic . Syntax ;
3130using CSSyntax = Microsoft . CodeAnalysis . CSharp . Syntax ;
3231using CSSyntaxKind = Microsoft . CodeAnalysis . CSharp . SyntaxKind ;
3332using ITypeSymbol = Microsoft . CodeAnalysis . ITypeSymbol ;
@@ -121,7 +120,7 @@ public bool ShouldPreferExplicitType(VBSyntax.ExpressionSyntax exp,
121120 }
122121
123122 private async Task < EqualsValueClauseSyntax > ConvertEqualsValueClauseSyntax (
124- VariableDeclaratorSyntax vbDeclarator , ModifiedIdentifierSyntax vbName ,
123+ VariableDeclaratorSyntax vbDeclarator , VBSyntax . ModifiedIdentifierSyntax vbName ,
125124 VBSyntax . ExpressionSyntax vbInitValue ,
126125 ITypeSymbol declaredSymbolType ,
127126 ISymbol declaredSymbol , CSharpSyntaxNode initializerOrMethodDecl )
@@ -140,12 +139,16 @@ private async Task<EqualsValueClauseSyntax> ConvertEqualsValueClauseSyntax(
140139 ? TypeConversionAnalyzer . AddExplicitConversion ( vbInitValue , adjustedInitializerExpr , isConst : declaredConst )
141140 : adjustedInitializerExpr ;
142141
143- if ( isField && ! declaredSymbol . IsStatic && ! IsDefinitelyStatic ( vbName , vbInitValue ) ) {
144- //TODO If not the part where we're doing type wide init, convert this declaration into an arrow property called "initial<FieldName>", then call it from the other part
145- // Assuming this is the part for type wide init
146- var lhs = SyntaxFactory . IdentifierName ( ConvertIdentifier ( vbName . Identifier , sourceTriviaMapKind : SourceTriviaMapKind . None ) ) ;
147- _typeContext . Initializers . AdditionalInstanceInitializers . Add ( ( lhs , CSSyntaxKind . SimpleAssignmentExpression , adjustedInitializerExpr ) ) ;
148- equalsValueClauseSyntax = null ;
142+ if ( isField && ! declaredSymbol . IsStatic && ! _semanticModel . IsDefinitelyStatic ( vbName , vbInitValue ) ) {
143+ if ( _typeContext . Initializers . ShouldAddTypeWideInitToThisPart ) {
144+ var lhs = SyntaxFactory . IdentifierName ( ConvertIdentifier ( vbName . Identifier , sourceTriviaMapKind : SourceTriviaMapKind . None ) ) ;
145+ _typeContext . Initializers . AdditionalInstanceInitializers . Add ( ( lhs , CSSyntaxKind . SimpleAssignmentExpression , adjustedInitializerExpr ) ) ;
146+ equalsValueClauseSyntax = null ;
147+ } else {
148+ var returnBlock = SyntaxFactory . Block ( SyntaxFactory . ReturnStatement ( adjustedInitializerExpr ) ) ;
149+ _typeContext . HoistedState . Hoist < HoistedParameterlessFunction > ( new HoistedParameterlessFunction ( GetInitialValueFunctionName ( vbName ) , csTypeSyntax , returnBlock ) ) ;
150+ equalsValueClauseSyntax = null ;
151+ }
149152 } else {
150153 equalsValueClauseSyntax = SyntaxFactory . EqualsValueClause ( convertedInitializer ) ;
151154 }
@@ -163,22 +166,13 @@ private async Task<EqualsValueClauseSyntax> ConvertEqualsValueClauseSyntax(
163166 return equalsValueClauseSyntax ;
164167 }
165168
166- /// <summary>
167- /// Returns true only if expressions static (i.e. doesn't reference the containing instance)
168- /// </summary>
169- private bool IsDefinitelyStatic ( ModifiedIdentifierSyntax vbName , VBSyntax . ExpressionSyntax vbInitValue )
170- {
171- var arrayBoundExpressions = vbName . ArrayBounds != null ? vbName . ArrayBounds . Arguments . Select ( a => a . GetExpression ( ) ) . Where ( x => x != null ) : Enumerable . Empty < VBSyntax . ExpressionSyntax > ( ) ;
172- var expressions = vbInitValue . Yield ( ) . Concat ( arrayBoundExpressions ) . ToArray ( ) ;
173- return expressions . All ( IsDefinitelyStatic ) ;
174- }
175-
176- /// <summary>
177- /// Returns true only if expression is static (i.e. doesn't reference the containing instance)
178- /// </summary>
179- private bool IsDefinitelyStatic ( VBSyntax . ExpressionSyntax e )
169+ /// <remarks>
170+ /// In CS we need to lift non-static initializers to the constructor. But for partial classes these can be in different files.
171+ /// Rather than re-architect to allow communication between files, we create an initializer function, and call it from the other part, and just hope the name doesn't clash.
172+ /// </remarks>
173+ public static string GetInitialValueFunctionName ( VBSyntax . ModifiedIdentifierSyntax vbName )
180174 {
181- return _semanticModel . GetOperation ( e ) . DescendantsAndSelf ( ) . OfType < IInstanceReferenceOperation > ( ) . Any ( ) == false ;
175+ return "initial" + vbName . Identifier . ValueText . ToPascalCase ( ) ;
182176 }
183177
184178 private VariableDeclarationSyntax CreateVariableDeclaration ( VariableDeclaratorSyntax vbDeclarator , bool preferExplicitType ,
@@ -235,13 +229,13 @@ private static TypeSyntax WithDeclarationCasing(TypeSyntax syntax, ITypeSymbol t
235229 private static VBSyntax . ExpressionSyntax GetInitializerToConvert ( VariableDeclaratorSyntax declarator )
236230 {
237231 return declarator . AsClause ? . TypeSwitch (
238- ( SimpleAsClauseSyntax _ ) => declarator . Initializer ? . Value ,
239- ( AsNewClauseSyntax c ) => c . NewExpression
232+ ( VBSyntax . SimpleAsClauseSyntax _ ) => declarator . Initializer ? . Value ,
233+ ( VBSyntax . AsNewClauseSyntax c ) => c . NewExpression
240234 ) ?? declarator . Initializer ? . Value ;
241235 }
242236
243237 private async Task < CSharpSyntaxNode > GetInitializerFromNameAndType ( ITypeSymbol typeSymbol ,
244- ModifiedIdentifierSyntax name , CSharpSyntaxNode initializer )
238+ VBSyntax . ModifiedIdentifierSyntax name , CSharpSyntaxNode initializer )
245239 {
246240 if ( ! SyntaxTokenExtensions . IsKind ( name . Nullable , SyntaxKind . None ) )
247241 {
@@ -333,7 +327,7 @@ public static bool MustInlinePropertyWithEventsAccess(SyntaxNode anyNodePossibly
333327
334328 public static bool InMethodCalledInitializeComponent ( SyntaxNode anyNodePossiblyWithinMethod )
335329 {
336- return anyNodePossiblyWithinMethod . GetAncestor < MethodBlockSyntax > ( ) ? . SubOrFunctionStatement . Identifier . Text == "InitializeComponent" ;
330+ return anyNodePossiblyWithinMethod . GetAncestor < VBSyntax . MethodBlockSyntax > ( ) ? . SubOrFunctionStatement . Identifier . Text == "InitializeComponent" ;
337331 }
338332
339333 public static SyntaxToken CsEscapedIdentifier ( string text )
@@ -489,8 +483,8 @@ public async Task<ArrayRankSpecifierSyntax> ConvertArrayBounds(ArgumentListSynta
489483 private async Task < IEnumerable < ExpressionSyntax > > ConvertArrayBounds ( SeparatedSyntaxList < VBSyntax . ArgumentSyntax > arguments )
490484 {
491485 return await arguments . SelectAsync ( a => {
492- VBSyntax . ExpressionSyntax upperBoundExpression = a is SimpleArgumentSyntax sas ? sas . Expression
493- : a is RangeArgumentSyntax ras ? ras . UpperBound
486+ VBSyntax . ExpressionSyntax upperBoundExpression = a is VBSyntax . SimpleArgumentSyntax sas ? sas . Expression
487+ : a is VBSyntax . RangeArgumentSyntax ras ? ras . UpperBound
494488 : throw new ArgumentOutOfRangeException ( nameof ( a ) , a , null ) ;
495489
496490 return IncreaseArrayUpperBoundExpression ( upperBoundExpression ) ;
@@ -559,7 +553,7 @@ public static CSSyntax.VariableDeclaratorSyntax CreateVariableDeclarator(string
559553 public async Task < ( string , ExpressionSyntax extraArg ) > GetParameterizedPropertyAccessMethod ( IOperation operation )
560554 {
561555 if ( operation is IPropertyReferenceOperation pro && pro . Arguments . Any ( ) &&
562- ! pro . Property . IsDefault ( ) ) {
556+ ! VBasic . VisualBasicExtensions . IsDefault ( pro . Property ) ) {
563557 var isSetter = pro . Parent . Kind == OperationKind . SimpleAssignment && pro . Parent . Children . First ( ) == pro ;
564558 var extraArg = isSetter
565559 ? ( ExpressionSyntax ) await operation . Parent . Syntax . ChildNodes ( ) . ElementAt ( 1 ) . AcceptAsync ( TriviaConvertingExpressionVisitor )
@@ -615,7 +609,7 @@ public static SyntaxToken GetMethodBlockBaseIdentifierForImplicitReturn(SyntaxNo
615609
616610 public static bool IsDefaultIndexer ( SyntaxNode node )
617611 {
618- return node is PropertyStatementSyntax pss && pss . Modifiers . Any ( m => SyntaxTokenExtensions . IsKind ( m , Microsoft . CodeAnalysis . VisualBasic . SyntaxKind . DefaultKeyword ) ) ;
612+ return node is VBSyntax . PropertyStatementSyntax pss && pss . Modifiers . Any ( m => SyntaxTokenExtensions . IsKind ( m , Microsoft . CodeAnalysis . VisualBasic . SyntaxKind . DefaultKeyword ) ) ;
619613 }
620614
621615
@@ -641,7 +635,7 @@ public bool IsOutAttribute(VBSyntax.AttributeSyntax a)
641635 ? . Equals ( OutAttributeType . FullName ) == true ;
642636 }
643637
644- public ISymbol GetDeclaredCsOriginalSymbolOrNull ( VisualBasicSyntaxNode node )
638+ public ISymbol GetDeclaredCsOriginalSymbolOrNull ( VBasic . VisualBasicSyntaxNode node )
645639 {
646640 var declaredSymbol = _semanticModel . GetDeclaredSymbol ( node ) ;
647641 return declaredSymbol != null ? GetCsOriginalSymbolOrNull ( declaredSymbol ) : null ;
0 commit comments