Пример #1
0
        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));
        }
Пример #2
0
        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);
                    }
                }
            }
        }
Пример #3
0
        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());
        }
Пример #4
0
        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));
        }
Пример #6
0
        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));
        }
Пример #7
0
        public static bool IsVoidGetter(this LocalFunctionStatementSyntax method)
        {
            var name     = method.Identifier.Text;
            var isGetter = name.StartsWith("Get", StringComparison.OrdinalIgnoreCase);

            return(method.IsVoid() && isGetter);
        }
Пример #8
0
 public override void VisitLocalFunctionStatement(LocalFunctionStatementSyntax node)
 {
     Visit(node.ParameterList);
     VisitType(node.ReturnType);
     VisitBodyOrExpressionBody(node.Body, node.ExpressionBody);
     //base.VisitLocalFunctionStatement(node);
 }
Пример #9
0
        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);
        }
Пример #10
0
        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,
Пример #12
0
        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));
        }
Пример #13
0
 /// <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));
 }
Пример #14
0
        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,
Пример #15
0
 protected LocalFunctionSymbol MakeLocalFunction(LocalFunctionStatementSyntax declaration)
 {
     return(new LocalFunctionSymbol(
                this,
                this.ContainingMemberOrLambda,
                declaration));
 }
Пример #16
0
        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();
        }
Пример #17
0
        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;
        }
Пример #18
0
        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));
        }
Пример #19
0
        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);
        }
Пример #20
0
        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));
        }
Пример #21
0
        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);
            }
Пример #23
0
        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);
        }
Пример #24
0
        internal static SyntaxNode WithoutAsyncModifier(
            LocalFunctionStatementSyntax localFunction,
            TypeSyntax returnType
            )
        {
            var newModifiers = RemoveAsyncModifier(localFunction.Modifiers, ref returnType);

            return(localFunction.WithReturnType(returnType).WithModifiers(newModifiers));
        }
Пример #25
0
        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)));
    }
Пример #27
0
        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));
        }
Пример #29
0
 public sealed override SyntaxNode VisitLocalFunctionStatement(LocalFunctionStatementSyntax node)
 {
     if (RewritingSyntaxKind.HasValue)
     {
         return(node);
     }
     RewritingSyntaxKind = node.Kind();
     return(OnVisitLocalFunctionStatement(node));
 }
Пример #30
0
        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);
        }
Пример #32
0
        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;
        }
Пример #33
0
 public override ISymbol GetDeclaredSymbol(LocalFunctionStatementSyntax declarationSyntax, CancellationToken cancellationToken = default(CancellationToken))
 {
     var boundLocalFunction = GetLowerBoundNode(declarationSyntax) as BoundLocalFunctionStatement;
     return boundLocalFunction?.Symbol;
 }
Пример #34
0
        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;
        }
Пример #35
0
 /// <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));
Пример #36
0
        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);
        }
Пример #37
0
        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;
        }
Пример #38
0
        /// <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);
        }
Пример #39
0
        private BoundStatement BindLocalFunctionStatement(LocalFunctionStatementSyntax node, DiagnosticBag diagnostics)
        {
            var binder = GetBinder(node);
            Debug.Assert(binder != null);

            return binder.BindLocalFunctionStatementParts(node, diagnostics);
        }
Пример #40
0
        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);
        }