public static DynamicAnalysisInjector TryCreate( MethodSymbol method, BoundStatement methodBody, SyntheticBoundNodeFactory methodBodyFactory, DiagnosticBag diagnostics, DebugDocumentProvider debugDocumentProvider, Instrumenter previous) { // Do not instrument implicitly-declared methods, except for constructors. // Instrument implicit constructors in order to instrument member initializers. if (method.IsImplicitlyDeclared && !method.IsImplicitConstructor) { return(null); } // Do not instrument methods marked with or in scope of ExcludeFromCodeCoverageAttribute. if (IsExcludedFromCodeCoverage(method)) { return(null); } MethodSymbol createPayloadForMethodsSpanningSingleFile = GetCreatePayloadOverload( methodBodyFactory.Compilation, WellKnownMember.Microsoft_CodeAnalysis_Runtime_Instrumentation__CreatePayloadForMethodsSpanningSingleFile, methodBody.Syntax, diagnostics); MethodSymbol createPayloadForMethodsSpanningMultipleFiles = GetCreatePayloadOverload( methodBodyFactory.Compilation, WellKnownMember.Microsoft_CodeAnalysis_Runtime_Instrumentation__CreatePayloadForMethodsSpanningMultipleFiles, methodBody.Syntax, diagnostics); // Do not instrument any methods if CreatePayload is not present. if ((object)createPayloadForMethodsSpanningSingleFile == null || (object)createPayloadForMethodsSpanningMultipleFiles == null) { return(null); } // Do not instrument CreatePayload if it is part of the current compilation (which occurs only during testing). // CreatePayload will fail at run time with an infinite recursion if it is instrumented. if (method.Equals(createPayloadForMethodsSpanningSingleFile) || method.Equals(createPayloadForMethodsSpanningMultipleFiles)) { return(null); } return(new DynamicAnalysisInjector( method, methodBody, methodBodyFactory, createPayloadForMethodsSpanningSingleFile, createPayloadForMethodsSpanningMultipleFiles, diagnostics, debugDocumentProvider, previous)); }
internal Microsoft.Cci.IMethodReference Translate(MethodSymbol methodSymbol, bool needDeclaration) { object reference; Microsoft.Cci.IMethodReference methodRef; NamedTypeSymbol container = methodSymbol.ContainingType; System.Diagnostics.Debug.Assert(ReferenceEquals(methodSymbol, methodSymbol.OriginalDefinition) || !methodSymbol.Equals(methodSymbol.OriginalDefinition)); if (!ReferenceEquals(methodSymbol.OriginalDefinition, methodSymbol)) { System.Diagnostics.Debug.Assert(!needDeclaration); return(methodSymbol); } else if (!needDeclaration) { bool methodIsGeneric = methodSymbol.IsGeneric; bool typeIsGeneric = IsGenericType(container); if (methodIsGeneric || typeIsGeneric) { if (genericInstanceMap.TryGetValue(methodSymbol, out reference)) { return((Microsoft.Cci.IMethodReference)reference); } if (methodIsGeneric) { if (typeIsGeneric) { // Specialized and generic instance at the same time. throw new NotImplementedException(); } else { methodRef = new GenericMethodInstanceReference(methodSymbol); } } else { System.Diagnostics.Debug.Assert(typeIsGeneric); methodRef = new SpecializedMethodReference(methodSymbol); } genericInstanceMap.Add(methodSymbol, methodRef); return(methodRef); } } return(methodSymbol); }
public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node) { MethodSymbol visitedMethodSymbol = model.GetDeclaredSymbol(node, this.cancellationToken) as MethodSymbol; // If this is the rewritten method, redeclare it to be static, and replace class references with new parameter within body if (visitedMethodSymbol != null && visitedMethodSymbol.Equals(this.methodSymbol)) { // Get type that the method is declared in NamedTypeSymbol containingType = this.methodSymbol.ContainingType; // Add whitespace before first modifier SyntaxToken firstToken = node.GetFirstToken(); SyntaxTriviaList leadingTrivia = firstToken.LeadingTrivia; MethodDeclarationSyntax newMethodDeclaration = node.ReplaceToken(firstToken, firstToken.WithLeadingTrivia(Syntax.Whitespace(" "))); // Add `static' modifier keyword at the first place SyntaxToken staticKeyword = Syntax.Token(SyntaxKind.StaticKeyword) .WithLeadingTrivia(leadingTrivia); newMethodDeclaration = newMethodDeclaration .WithModifiers(newMethodDeclaration.Modifiers.Insert(0, staticKeyword)); // Introduce new parameter of method's container type SyntaxToken newParameterNameToken = Syntax.Identifier("self"); IdentifierNameSyntax newParameterName = Syntax.IdentifierName(newParameterNameToken); TypeSyntax containingTypeSyntax = Syntax.ParseTypeName(containingType.ToMinimalDisplayString(node.ParameterList.GetLocation(), model)); ParameterSyntax newParameterNode = Syntax.Parameter(newParameterNameToken) .WithType(containingTypeSyntax); SeparatedSyntaxList <ParameterSyntax> parametersList = newMethodDeclaration.ParameterList.Parameters.Insert(0, newParameterNode); ParameterListSyntax parameters = Syntax.ParameterList(parametersList).WithAdditionalAnnotations(CodeAnnotations.Formatting); newMethodDeclaration = newMethodDeclaration.WithParameterList(parameters); // Process the methods body to update all references to itself and containing type's members NameQualifier nameQualifier = new NameQualifier(model, containingType, methodSymbol, newParameterNameToken, cancellationToken); BlockSyntax processedBody = (BlockSyntax)nameQualifier.Visit(node.Body); // Replace the body with the processed one newMethodDeclaration = newMethodDeclaration.WithBody(processedBody); return(newMethodDeclaration); } else { // Otherwise continue with visiting its children, to replace methods invocations return(base.VisitMethodDeclaration(node)); } }
public static DynamicAnalysisInjector TryCreate(MethodSymbol method, BoundStatement methodBody, SyntheticBoundNodeFactory methodBodyFactory, DiagnosticBag diagnostics, DebugDocumentProvider debugDocumentProvider, Instrumenter previous) { // Do not instrument implicitly-declared methods. if (!method.IsImplicitlyDeclared) { MethodSymbol createPayload = GetCreatePayload(methodBodyFactory.Compilation, methodBody.Syntax, diagnostics); // Do not instrument any methods if CreatePayload is not present. // Do not instrument CreatePayload if it is part of the current compilation (which occurs only during testing). // CreatePayload will fail at run time with an infinite recursion if it Is instrumented. if ((object)createPayload != null && !method.Equals(createPayload)) { return(new DynamicAnalysisInjector(method, methodBody, methodBodyFactory, createPayload, diagnostics, debugDocumentProvider, previous)); } } return(null); }
internal Microsoft.Cci.IMethodReference Translate(MethodSymbol methodSymbol, bool needDeclaration) { object reference; Microsoft.Cci.IMethodReference methodRef; NamedTypeSymbol container = methodSymbol.ContainingType; System.Diagnostics.Debug.Assert(ReferenceEquals(methodSymbol, methodSymbol.OriginalDefinition) || !methodSymbol.Equals(methodSymbol.OriginalDefinition)); if (!ReferenceEquals(methodSymbol.OriginalDefinition, methodSymbol)) { System.Diagnostics.Debug.Assert(!needDeclaration); return methodSymbol; } else if (!needDeclaration) { bool methodIsGeneric = methodSymbol.IsGeneric; bool typeIsGeneric = IsGenericType(container); if (methodIsGeneric || typeIsGeneric) { if (genericInstanceMap.TryGetValue(methodSymbol, out reference)) { return (Microsoft.Cci.IMethodReference)reference; } if (methodIsGeneric) { if (typeIsGeneric) { // Specialized and generic instance at the same time. throw new NotImplementedException(); } else { methodRef = new GenericMethodInstanceReference(methodSymbol); } } else { System.Diagnostics.Debug.Assert(typeIsGeneric); methodRef = new SpecializedMethodReference(methodSymbol); } genericInstanceMap.Add(methodSymbol, methodRef); return methodRef; } } return methodSymbol; }
public override SyntaxNode VisitInvocationExpression(InvocationExpressionSyntax node) { ExpressionSyntax expression = node.Expression; CommonSymbolInfo methodSymbolInfo = this.model.GetSymbolInfo(expression); MethodSymbol visitedMethodSymbol = methodSymbolInfo.Symbol as MethodSymbol; // Verify does the invocation refer to searched method if (visitedMethodSymbol != null && visitedMethodSymbol.Equals(this.methodSymbol)) { if (expression.Kind == SyntaxKind.MemberAccessExpression) { MemberAccessExpressionSyntax memberAccess = (MemberAccessExpressionSyntax)expression; // Move all from the beginning (except for the method name) to parameter // Considers: // a.b.foo(47); -> B.foo(a.b, 47); ArgumentListSyntax argumentsList = node.ArgumentList; ArgumentSyntax newArgument = Syntax.Argument(memberAccess.Expression); SeparatedSyntaxList <ArgumentSyntax> arguments = argumentsList.Arguments.Insert(0, newArgument); argumentsList = Syntax.ArgumentList(arguments).WithAdditionalAnnotations(CodeAnnotations.Formatting); InvocationExpressionSyntax newInvocation = node.WithArgumentList(argumentsList); // Replace invocation expression with qualified (class) name TypeSyntax typeSyntax = Syntax.ParseTypeName(this.methodSymbol.ContainingType.ToMinimalDisplayString(expression.GetLocation(), this.model)) .WithLeadingTrivia(memberAccess.Expression.GetLeadingTrivia()); newInvocation = newInvocation.WithExpression(Syntax.MemberAccessExpression(SyntaxKind.MemberAccessExpression, typeSyntax, memberAccess.Name)); return(newInvocation); } else if (expression.Kind == SyntaxKind.IdentifierName) { IdentifierNameSyntax identifierName = (IdentifierNameSyntax)expression; // Unqualified reference, `this' should be passed as first parameter // Considers: // foo(47); -> B.foo(this, 47); ArgumentListSyntax argumentsList = node.ArgumentList; ArgumentSyntax newArgument = Syntax.Argument(Syntax.ThisExpression()); SeparatedSyntaxList <ArgumentSyntax> arguments = argumentsList.Arguments.Insert(0, newArgument); argumentsList = Syntax.ArgumentList(arguments).WithAdditionalAnnotations(CodeAnnotations.Formatting); InvocationExpressionSyntax newInvocation = node.WithArgumentList(argumentsList); // Replace invocation expression with qualified (class) name TypeSyntax typeSyntax = Syntax.ParseTypeName(this.methodSymbol.ContainingType.ToMinimalDisplayString(expression.GetLocation(), this.model)) .WithLeadingTrivia(identifierName.GetLeadingTrivia()); newInvocation = newInvocation.WithExpression(Syntax.MemberAccessExpression(SyntaxKind.MemberAccessExpression, typeSyntax, identifierName)); return(newInvocation); } } return(base.VisitInvocationExpression(node)); }