/// <summary> /// Normalizes the <paramref name="methodDeclaration" />. /// </summary> protected override SyntaxNode Normalize(MethodDeclarationSyntax methodDeclaration) { // Nothing to do here for methods without expression bodies if (methodDeclaration.ExpressionBody == null) return methodDeclaration; var methodSymbol = methodDeclaration.GetMethodSymbol(SemanticModel); StatementSyntax statementBody; if (methodSymbol.ReturnsVoid) statementBody = (StatementSyntax)Syntax.ExpressionStatement(methodDeclaration.ExpressionBody.Expression); else statementBody = (StatementSyntax)Syntax.ReturnStatement(methodDeclaration.ExpressionBody.Expression); return methodDeclaration.WithExpressionBody(null).WithBody(SyntaxFactory.Block(statementBody).NormalizeWhitespace()); }
/// <summary> /// Normalizes the <paramref name="declaration" />. /// </summary> public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax declaration) { // Nothing to do here for methods without expression bodies if (declaration.ExpressionBody == null) return declaration; // Nothing to do here for methods not defined in fault effects or for methods that are no overrides of some port var methodSymbol = declaration.GetMethodSymbol(SemanticModel); if (!methodSymbol.ContainingType.IsFaultEffect(SemanticModel) || !methodSymbol.IsOverride) return declaration; var originalDeclaration = declaration; var statements = AsStatementBody(methodSymbol, declaration.ExpressionBody.Expression); declaration = declaration.WithSemicolonToken(default(SyntaxToken)).WithExpressionBody(null); return declaration.WithBody(statements).EnsureLineCount(originalDeclaration); }
/// <summary> /// Normalizes the <paramref name="declaration" />. /// </summary> public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax declaration) { _methodSymbol = declaration.GetMethodSymbol(SemanticModel); if (!_methodSymbol.ContainingType.IsComponent(SemanticModel) || !_methodSymbol.IsRequiredPort(SemanticModel)) return declaration; var body = CreateBindingCode(); var originalDeclaration = declaration; var index = declaration.Modifiers.IndexOf(SyntaxKind.ExternKeyword); var delegateFieldName = Syntax.LiteralExpression(GetBindingDelegateFieldName()); var infoFieldName = Syntax.LiteralExpression(GetBinderFieldName()); var defaultMethod = Syntax.LiteralExpression(GetUnboundPortAssignmentMethodName()); declaration = declaration.WithModifiers(declaration.Modifiers.RemoveAt(index)).WithSemicolonToken(default(SyntaxToken)); declaration = (MethodDeclarationSyntax)Syntax.AddAttribute<DebuggerHiddenAttribute>(declaration); declaration = (MethodDeclarationSyntax)Syntax.AddAttribute<BindingMetadataAttribute>(declaration, delegateFieldName, infoFieldName, defaultMethod); return declaration.WithBody(body).EnsureLineCount(originalDeclaration); }
/// <summary> /// Creates a delegate declaration that is compatible with <paramref name="methodDeclaration" />. /// </summary> /// <param name="methodDeclaration">The declaration of the method the delegate should be created for.</param> private DelegateDeclarationSyntax CreateDelegate(MethodDeclarationSyntax methodDeclaration) { var methodSymbol = methodDeclaration.GetMethodSymbol(SemanticModel); var methodDelegate = methodSymbol.GetSynthesizedDelegateDeclaration(GetDelegateName()); methodDelegate = methodDelegate.AddAttributeLists(_compilerGeneratedAttribute); return methodDelegate; }
/// <summary> /// Normalizes the <paramref name="methodDeclaration" />. /// </summary> public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax methodDeclaration) { var methodSymbol = methodDeclaration.GetMethodSymbol(SemanticModel); if (methodSymbol.IsRequiredPort(SemanticModel)) return NormalizeExternMethod(methodDeclaration); if (methodSymbol.IsProvidedPort(SemanticModel)) return NormalizeMethod(methodDeclaration, typeof(ProvidedAttribute)); if (methodSymbol.IsUpdateMethod(SemanticModel) && methodSymbol.ContainingType.IsDerivedFromComponent(Compilation)) return NormalizeMethod(methodDeclaration); return methodDeclaration; }
/// <summary> /// Normalizes the <paramref name="declaration" />. /// </summary> public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax declaration) { var originalDeclaration = declaration; var methodSymbol = declaration.GetMethodSymbol(SemanticModel); if (!methodSymbol.ContainingType.IsFaultEffect(SemanticModel) || !methodSymbol.IsOverride) return declaration; var memberAccess = Syntax.MemberAccessExpression(Syntax.BaseExpression(), methodSymbol.Name); var invocation = Syntax.InvocationExpression(memberAccess, CreateInvocationArguments(methodSymbol.Parameters)); declaration = declaration.WithBody(CreateBody(methodSymbol, declaration.Body, invocation)); return declaration.EnsureLineCount(originalDeclaration); }
/// <summary> /// Normalizes the <paramref name="methodDeclaration" />. /// </summary> /// <param name="methodDeclaration">The method declaration that should be normalized.</param> public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax methodDeclaration) { if (!methodDeclaration.RequiresBoundTreeGeneration(SemanticModel)) return methodDeclaration; var methodSymbol = methodDeclaration.GetMethodSymbol(SemanticModel); var methodBody = _implementationMethods[GetMethodKey(methodSymbol)]; var metadataMethodName = (methodDeclaration.Identifier.ValueText + "MethodBody" + _methodCount++).ToSynthesized(); var metadataMethod = Syntax.MethodDeclaration( name: metadataMethodName, returnType: Syntax.TypeExpression(Compilation.GetTypeSymbol<MethodBodyMetadata>()), accessibility: Accessibility.Private, statements: methodBody.Statements); var suppressAttribute = Syntax.Attribute(typeof(SuppressTransformationAttribute).FullName); var compilerGeneratedAttribute = Syntax.Attribute(typeof(CompilerGeneratedAttribute).FullName); metadataMethod = Syntax.AddAttributes(metadataMethod, suppressAttribute, compilerGeneratedAttribute); AddMembers(methodSymbol.ContainingType, (MethodDeclarationSyntax)metadataMethod); var metadataAttribute = Syntax.Attribute(typeof(MethodBodyMetadataAttribute).FullName, Syntax.LiteralExpression(metadataMethodName)); return Syntax.AddAttributes(methodDeclaration, metadataAttribute); }
/// <summary> /// Normalizes the <paramref name="methodDeclaration" />. /// </summary> protected override SyntaxNode Normalize(MethodDeclarationSyntax methodDeclaration) { var returnCount = methodDeclaration.Descendants<ReturnStatementSyntax>().Count(); // If there is no return statement within the method's body, there's nothing to do if (returnCount == 0) return methodDeclaration; // If there is only one return and it is the last method body's last statement, there's nothing to do if (returnCount == 1 && methodDeclaration.Body.Statements[methodDeclaration.Body.Statements.Count - 1] is ReturnStatementSyntax) return methodDeclaration; // Otherwise, we have to normalize the method var nameScope = methodDeclaration.GetNameScope(SemanticModel, includeLocals: true); var symbol = methodDeclaration.GetMethodSymbol(SemanticModel); _returnsValue = !symbol.ReturnsVoid; _hasReturnedVariable = SyntaxFactory.IdentifierName(nameScope.MakeUnique("hasReturned")); _returnValueVariable = _returnsValue ? SyntaxFactory.IdentifierName(nameScope.MakeUnique("returnValue")) : null; var rewriter = new Rewriter(Syntax, _hasReturnedVariable); methodDeclaration = (MethodDeclarationSyntax)rewriter.Visit(methodDeclaration); methodDeclaration = (MethodDeclarationSyntax)base.Normalize(methodDeclaration); // Generate the declarations for the local variables var hasReturnedLocal = Syntax.LocalDeclarationStatement(Syntax.TypeExpression<bool>(SemanticModel), _hasReturnedVariable.Identifier.ValueText, Syntax.FalseLiteralExpression()); var statements = methodDeclaration.Body.Statements.Insert(0, (StatementSyntax)hasReturnedLocal); if (_returnsValue) { var returnValueLocal = Syntax.LocalDeclarationStatement(symbol.ReturnType, _returnValueVariable.Identifier.ValueText); statements = statements.Insert(0, (StatementSyntax)returnValueLocal); // If the method returns a value, add the final return statement, which by now is the only one within the entire method body statements = statements.Add((StatementSyntax)Syntax.ReturnStatement(_returnValueVariable)); } return methodDeclaration.WithBody(SyntaxFactory.Block(statements)).NormalizeWhitespace(); }