public ImmutableArray <int> GetMethodParameterLines(IWorkSession session, int lineInMethod, int columnInMethod) { var declaration = RoslynAdapterHelper.FindSyntaxNodeInSession(session, lineInMethod, columnInMethod) ?.AncestorsAndSelf() .FirstOrDefault(m => m is MemberDeclarationSyntax || m is AnonymousFunctionExpressionSyntax || m is LocalFunctionStatementSyntax); var parameters = declaration switch { BaseMethodDeclarationSyntax m => m.ParameterList.Parameters, ParenthesizedLambdaExpressionSyntax l => l.ParameterList.Parameters, SimpleLambdaExpressionSyntax l => SyntaxFactory.SingletonSeparatedList(l.Parameter), LocalFunctionStatementSyntax f => f.ParameterList.Parameters, _ => SyntaxFactory.SeparatedList <ParameterSyntax>() }; if (parameters.Count == 0) { return(ImmutableArray <int> .Empty); } var results = new int[parameters.Count]; for (var i = 0; i < parameters.Count; i++) { results[i] = parameters[i].GetLocation().GetLineSpan().StartLinePosition.Line + 1; } return(ImmutableArray.Create(results)); }
internal static void ComputeRefactoring(RefactoringContext context, LocalFunctionStatementSyntax localFunctionStatement) { TypeParameterListSyntax typeParameterList = localFunctionStatement.TypeParameterList; if (typeParameterList != null) { if (context.Span.IsEmptyAndContainedInSpan(typeParameterList)) { RegisterRefactoring(context, localFunctionStatement); } } else { TextSpan span = context.Span; SyntaxToken identifier = localFunctionStatement.Identifier; if (!identifier.IsMissing && span.Start >= identifier.Span.End && CheckIdentifierAndSpan(identifier, span)) { ParameterListSyntax parameterList = localFunctionStatement.ParameterList; if (parameterList != null && span.End <= parameterList.SpanStart) { RegisterRefactoring(context, localFunctionStatement); } } } }
private static SyntaxNode GetFirstUsageLocalFunc(SemanticModel model, LocalFunctionStatementSyntax node, SyntaxNode root, List <SyntaxNode> ignore = null) { var symbol = model.GetSymbolInfo(node).Symbol ?? model.GetDeclaredSymbol(node); return(root.DescendantNodes(x => x != node).OfType <IdentifierNameSyntax>().Where(x => { if (x.Identifier.ValueText != node.Identifier.ValueText) { return false; } var info = model.GetSymbolInfo(x); var xSymbol = info.Symbol; if (xSymbol == null && info.CandidateSymbols != null && info.CandidateSymbols.Length > 0) { xSymbol = info.CandidateSymbols[0]; } if (xSymbol == null || !SymbolEqualityComparer.Default.Equals(symbol, xSymbol)) { return false; } if (ignore != null && ignore.Contains(x)) { return false; } return true; }).FirstOrDefault()); }
public LocalFunctionSymbol( Binder binder, Symbol containingSymbol, LocalFunctionStatementSyntax syntax) { _syntax = syntax; _containingSymbol = containingSymbol; _declarationModifiers = DeclarationModifiers.Private | DeclarationModifiers.Static | syntax.Modifiers.ToDeclarationModifiers(); var diagnostics = DiagnosticBag.GetInstance(); if (_syntax.TypeParameterList != null) { binder = new WithMethodTypeParametersBinder(this, binder); _typeParameters = MakeTypeParameters(diagnostics); } else { _typeParameters = ImmutableArray <TypeParameterSymbol> .Empty; } if (IsExtensionMethod) { diagnostics.Add(ErrorCode.ERR_BadExtensionAgg, Locations[0]); } _binder = binder; _refKind = (syntax.ReturnType.Kind() == SyntaxKind.RefType) ? RefKind.Ref : RefKind.None; _diagnostics = diagnostics.ToReadOnlyAndFree(); }
private static bool IsReturnTypeConstructedFromTaskOfT(LocalFunctionStatementSyntax localFunction, INamedTypeSymbol taskOfTSymbol, SemanticModel semanticModel, CancellationToken cancellationToken) { var methodSymbol = (IMethodSymbol)semanticModel.GetDeclaredSymbol(localFunction, cancellationToken); return(methodSymbol?.IsErrorType() == false && methodSymbol.ReturnType.IsConstructedFrom(taskOfTSymbol)); }
private SyntaxNode FixLocalFunction(IMethodSymbol methodSymbol, LocalFunctionStatementSyntax localFunction, KnownTypes knownTypes) { var newReturnType = FixMethodReturnType(methodSymbol, localFunction.ReturnType, knownTypes); var newModifiers = FixMethodModifiers(localFunction.Modifiers, ref newReturnType); return(localFunction.WithReturnType(newReturnType).WithModifiers(newModifiers)); }
public static bool IsVoidGetter(this LocalFunctionStatementSyntax method) { var name = method.Identifier.Text; var isGetter = name.StartsWith("Get", StringComparison.OrdinalIgnoreCase); return(method.IsVoid() && isGetter); }
public override void VisitLocalFunctionStatement(LocalFunctionStatementSyntax node) { Visit(node.ParameterList); VisitType(node.ReturnType); VisitBodyOrExpressionBody(node.Body, node.ExpressionBody); //base.VisitLocalFunctionStatement(node); }
private static LocalFunctionSymbol FindLocalFunction(LocalFunctionStatementSyntax node, Binder enclosing) { LocalFunctionSymbol match = null; // Don't use LookupLocalFunction because it recurses up the tree, as it // should be defined in the directly enclosing block (see note below) Binder possibleScopeBinder = enclosing; while (possibleScopeBinder != null && !possibleScopeBinder.IsLocalFunctionsScopeBinder) { possibleScopeBinder = possibleScopeBinder.Next; } if (possibleScopeBinder != null) { foreach (var candidate in possibleScopeBinder.LocalFunctions) { if (candidate.Locations[0] == node.Identifier.GetLocation()) { match = candidate; } } } return(match); }
public override void VisitLocalFunctionStatement(LocalFunctionStatementSyntax node) { Symbol oldMethod = _containingMemberOrLambda; Binder binder = _enclosing; LocalFunctionSymbol match = FindLocalFunction(node, _enclosing); if ((object)match != null) { _containingMemberOrLambda = match; binder = match.IsGenericMethod ? new WithMethodTypeParametersBinder(match, _enclosing) : _enclosing; binder = binder.WithUnsafeRegionIfNecessary(node.Modifiers); binder = new InMethodBinder(match, binder); } BlockSyntax blockBody = node.Body; if (blockBody != null) { Visit(blockBody, binder); } ArrowExpressionClauseSyntax arrowBody = node.ExpressionBody; if (arrowBody != null) { Visit(arrowBody, binder); } _containingMemberOrLambda = oldMethod; }
private static async Task <Document> UpdateDocumentAsync( SyntaxNode root, Document document, BlockSyntax parentBlock, LocalFunctionStatementSyntax localFunction, CodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var declaredSymbol = (IMethodSymbol)semanticModel.GetDeclaredSymbol(localFunction, cancellationToken); var dataFlow = semanticModel.AnalyzeDataFlow( localFunction.Body ?? (SyntaxNode)localFunction.ExpressionBody.Expression); // Exclude local function parameters in case they were captured inside the function body var captures = dataFlow.CapturedInside.Except(dataFlow.VariablesDeclared).Except(declaredSymbol.Parameters).ToList(); // First, create a parameter per each capture so that we can pass them as arguments to the final method // Filter out `this` because it doesn't need a parameter, we will just make a non-static method for that // We also make a `ref` parameter here for each capture that is being written into inside the function var capturesAsParameters = captures .Where(capture => !capture.IsThisParameter()) .Select(capture => CodeGenerationSymbolFactory.CreateParameterSymbol( attributes: default,
public static Task <Document> RefactorAsync( Document document, LocalFunctionStatementSyntax localFunction, CancellationToken cancellationToken = default(CancellationToken)) { if (document == null) { throw new ArgumentNullException(nameof(document)); } if (localFunction == null) { throw new ArgumentNullException(nameof(localFunction)); } StatementsInfo statementsInfos = SyntaxInfo.StatementsInfo(localFunction); SyntaxList <StatementSyntax> statements = statementsInfos.Statements; int index = statements.IndexOf(localFunction); if (index == 0 && statementsInfos.Block.OpenBraceToken.GetFullSpanEndLine() == localFunction.GetFullSpanStartLine()) { localFunction = localFunction.WithLeadingTrivia(localFunction.GetLeadingTrivia().Insert(0, NewLine())); } SyntaxList <StatementSyntax> newStatements = statements.Insert(index + 1, localFunction.WithNavigationAnnotation()); return(document.ReplaceStatementsAsync(statementsInfos, newStatements, cancellationToken)); }
/// <summary> /// Returns a method symbol for the specified local function syntax. /// </summary> /// <param name="semanticModel"></param> /// <param name="localFunction"></param> /// <param name="cancellationToken"></param> internal static IMethodSymbol GetDeclaredSymbol( this SemanticModel semanticModel, LocalFunctionStatementSyntax localFunction, CancellationToken cancellationToken = default) { return((IMethodSymbol)ModelExtensions.GetDeclaredSymbol(semanticModel, localFunction, cancellationToken)); }
private static async Task <Document> RefactorAsync( Document document, StatementSyntax statement, CancellationToken cancellationToken) { StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(statement); var methodDeclaration = (MethodDeclarationSyntax)statementsInfo.Parent.Parent; SyntaxToken asyncKeyword = methodDeclaration.Modifiers.Find(SyntaxKind.AsyncKeyword); SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); string name = methodDeclaration.Identifier.ValueText; name = NameGenerator.Default.EnsureUniqueLocalName(name, semanticModel, statement.SpanStart, cancellationToken: cancellationToken); SyntaxList <StatementSyntax> statements = statementsInfo.Statements; int index = statements.IndexOf(statement); List <StatementSyntax> localFunctionStatements = statements.Skip(index).ToList(); localFunctionStatements[0] = localFunctionStatements[0].TrimLeadingTrivia(); LocalFunctionStatementSyntax localFunction = LocalFunctionStatement( (asyncKeyword.IsKind(SyntaxKind.AsyncKeyword)) ? TokenList(SyntaxKind.AsyncKeyword) : default,
protected LocalFunctionSymbol MakeLocalFunction(LocalFunctionStatementSyntax declaration) { return(new LocalFunctionSymbol( this, this.ContainingMemberOrLambda, declaration)); }
public LocalFunctionSymbol( Binder binder, Symbol containingSymbol, LocalFunctionStatementSyntax syntax) { _syntax = syntax; _containingSymbol = containingSymbol; _declarationModifiers = DeclarationModifiers.Private | DeclarationModifiers.Static | syntax.Modifiers.ToDeclarationModifiers(); var diagnostics = DiagnosticBag.GetInstance(); if (_syntax.TypeParameterList != null) { binder = new WithMethodTypeParametersBinder(this, binder); _typeParameters = MakeTypeParameters(diagnostics); } else { _typeParameters = ImmutableArray<TypeParameterSymbol>.Empty; } if (IsExtensionMethod) { diagnostics.Add(ErrorCode.ERR_BadExtensionAgg, Locations[0]); } _binder = binder; _refKind = (syntax.ReturnType.Kind() == SyntaxKind.RefType) ? RefKind.Ref : RefKind.None; _diagnostics = diagnostics.ToReadOnlyAndFree(); }
public LocalFunctionSymbol( Binder binder, Symbol containingSymbol, LocalFunctionStatementSyntax syntax) { _syntax = syntax; _containingSymbol = containingSymbol; _declarationDiagnostics = new DiagnosticBag(); _declarationModifiers = DeclarationModifiers.Private | syntax.Modifiers.ToDeclarationModifiers(diagnostics: _declarationDiagnostics); this.CheckUnsafeModifier(_declarationModifiers, _declarationDiagnostics); ScopeBinder = binder; binder = binder.WithUnsafeRegionIfNecessary(syntax.Modifiers); if (_syntax.TypeParameterList != null) { binder = new WithMethodTypeParametersBinder(this, binder); _typeParameters = MakeTypeParameters(_declarationDiagnostics); } else { _typeParameters = ImmutableArray <SourceMethodTypeParameterSymbol> .Empty; ReportErrorIfHasConstraints(_syntax.ConstraintClauses, _declarationDiagnostics); } if (IsExtensionMethod) { _declarationDiagnostics.Add(ErrorCode.ERR_BadExtensionAgg, Locations[0]); } foreach (var param in syntax.ParameterList.Parameters) { ReportAttributesDisallowed(param.AttributeLists, _declarationDiagnostics); } if (syntax.ReturnType.Kind() == SyntaxKind.RefType) { var returnType = (RefTypeSyntax)syntax.ReturnType; if (returnType.ReadOnlyKeyword.Kind() == SyntaxKind.ReadOnlyKeyword) { _refKind = RefKind.RefReadOnly; } else { _refKind = RefKind.Ref; } } else { _refKind = RefKind.None; } _binder = binder; }
private static Task <Document> RefactorAsync(Document document, LocalFunctionStatementSyntax localFunction, SemanticModel semanticModel, CancellationToken cancellationToken) { LocalFunctionStatementSyntax newNode = AwaitRemover.Visit(localFunction, semanticModel, cancellationToken); newNode = newNode.RemoveModifier(SyntaxKind.AsyncKeyword); return(document.ReplaceNodeAsync(localFunction, newNode, cancellationToken)); }
public static bool IsNoArgsSetter(this LocalFunctionStatementSyntax method) { var name = method.Identifier.Text; var isSetter = name.StartsWith("Set", StringComparison.OrdinalIgnoreCase); var noArgs = !method.ParameterList.Parameters.Any(); return(noArgs && isSetter); }
public static void RegisterRefactoring(RefactoringContext context, LocalFunctionStatementSyntax localFunctionStatement) { FileLinePositionSpan fileSpan = GetFileLinePositionSpan(localFunctionStatement, context.CancellationToken); context.RegisterRefactoring( $"Comment out {localFunctionStatement.GetTitle()}", cancellationToken => RefactorAsync(context.Document, fileSpan.StartLine(), fileSpan.EndLine(), cancellationToken)); }
private static SyntaxNode ConvertLocalFunctionToAsync(LocalFunctionStatementSyntax localFunction) { var token = localFunction.GetFirstToken(); return(localFunction .ReplaceToken(token, token.WithLeadingTrivia(TriviaList())) .AddModifiers(Token(token.LeadingTrivia, SyntaxKind.AsyncKeyword, TriviaList(Space))) .WithAdditionalAnnotations(Formatter.Annotation)); }
public override void VisitLocalFunctionStatement(LocalFunctionStatementSyntax node) { if (ViolatesRule(node)) { _localFunctionViolations.Add(node); } base.VisitLocalFunctionStatement(node); }
public static void RegisterRefactoring(RefactoringContext context, LocalFunctionStatementSyntax localFunctionStatement) { FileLinePositionSpan fileSpan = GetFileLinePositionSpan(localFunctionStatement, context.CancellationToken); context.RegisterRefactoring( $"Comment out {CSharpFacts.GetTitle(localFunctionStatement)}", ct => RefactorAsync(context.Document, fileSpan.StartLine(), fileSpan.EndLine(), ct), RefactoringDescriptors.CommentOutMemberDeclaration); }
internal static SyntaxNode WithoutAsyncModifier( LocalFunctionStatementSyntax localFunction, TypeSyntax returnType ) { var newModifiers = RemoveAsyncModifier(localFunction.Modifiers, ref returnType); return(localFunction.WithReturnType(returnType).WithModifiers(newModifiers)); }
internal static ModifierListInfo Create(LocalFunctionStatementSyntax localFunctionStatement) { if (localFunctionStatement == null) { return(Default); } return(new ModifierListInfo(localFunctionStatement, localFunctionStatement.Modifiers)); }
/// <summary> /// Returns a <see cref="LocalFunctionStatementSyntax"/> as a method definition. /// </summary> /// <param name="node">The input <see cref="LocalFunctionStatementSyntax"/> node.</param> /// <returns>A node like the one in input, but just as a definition.</returns> public static LocalFunctionStatementSyntax AsDefinition(this LocalFunctionStatementSyntax node) { if (node.ExpressionBody is ArrowExpressionClauseSyntax) { return(node.WithExpressionBody(null).WithSemicolonToken(Token(SyntaxKind.SemicolonToken))); } return(node.WithBody(null).WithSemicolonToken(Token(SyntaxKind.SemicolonToken))); }
private SyntaxNode FixLocalFunction( bool keepVoid, IMethodSymbol methodSymbol, LocalFunctionStatementSyntax localFunction, KnownTypes knownTypes) { var newReturnType = FixMethodReturnType(keepVoid, methodSymbol, localFunction.ReturnType, knownTypes); var newModifiers = AddAsyncModifierWithCorrectedTrivia(localFunction.Modifiers, ref newReturnType); return(localFunction.WithReturnType(newReturnType).WithModifiers(newModifiers)); }
private SyntaxNode FixLocalFunction( bool keepVoid, IMethodSymbol methodSymbol, LocalFunctionStatementSyntax localFunction, INamedTypeSymbol taskType, INamedTypeSymbol taskOfTType, INamedTypeSymbol valueTaskOfTType) { var newReturnType = FixMethodReturnType(keepVoid, methodSymbol, localFunction.ReturnType, taskType, taskOfTType, valueTaskOfTType); var newModifiers = AddAsyncModifierWithCorrectedTrivia(localFunction.Modifiers, ref newReturnType); return(localFunction.WithReturnType(newReturnType).WithModifiers(newModifiers)); }
public sealed override SyntaxNode VisitLocalFunctionStatement(LocalFunctionStatementSyntax node) { if (RewritingSyntaxKind.HasValue) { return(node); } RewritingSyntaxKind = node.Kind(); return(OnVisitLocalFunctionStatement(node)); }
internal static GenericInfo Create(LocalFunctionStatementSyntax localFunctionStatement) { if (localFunctionStatement == null) { return(Default); } return(new GenericInfo(localFunctionStatement)); }
public static bool CanRefactor(LocalFunctionStatementSyntax localFunctionStatement) { if (localFunctionStatement == null) { throw new ArgumentNullException(nameof(localFunctionStatement)); } return(localFunctionStatement.ExpressionBody == null && GetExpression(localFunctionStatement.Body) != null); }
public override void VisitLocalFunctionStatement(LocalFunctionStatementSyntax node) { var body = (CSharpSyntaxNode)node.Body ?? node.ExpressionBody; LocalFunctionSymbol match = null; // Don't use LookupLocalFunction because it recurses up the tree, as it // should be defined in the directly enclosing block (see note below) Binder possibleScopeBinder = _enclosing; while (possibleScopeBinder != null && !possibleScopeBinder.IsLocalFunctionsScopeBinder) { possibleScopeBinder = possibleScopeBinder.Next; } if (possibleScopeBinder != null) { foreach (var candidate in possibleScopeBinder.LocalFunctions) { if (candidate.Locations[0] == node.Identifier.GetLocation()) { match = candidate; } } } bool oldSawYield = _sawYield; _sawYield = false; if (match != null) { var oldMethod = _containingMemberOrLambda; _containingMemberOrLambda = match; if (body != null) { Binder binder = match.IsGenericMethod ? new WithMethodTypeParametersBinder(match, _enclosing) : _enclosing; binder = binder.WithUnsafeRegionIfNecessary(node.Modifiers); Visit(body, new InMethodBinder(match, binder)); } _containingMemberOrLambda = oldMethod; } else { // The enclosing block should have found this node and created a LocalFunctionMethodSymbol // The code that does so is in LocalScopeBinder.BuildLocalFunctions if (body != null) { // do our best to attempt to bind Visit(body); } } if (_sawYield) { _methodsWithYields.Add(body); } _sawYield = oldSawYield; }
public override ISymbol GetDeclaredSymbol(LocalFunctionStatementSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken)) { var boundLocalFunction = GetLowerBoundNode(declarationSyntax) as BoundLocalFunctionStatement; return boundLocalFunction?.Symbol; }
private static double ComputeWeightedDistanceOfLocalFunctions(LocalFunctionStatementSyntax leftNode, LocalFunctionStatementSyntax rightNode) { double modifierDistance = ComputeDistance(leftNode.Modifiers, rightNode.Modifiers); double returnTypeDistance = ComputeDistance(leftNode.ReturnType, rightNode.ReturnType); double identifierDistance = ComputeDistance(leftNode.Identifier, rightNode.Identifier); double typeParameterDistance = ComputeDistance(leftNode.TypeParameterList, rightNode.TypeParameterList); double parameterDistance = ComputeDistance(leftNode.ParameterList.Parameters, rightNode.ParameterList.Parameters); double bodyDistance = ComputeDistance((SyntaxNode)leftNode.Body ?? leftNode.ExpressionBody, (SyntaxNode)rightNode.Body ?? rightNode.ExpressionBody); return modifierDistance * 0.1 + returnTypeDistance * 0.1 + identifierDistance * 0.2 + typeParameterDistance * 0.2 + parameterDistance * 0.2 + bodyDistance * 0.2; }
/// <summary> /// Given a local function declaration syntax, get the corresponding symbol. /// </summary> /// <param name="declarationSyntax">The syntax node that declares a member.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The symbol that was declared.</returns> public abstract ISymbol GetDeclaredSymbol(LocalFunctionStatementSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken));
private BoundStatement BindLocalFunctionStatementParts(LocalFunctionStatementSyntax node, DiagnosticBag diagnostics) { // already defined symbol in containing block var localSymbol = this.LookupLocalFunction(node.Identifier); var hasErrors = false; // In error scenarios with misplaced code, it is possible we can't bind the local declaration. // This occurs through the semantic model. In that case concoct a plausible result. if (localSymbol == null) { localSymbol = new LocalFunctionSymbol(this, this.ContainingMemberOrLambda, node); } else { hasErrors |= this.ValidateDeclarationNameConflictsInScope(localSymbol, diagnostics); } BoundBlock block; if (node.Body != null) { block = BindEmbeddedBlock(node.Body, diagnostics); } else if (node.ExpressionBody != null) { block = BindExpressionBodyAsBlock(node.ExpressionBody, diagnostics); } else { block = null; hasErrors = true; // TODO: add a message for this? diagnostics.Add(ErrorCode.ERR_ConcreteMissingBody, localSymbol.Locations[0], localSymbol); } if (block != null) { localSymbol.ComputeReturnType(); // Have to do ControlFlowPass here because in MethodCompiler, we don't call this for synthed methods // rather we go directly to LowerBodyOrInitializer, which skips over flow analysis (which is in CompileMethod) // (the same thing - calling ControlFlowPass.Analyze in the lowering - is done for lambdas) // It's a bit of code duplication, but refactoring would make things worse. var endIsReachable = ControlFlowPass.Analyze(localSymbol.DeclaringCompilation, localSymbol, block, diagnostics); if (endIsReachable) { if (ImplicitReturnIsOkay(localSymbol)) { block = FlowAnalysisPass.AppendImplicitReturn(block, localSymbol, node.Body); } else { diagnostics.Add(ErrorCode.ERR_ReturnExpected, localSymbol.Locations[0], localSymbol); } } } localSymbol.GrabDiagnostics(diagnostics); return new BoundLocalFunctionStatement(node, localSymbol, block, hasErrors); }
public override void VisitLocalFunctionStatement(LocalFunctionStatementSyntax node) { var body = (CSharpSyntaxNode)node.Body ?? node.ExpressionBody; LocalFunctionSymbol match = null; // Don't use LookupLocalFunction because it recurses up the tree, as it // should be defined in the directly enclosing block (see note below) foreach (var candidate in _enclosing.LocalFunctions) { if (candidate.Locations[0] == node.Identifier.GetLocation()) { match = candidate; } } bool oldSawYield = _sawYield; _sawYield = false; if (match != null) { var oldMethod = _method; _method = match; Binder addToMap; if (match.IsGenericMethod) { addToMap = new WithMethodTypeParametersBinder(match, _enclosing); } else { addToMap = _enclosing; } addToMap = new InMethodBinder(match, addToMap); AddToMap(node, addToMap); if (body != null) { Visit(body, addToMap); } _method = oldMethod; } else { // The enclosing block should have found this node and created a LocalFunctionMethodSymbol // The code that does so is in LocalScopeBinder.BuildLocalFunctions if (body != null) { // do our best to attempt to bind Visit(body); } } if (_sawYield) { _methodsWithYields.Add(node); } _sawYield = oldSawYield; }
/// <summary> /// Given a local function declaration syntax, get the corresponding symbol. /// </summary> /// <param name="declarationSyntax">The syntax node that declares a member.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The symbol that was declared.</returns> public override ISymbol GetDeclaredSymbol(LocalFunctionStatementSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken)) { CheckSyntaxNode(declarationSyntax); return this.GetMemberModel(declarationSyntax)?.GetDeclaredSymbol(declarationSyntax, cancellationToken); }
private BoundStatement BindLocalFunctionStatement(LocalFunctionStatementSyntax node, DiagnosticBag diagnostics) { var binder = GetBinder(node); Debug.Assert(binder != null); return binder.BindLocalFunctionStatementParts(node, diagnostics); }
private BoundStatement BindLocalFunctionStatement(LocalFunctionStatementSyntax node, DiagnosticBag diagnostics) { // already defined symbol in containing block var localSymbol = this.LookupLocalFunction(node.Identifier); var hasErrors = localSymbol.ScopeBinder .ValidateDeclarationNameConflictsInScope(localSymbol, diagnostics); BoundBlock block; if (node.Body != null) { block = BindEmbeddedBlock(node.Body, diagnostics); } else if (node.ExpressionBody != null) { block = BindExpressionBodyAsBlock(node.ExpressionBody, diagnostics); } else { block = null; hasErrors = true; // TODO(https://github.com/dotnet/roslyn/issues/14900): Better error message diagnostics.Add(ErrorCode.ERR_ConcreteMissingBody, localSymbol.Locations[0], localSymbol); } if (block != null) { localSymbol.ComputeReturnType(); // Have to do ControlFlowPass here because in MethodCompiler, we don't call this for synthed methods // rather we go directly to LowerBodyOrInitializer, which skips over flow analysis (which is in CompileMethod) // (the same thing - calling ControlFlowPass.Analyze in the lowering - is done for lambdas) // It's a bit of code duplication, but refactoring would make things worse. var endIsReachable = ControlFlowPass.Analyze(localSymbol.DeclaringCompilation, localSymbol, block, diagnostics); if (endIsReachable) { if (ImplicitReturnIsOkay(localSymbol)) { block = FlowAnalysisPass.AppendImplicitReturn(block, localSymbol, node.Body); } else { diagnostics.Add(ErrorCode.ERR_ReturnExpected, localSymbol.Locations[0], localSymbol); } } } localSymbol.GrabDiagnostics(diagnostics); return new BoundLocalFunctionStatement(node, localSymbol, block, hasErrors); }