private SyntaxNode VisitQueryMethodLambdaExpresssion(LambdaExpressionSyntax lambda) { queryMethodCtx.Current.InLambdaExpression = true; SyntaxNode res; if (queryMethodCtx.Current.IsDynamicMethod) { //注意处理行差 var args = new SeparatedSyntaxList <ArgumentSyntax>(); if (lambda.Body is AnonymousObjectCreationExpressionSyntax aoc) { //转换Lambda表达式为运行时Lambda表达式 //eg: t=>new {t.Id, t.Name} 转换为 r=> new {Id=r.GetInt(0), Name=r.GetString(1)} var sb = StringBuilderCache.Acquire(); sb.Append("r => new {"); for (int i = 0; i < aoc.Initializers.Count; i++) { if (i != 0) { sb.Append(','); } var initializer = aoc.Initializers[i]; if (initializer.NameEquals != null) { sb.Append(initializer.NameEquals.Name.Identifier.ValueText); } else { sb.Append(((MemberAccessExpressionSyntax)initializer.Expression).Name.Identifier.ValueText); } sb.Append("=r.Get"); var expSymbol = SemanticModel.GetSymbolInfo(initializer.Expression).Symbol; var expType = TypeHelper.GetSymbolType(expSymbol); var typeString = TypeHelper.GetEntityMemberTypeString(expType, out bool isNullable); if (isNullable) { sb.Append("Nullable"); } sb.Append(typeString); sb.Append('('); sb.Append(i); sb.Append(')'); } sb.Append('}'); //转换为参数并加入参数列表 args = args.Add(SyntaxFactory.Argument( SyntaxFactory.ParseExpression(StringBuilderCache.GetStringAndRelease(sb)) )); //处理selectItems参数 for (int i = 0; i < aoc.Initializers.Count; i++) { var initializer = aoc.Initializers[i]; var argExpression = (ExpressionSyntax)initializer.Expression.Accept(this); if (initializer.NameEquals != null) //TODO:***检查是否还需要转换为SelectAs("XXX"),因前面已按序号获取 { var selectAsMethodName = (SimpleNameSyntax)SyntaxFactory.ParseName("SelectAs"); var selectAsMethod = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, argExpression, selectAsMethodName); var selectAsArgs = SyntaxFactory.ParseArgumentList(string.Format("(\"{0}\")", initializer.NameEquals.Name.Identifier.ValueText)); argExpression = SyntaxFactory.InvocationExpression(selectAsMethod, selectAsArgs); } var arg = SyntaxFactory.Argument(argExpression); //最后一个参数补body所有行差 if (i == aoc.Initializers.Count - 1) { var lineSpan = lambda.Body.GetLocation().GetLineSpan(); var lineDiff = lineSpan.EndLinePosition.Line - lineSpan.StartLinePosition.Line; if (lineDiff > 0) { arg = arg.WithTrailingTrivia(SyntaxFactory.Whitespace(new string('\n', lineDiff))); } } args = args.Add(arg); } } else if (lambda.Body is MemberAccessExpressionSyntax ma) { //转换Lambda表达式为运行时Lambda表达式 //eg: t=> t.Name 转换为 r=> r.GetString(0) var sb = StringBuilderCache.Acquire(); sb.Append("r => r.Get"); var expSymbol = SemanticModel.GetSymbolInfo(ma).Symbol; var expType = TypeHelper.GetSymbolType(expSymbol); var typeString = TypeHelper.GetEntityMemberTypeString(expType, out bool isNullable); if (isNullable) { sb.Append("Nullable"); } sb.Append(typeString); sb.Append("(0)"); //转换为参数并加入参数列表 args = args.Add(SyntaxFactory.Argument( SyntaxFactory.ParseExpression(StringBuilderCache.GetStringAndRelease(sb)) )); //处理selectItems参数 var argExpression = (ExpressionSyntax)ma.Accept(this); args = args.Add(SyntaxFactory.Argument(argExpression).WithTriviaFrom(ma)); } else { throw new NotImplementedException($"动态查询方法的第一个参数[{lambda.Body.GetType().Name}]暂未实现"); } res = SyntaxFactory.ArgumentList(args); } else if (queryMethodCtx.Current.MethodName == TypeHelper.SqlQueryToScalarMethod) { var args = new SeparatedSyntaxList <ArgumentSyntax>(); var argExpression = (ExpressionSyntax)lambda.Body.Accept(this); var arg = SyntaxFactory.Argument(argExpression); args = args.Add(arg); res = SyntaxFactory.ArgumentList(args); } else { res = Visit(lambda.Body); } queryMethodCtx.Current.InLambdaExpression = false; return(res); }
public override async Task RegisterCodeFixesAsync(CodeFixContext context) { var diagnostic = context.Diagnostics.First(); var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); var syntaxNode = (ExpressionSyntax)root.FindNode(diagnostic.Location.SourceSpan, getInnermostNodeForTie: true); var container = Utils.GetContainingFunction(syntaxNode); if (container.BlockOrExpression == null) { return; } var semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false); var enclosingSymbol = semanticModel.GetEnclosingSymbol(diagnostic.Location.SourceSpan.Start, context.CancellationToken); if (enclosingSymbol == null) { return; } bool convertToAsync = !container.IsAsync && Utils.HasAsyncCompatibleReturnType(enclosingSymbol as IMethodSymbol); if (convertToAsync) { // We don't support this yet, and we don't want to take the sync method path in this case. // The user will have to fix this themselves. return; } Regex lookupKey = (container.IsAsync || convertToAsync) ? CommonInterest.FileNamePatternForMethodsThatSwitchToMainThread : CommonInterest.FileNamePatternForMethodsThatAssertMainThread; string[] options = diagnostic.Properties[lookupKey.ToString()].Split('\n'); if (options.Length > 0) { // For any symbol lookups, we want to consider the position of the very first statement in the block. int positionForLookup = container.BlockOrExpression.GetLocation().SourceSpan.Start + 1; var cancellationTokenSymbol = new Lazy <ISymbol>(() => semanticModel.LookupSymbols(positionForLookup) .Where(s => (s.IsStatic || !enclosingSymbol.IsStatic) && s.CanBeReferencedByName && IsSymbolTheRightType(s, nameof(CancellationToken), Namespaces.SystemThreading)) .OrderBy(s => s.ContainingSymbol.Equals(enclosingSymbol) ? 1 : s.ContainingType.Equals(enclosingSymbol.ContainingType) ? 2 : 3) // prefer locality .FirstOrDefault()); foreach (var option in options) { var(fullTypeName, methodName) = SplitOffLastElement(option); var(ns, leafTypeName) = SplitOffLastElement(fullTypeName); string[] namespaces = ns?.Split('.'); if (fullTypeName == null) { continue; } var proposedType = semanticModel.Compilation.GetTypeByMetadataName(fullTypeName); // We're looking for methods that either require no parameters, // or (if we have one to give) that have just one parameter that is a CancellationToken. var proposedMethod = proposedType?.GetMembers(methodName).OfType <IMethodSymbol>() .FirstOrDefault(m => !m.Parameters.Any(p => !p.HasExplicitDefaultValue) || (cancellationTokenSymbol.Value != null && m.Parameters.Length == 1 && IsCancellationTokenParameter(m.Parameters[0]))); if (proposedMethod == null) { // We can't find it, so don't offer to use it. continue; } if (proposedMethod.IsStatic) { OfferFix(option); } else { // Search fields on the declaring type. // Consider local variables too, if they're captured in a closure from some surrounding code block // such that they would presumably be initialized by the time the first statement in our own code block runs. ITypeSymbol enclosingTypeSymbol = enclosingSymbol as ITypeSymbol ?? enclosingSymbol.ContainingType; if (enclosingTypeSymbol != null) { var candidateMembers = from symbol in semanticModel.LookupSymbols(positionForLookup, enclosingTypeSymbol) where symbol.IsStatic || !enclosingSymbol.IsStatic where IsSymbolTheRightType(symbol, leafTypeName, namespaces) select symbol; foreach (var candidate in candidateMembers) { OfferFix($"{candidate.Name}.{methodName}"); } } // Find static fields/properties that return the matching type from other public, non-generic types. var candidateStatics = from offering in semanticModel.LookupStaticMembers(positionForLookup).OfType <ITypeSymbol>() from symbol in offering.GetMembers() where symbol.IsStatic && symbol.CanBeReferencedByName && IsSymbolTheRightType(symbol, leafTypeName, namespaces) select symbol; foreach (var candidate in candidateStatics) { OfferFix($"{candidate.ContainingNamespace}.{candidate.ContainingType.Name}.{candidate.Name}.{methodName}"); } } void OfferFix(string fullyQualifiedMethod) { context.RegisterCodeFix(CodeAction.Create($"Add call to {fullyQualifiedMethod}", ct => Fix(fullyQualifiedMethod, proposedMethod, cancellationTokenSymbol, ct), fullyQualifiedMethod), context.Diagnostics); } } } bool IsSymbolTheRightType(ISymbol symbol, string typeName, IReadOnlyList <string> namespaces) { var fieldSymbol = symbol as IFieldSymbol; var propertySymbol = symbol as IPropertySymbol; var parameterSymbol = symbol as IParameterSymbol; var localSymbol = symbol as ILocalSymbol; var memberType = fieldSymbol?.Type ?? propertySymbol?.Type ?? parameterSymbol?.Type ?? localSymbol?.Type; return(memberType?.Name == typeName && memberType.BelongsToNamespace(namespaces)); } Task <Document> Fix(string fullyQualifiedMethod, IMethodSymbol methodSymbol, Lazy <ISymbol> cancellationTokenSymbol, CancellationToken cancellationToken) { int typeAndMethodDelimiterIndex = fullyQualifiedMethod.LastIndexOf('.'); IdentifierNameSyntax methodName = SyntaxFactory.IdentifierName(fullyQualifiedMethod.Substring(typeAndMethodDelimiterIndex + 1)); ExpressionSyntax invokedMethod = Utils.MemberAccess(fullyQualifiedMethod.Substring(0, typeAndMethodDelimiterIndex).Split('.'), methodName); var invocationExpression = SyntaxFactory.InvocationExpression(invokedMethod); var cancellationTokenParameter = methodSymbol.Parameters.FirstOrDefault(IsCancellationTokenParameter); if (cancellationTokenParameter != null && cancellationTokenSymbol.Value != null) { var arg = SyntaxFactory.Argument(SyntaxFactory.IdentifierName(cancellationTokenSymbol.Value.Name)); if (methodSymbol.Parameters.IndexOf(cancellationTokenParameter) > 0) { arg = arg.WithNameColon(SyntaxFactory.NameColon(SyntaxFactory.IdentifierName(cancellationTokenParameter.Name))); } invocationExpression = invocationExpression.AddArgumentListArguments(arg); } ExpressionSyntax awaitExpression = container.IsAsync ? SyntaxFactory.AwaitExpression(invocationExpression) : null; var addedStatement = SyntaxFactory.ExpressionStatement(awaitExpression ?? invocationExpression) .WithAdditionalAnnotations(Simplifier.Annotation, Formatter.Annotation); var initialBlockSyntax = container.BlockOrExpression as BlockSyntax; if (initialBlockSyntax == null) { initialBlockSyntax = SyntaxFactory.Block(SyntaxFactory.ReturnStatement((ExpressionSyntax)container.BlockOrExpression)) .WithAdditionalAnnotations(Formatter.Annotation); } var newBlock = initialBlockSyntax.WithStatements(initialBlockSyntax.Statements.Insert(0, addedStatement)); return(Task.FromResult(context.Document.WithSyntaxRoot(root.ReplaceNode(container.BlockOrExpression, newBlock)))); } bool IsCancellationTokenParameter(IParameterSymbol parameterSymbol) => parameterSymbol.Type.Name == nameof(CancellationToken) && parameterSymbol.Type.BelongsToNamespace(Namespaces.SystemThreading); }
public ExpressionSyntax EmitValueReference(object value) { var id = AddObject(value); return(SyntaxFactory.ElementAccessExpression(SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, ParseTypeName(typeof(DefaultViewCompilerCodeEmitter)), SyntaxFactory.IdentifierName(nameof(_ViewImmutableObjects))), SyntaxFactory.BracketedArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(EmitValue(id)))))); }
internal static ExpressionSyntax OptionalFor(ExpressionSyntax expression) { return(SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.QualifiedName( SyntaxFactory.IdentifierName(nameof(ImmutableObjectGraph)), SyntaxFactory.IdentifierName(nameof(ImmutableObjectGraph.Optional))), SyntaxFactory.IdentifierName(nameof(ImmutableObjectGraph.Optional.For))), SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(expression))))); }
private static async Task <Document> UseCollectionSizeAssertionAsync(Document document, InvocationExpressionSyntax invocation, string replacementMethod, CancellationToken cancellationToken) { var editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false); var memberAccess = (MemberAccessExpressionSyntax)invocation.Expression; var expression = GetExpressionSyntax(invocation); editor.ReplaceNode(invocation, invocation.WithArgumentList(invocation.ArgumentList.WithArguments(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(expression)))) .WithExpression(memberAccess.WithName(SyntaxFactory.IdentifierName(replacementMethod)))); return(editor.GetChangedDocument()); }
public static InvocationExpressionSyntax Invoke(this ExpressionSyntax target, params ExpressionSyntax[] arguments) { return(target.Invoke(arguments.Select(x => SyntaxFactory.Argument(x)).ToArray())); }
internal static InvocationExpressionSyntax ToList(ExpressionSyntax expression) { return(SyntaxFactory.InvocationExpression( // System.Linq.Enumerable.ToList SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.QualifiedName( SyntaxFactory.QualifiedName( SyntaxFactory.IdentifierName(nameof(System)), SyntaxFactory.IdentifierName(nameof(System.Linq))), SyntaxFactory.IdentifierName(nameof(Enumerable))), SyntaxFactory.IdentifierName(nameof(Enumerable.ToList))), SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(expression))))); }
/// <summary> /// Generates the multipart content statements. /// </summary> /// <param name="curlOptions">The curl options.</param> /// <returns>Collection of <see cref="StatementSyntax"/>.</returns> /// <remarks> /// var multipartContent = new MultipartFormDataContent(); /// multipartContent.Add(new StringContent("John"), "name"); /// multipartContent.Add(new ByteArrayContent(File.ReadAllBytes("D:\\text.txt")), "shoesize", Path.GetFileName("D:\\text.txt")); /// request.Content = multipartContent; /// </remarks> private IEnumerable <StatementSyntax> CreateMultipartContentStatements(CurlOptions curlOptions) { var statements = new LinkedList <StatementSyntax>(); const string MultipartVariableName = "multipartContent"; const string MultipartAddMethodName = "Add"; statements.AddLast( SyntaxFactory.LocalDeclarationStatement( RoslynExtensions.CreateVariableFromNewObjectExpression( MultipartVariableName, nameof(MultipartFormDataContent)))); int fileCounter = 1; foreach (var data in curlOptions.FormData) { StatementSyntax addStatement; if (data.Type == UploadDataType.Inline) { var contentExpression = RoslynExtensions.CreateObjectCreationExpression( nameof(StringContent), RoslynExtensions.CreateStringLiteralArgument(data.Content)); addStatement = SyntaxFactory.ExpressionStatement( RoslynExtensions.CreateInvocationExpression( MultipartVariableName, MultipartAddMethodName, SyntaxFactory.Argument(contentExpression), RoslynExtensions.CreateStringLiteralArgument(data.Name))); } else if (data.Type == UploadDataType.BinaryFile) { var getFileNameArgument = string.IsNullOrEmpty(data.FileName) ? SyntaxFactory.Argument( RoslynExtensions.CreateInvocationExpression( nameof(Path), nameof(Path.GetFileName), RoslynExtensions.CreateStringLiteralArgument(data.Content))) : RoslynExtensions.CreateStringLiteralArgument(data.FileName); // If the file has content type, we should add it to ByteArrayContent headers var contentExpression = CreateNewByteArrayContentExpression(data.Content); ExpressionSyntax contentArgumentExpression; if (string.IsNullOrEmpty(data.ContentType)) { contentArgumentExpression = contentExpression; } else { var byteArrayVariableName = "file" + fileCounter; var byteArrayContentInitialization = RoslynExtensions.CreateVariableInitializationExpression(byteArrayVariableName, contentExpression); statements.AddLast(SyntaxFactory.LocalDeclarationStatement(byteArrayContentInitialization)); statements.AddLast( SyntaxFactory.ExpressionStatement( RoslynExtensions.CreateInvocationExpression( byteArrayVariableName, "Headers", "Add", RoslynExtensions.CreateStringLiteralArgument("Content-Type"), RoslynExtensions.CreateStringLiteralArgument(data.ContentType)))); contentArgumentExpression = SyntaxFactory.IdentifierName(byteArrayVariableName); } addStatement = SyntaxFactory.ExpressionStatement( RoslynExtensions.CreateInvocationExpression( MultipartVariableName, MultipartAddMethodName, SyntaxFactory.Argument(contentArgumentExpression), RoslynExtensions.CreateStringLiteralArgument(data.Name), getFileNameArgument)); } else { var contentExpression = RoslynExtensions.CreateObjectCreationExpression( nameof(StringContent), SyntaxFactory.Argument(CreateFileReadAllTextExpression(data.Content))); addStatement = SyntaxFactory.ExpressionStatement( RoslynExtensions.CreateInvocationExpression( MultipartVariableName, MultipartAddMethodName, SyntaxFactory.Argument(contentExpression), RoslynExtensions.CreateStringLiteralArgument(data.Name))); } statements.AddLast(addStatement); } statements.AddLast(SyntaxFactory.ExpressionStatement( RoslynExtensions.CreateMemberAssignmentExpression( RequestVariableName, RequestContentPropertyName, SyntaxFactory.IdentifierName(MultipartVariableName)))); statements.TryAppendWhiteSpaceAtEnd(); return(statements); }
/// <summary> /// Generate the HttpRequestMessage using statements with statements inside the using blocks. /// </summary> /// <param name="curlOptions">The curl options.</param> /// <returns>Collection of <see cref="UsingStatementSyntax"/>.</returns> /// <remarks> /// using (var request = new HttpRequestMessage(new HttpMethod("GET"), "https://github.com/")) /// { /// var response = await httpClient.SendAsync(request); /// } /// </remarks> private IEnumerable <UsingStatementSyntax> CreateRequestUsingStatements(CurlOptions curlOptions) { var innerBlock = SyntaxFactory.Block(); var methodNameArgument = RoslynExtensions.CreateStringLiteralArgument(curlOptions.HttpMethod); var httpMethodArgument = RoslynExtensions.CreateObjectCreationExpression(nameof(HttpMethod), methodNameArgument); var urlArgument = RoslynExtensions.CreateStringLiteralArgument(curlOptions.GetFullUrl()); var requestUsingStatement = RoslynExtensions.CreateUsingStatement( RequestVariableName, nameof(HttpRequestMessage), SyntaxFactory.Argument(httpMethodArgument), urlArgument); var statements = CreateHeaderAssignmentStatements(curlOptions); innerBlock = innerBlock.AddStatements(statements.ToArray()); if (!string.IsNullOrEmpty(curlOptions.UserPasswordPair)) { var basicAuthorizationStatements = CreateBasicAuthorizationStatements(curlOptions); innerBlock = innerBlock.AddStatements(basicAuthorizationStatements.ToArray()); } var requestInnerBlocks = new LinkedList <UsingStatementSyntax>(); if (curlOptions.HasDataPayload && !curlOptions.ForceGet) { var assignmentExpression = CreateStringContentAssignmentStatement(curlOptions); requestInnerBlocks.AddLast( requestUsingStatement.WithStatement(innerBlock.AddStatements(assignmentExpression.ToArray()))); } else if (curlOptions.HasFormPayload) { var multipartContentStatements = CreateMultipartContentStatements(curlOptions); requestInnerBlocks.AddLast( requestUsingStatement.WithStatement(innerBlock.AddStatements(multipartContentStatements.ToArray()))); } else if (curlOptions.HasFilePayload) { foreach (var file in curlOptions.UploadFiles) { // NOTE that you must use a trailing / on the last directory to really prove to // Curl that there is no file name or curl will think that your last directory name is the remote file name to use. if (!string.IsNullOrEmpty(curlOptions.Url.PathAndQuery) && curlOptions.Url.PathAndQuery.EndsWith('/')) { var objectCreationExpressionSyntaxs = requestUsingStatement.DescendantNodes() .OfType <ObjectCreationExpressionSyntax>() .First( t => t.Type is IdentifierNameSyntax identifier && identifier.Identifier.ValueText == nameof(HttpRequestMessage)); var s = objectCreationExpressionSyntaxs.ArgumentList.Arguments.Last(); requestUsingStatement = requestUsingStatement.ReplaceNode( s, RoslynExtensions.CreateStringLiteralArgument(curlOptions.GetUrlForFileUpload(file).ToString())); } var byteArrayContentExpression = CreateNewByteArrayContentExpression(file); requestInnerBlocks.AddLast(requestUsingStatement.WithStatement(innerBlock.AddStatements( SyntaxFactory.ExpressionStatement( RoslynExtensions.CreateMemberAssignmentExpression( RequestVariableName, RequestContentPropertyName, byteArrayContentExpression)) .AppendWhiteSpace()))); } } var sendStatement = CreateSendStatement(); if (!requestInnerBlocks.Any()) { return(new List <UsingStatementSyntax> { requestUsingStatement.WithStatement(innerBlock.AddStatements(sendStatement)) }); } return(requestInnerBlocks.Select(i => i.WithStatement(((BlockSyntax)i.Statement).AddStatements(sendStatement)))); }
private void ImplementSortedChildrenInterface() { this.baseTypes.Add(SyntaxFactory.SimpleBaseType(Syntax.GetTypeSyntax(typeof(IRecursiveParentWithSortedChildren)))); // int IRecursiveParentWithSortedChildren.Compare(IRecursiveType first, IRecursiveType second) var firstParameterName = SyntaxFactory.IdentifierName("first"); var secondParameterName = SyntaxFactory.IdentifierName("second"); this.innerMembers.Add(SyntaxFactory.MethodDeclaration( SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.IntKeyword)), nameof(IRecursiveParentWithSortedChildren.Compare)) .WithExplicitInterfaceSpecifier(SyntaxFactory.ExplicitInterfaceSpecifier(SyntaxFactory.IdentifierName(nameof(IRecursiveParentWithSortedChildren)))) .AddParameterListParameters( SyntaxFactory.Parameter(firstParameterName.Identifier).WithType(Syntax.GetTypeSyntax(typeof(IRecursiveType))), SyntaxFactory.Parameter(secondParameterName.Identifier).WithType(Syntax.GetTypeSyntax(typeof(IRecursiveType)))) .WithBody(SyntaxFactory.Block( // return this.Children.KeyComparer.Compare((<#= templateType.RecursiveType.TypeName #>)first, (<#= templateType.RecursiveType.TypeName #>)second); SyntaxFactory.ReturnStatement( SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, Syntax.ThisDot(SyntaxFactory.IdentifierName(this.generator.applyToMetaType.RecursiveField.Name.ToPascalCase())), SyntaxFactory.IdentifierName(nameof(ImmutableSortedSet <int> .KeyComparer))), SyntaxFactory.IdentifierName(nameof(IComparer <int> .Compare))), SyntaxFactory.ArgumentList(Syntax.JoinSyntaxNodes(SyntaxKind.CommaToken, SyntaxFactory.Argument(SyntaxFactory.CastExpression(this.generator.applyToMetaType.RecursiveType.TypeSyntax, firstParameterName)), SyntaxFactory.Argument(SyntaxFactory.CastExpression(this.generator.applyToMetaType.RecursiveType.TypeSyntax, secondParameterName))))))))); }
public override async Task RegisterCodeFixesAsync(CodeFixContext context) { Diagnostic?diagnostic = context.Diagnostics.First(); SyntaxNode?root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); var syntaxNode = (ExpressionSyntax)root.FindNode(diagnostic.Location.SourceSpan, getInnermostNodeForTie: true); CSharpUtils.ContainingFunctionData container = CSharpUtils.GetContainingFunction(syntaxNode); if (container.BlockOrExpression is null) { return; } SemanticModel?semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false); ISymbol?enclosingSymbol = semanticModel.GetEnclosingSymbol(diagnostic.Location.SourceSpan.Start, context.CancellationToken); if (enclosingSymbol is null) { return; } bool convertToAsync = !container.IsAsync && Utils.HasAsyncCompatibleReturnType(enclosingSymbol as IMethodSymbol); if (convertToAsync) { // We don't support this yet, and we don't want to take the sync method path in this case. // The user will have to fix this themselves. return; } Regex lookupKey = (container.IsAsync || convertToAsync) ? CommonInterest.FileNamePatternForMethodsThatSwitchToMainThread : CommonInterest.FileNamePatternForMethodsThatAssertMainThread; string[] options = diagnostic.Properties[lookupKey.ToString()].Split('\n'); if (options.Length > 0) { // For any symbol lookups, we want to consider the position of the very first statement in the block. int positionForLookup = container.BlockOrExpression.GetLocation().SourceSpan.Start + 1; Lazy <ISymbol> cancellationTokenSymbol = new Lazy <ISymbol>(() => Utils.FindCancellationToken(semanticModel, positionForLookup, context.CancellationToken).FirstOrDefault()); foreach (var option in options) { // We're looking for methods that either require no parameters, // or (if we have one to give) that have just one parameter that is a CancellationToken. IMethodSymbol?proposedMethod = Utils.FindMethodGroup(semanticModel, option) .FirstOrDefault(m => !m.Parameters.Any(p => !p.HasExplicitDefaultValue) || (cancellationTokenSymbol.Value is object && m.Parameters.Length == 1 && Utils.IsCancellationTokenParameter(m.Parameters[0]))); if (proposedMethod is null) { // We can't find it, so don't offer to use it. continue; } if (proposedMethod.IsStatic) { OfferFix(option); } else { foreach (Tuple <bool, ISymbol>?candidate in Utils.FindInstanceOf(proposedMethod.ContainingType, semanticModel, positionForLookup, context.CancellationToken)) { if (candidate.Item1) { OfferFix($"{candidate.Item2.Name}.{proposedMethod.Name}"); } else { OfferFix($"{candidate.Item2.ContainingNamespace}.{candidate.Item2.ContainingType.Name}.{candidate.Item2.Name}.{proposedMethod.Name}"); } } } void OfferFix(string fullyQualifiedMethod) { context.RegisterCodeFix(CodeAction.Create($"Add call to {fullyQualifiedMethod}", ct => Fix(fullyQualifiedMethod, proposedMethod, cancellationTokenSymbol), fullyQualifiedMethod), context.Diagnostics); } } } Task <Document> Fix(string fullyQualifiedMethod, IMethodSymbol methodSymbol, Lazy <ISymbol> cancellationTokenSymbol) { int typeAndMethodDelimiterIndex = fullyQualifiedMethod.LastIndexOf('.'); IdentifierNameSyntax methodName = SyntaxFactory.IdentifierName(fullyQualifiedMethod.Substring(typeAndMethodDelimiterIndex + 1)); ExpressionSyntax invokedMethod = CSharpUtils.MemberAccess(fullyQualifiedMethod.Substring(0, typeAndMethodDelimiterIndex).Split('.'), methodName); InvocationExpressionSyntax?invocationExpression = SyntaxFactory.InvocationExpression(invokedMethod); IParameterSymbol? cancellationTokenParameter = methodSymbol.Parameters.FirstOrDefault(Utils.IsCancellationTokenParameter); if (cancellationTokenParameter is object && cancellationTokenSymbol.Value is object) { ArgumentSyntax?arg = SyntaxFactory.Argument(SyntaxFactory.IdentifierName(cancellationTokenSymbol.Value.Name)); if (methodSymbol.Parameters.IndexOf(cancellationTokenParameter) > 0) { arg = arg.WithNameColon(SyntaxFactory.NameColon(SyntaxFactory.IdentifierName(cancellationTokenParameter.Name))); } invocationExpression = invocationExpression.AddArgumentListArguments(arg); } ExpressionSyntax? awaitExpression = container.IsAsync ? SyntaxFactory.AwaitExpression(invocationExpression) : null; ExpressionStatementSyntax?addedStatement = SyntaxFactory.ExpressionStatement(awaitExpression ?? invocationExpression) .WithAdditionalAnnotations(Simplifier.Annotation, Formatter.Annotation); var initialBlockSyntax = container.BlockOrExpression as BlockSyntax; if (initialBlockSyntax is null) { initialBlockSyntax = SyntaxFactory.Block(SyntaxFactory.ReturnStatement((ExpressionSyntax)container.BlockOrExpression)) .WithAdditionalAnnotations(Formatter.Annotation); } BlockSyntax?newBlock = initialBlockSyntax.WithStatements(initialBlockSyntax.Statements.Insert(0, addedStatement)); return(Task.FromResult(context.Document.WithSyntaxRoot(root.ReplaceNode(container.BlockOrExpression, newBlock)))); } }
private void ImplementOrderedChildrenInterface() { // We only need to declare this interface if the children are not sorted, // since sorted children merit a derived interface making this redundant. if (!this.generator.applyToMetaType.ChildrenAreSorted) { this.baseTypes.Add(SyntaxFactory.SimpleBaseType(Syntax.GetTypeSyntax(typeof(IRecursiveParentWithOrderedChildren)))); } // IReadOnlyList<IRecursiveType> IRecursiveParentWithOrderedChildren.Children => this.children; this.innerMembers.Add(SyntaxFactory.PropertyDeclaration( Syntax.IReadOnlyListOf(Syntax.GetTypeSyntax(typeof(IRecursiveType))), nameof(IRecursiveParentWithOrderedChildren.Children)) .WithExplicitInterfaceSpecifier(SyntaxFactory.ExplicitInterfaceSpecifier(SyntaxFactory.IdentifierName(nameof(IRecursiveParentWithOrderedChildren)))) .WithExpressionBody(SyntaxFactory.ArrowExpressionClause(Syntax.ThisDot(SyntaxFactory.IdentifierName(this.generator.applyToMetaType.RecursiveField.Name)))) .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)) .AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(DebuggerBrowsableNeverAttribute)))); // int IRecursiveParentWithOrderedChildren.IndexOf(IRecursiveType value) var valueParameterName = SyntaxFactory.IdentifierName("value"); this.innerMembers.Add(SyntaxFactory.MethodDeclaration( SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.IntKeyword)), nameof(IRecursiveParentWithOrderedChildren.IndexOf)) .WithExplicitInterfaceSpecifier(SyntaxFactory.ExplicitInterfaceSpecifier(SyntaxFactory.IdentifierName(nameof(IRecursiveParentWithOrderedChildren)))) .AddParameterListParameters(SyntaxFactory.Parameter(valueParameterName.Identifier).WithType(Syntax.GetTypeSyntax(typeof(IRecursiveType)))) .WithBody(SyntaxFactory.Block( // return this.Children.IndexOf((<#= templateType.RecursiveType.TypeName #>)value); SyntaxFactory.ReturnStatement( SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, Syntax.ThisDot(SyntaxFactory.IdentifierName(this.generator.applyToMetaType.RecursiveField.Name.ToPascalCase())), SyntaxFactory.IdentifierName(nameof(IList <int> .IndexOf))), SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList( SyntaxFactory.Argument( SyntaxFactory.CastExpression( this.generator.applyToMetaType.RecursiveType.TypeSyntax, valueParameterName))))))))); }
private void ImplementRecursiveParentInterface() { var irecursiveParentOfT = CreateIRecursiveParentOfTSyntax(GetFullyQualifiedSymbolName(this.generator.applyToMetaType.RecursiveType.TypeSymbol)); this.baseTypes.Add(SyntaxFactory.SimpleBaseType(irecursiveParentOfT)); // this.Children; var thisDotChildren = Syntax.ThisDot(SyntaxFactory.IdentifierName(this.generator.applyToMetaType.RecursiveField.Name.ToPascalCase())); // System.Collections.Generic.IReadOnlyCollection<IRecursiveType> IRecursiveParent.Children this.innerMembers.Add( SyntaxFactory.PropertyDeclaration( Syntax.GetTypeSyntax(typeof(IReadOnlyCollection <IRecursiveType>)), nameof(IRecursiveParent.Children)) .WithExplicitInterfaceSpecifier(SyntaxFactory.ExplicitInterfaceSpecifier(Syntax.GetTypeSyntax(typeof(IRecursiveParent)))) .WithExpressionBody(SyntaxFactory.ArrowExpressionClause(thisDotChildren)) .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)) .AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(DebuggerBrowsableNeverAttribute)))); // public ParentedRecursiveType<TRecursiveParent, TRecursiveType> GetParentedNode(uint identity) this.innerMembers.Add( SyntaxFactory.MethodDeclaration( SyntaxFactory.GenericName(nameof(ParentedRecursiveType <IRecursiveParent <IRecursiveType>, IRecursiveType>)).AddTypeArgumentListArguments( this.applyTo.RecursiveParent.TypeSyntax, this.applyTo.RecursiveType.TypeSyntax), nameof(IRecursiveParent.GetParentedNode)) .AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword)) //.WithExplicitInterfaceSpecifier(SyntaxFactory.ExplicitInterfaceSpecifier(Syntax.GetTypeSyntax(typeof(IRecursiveParent)))) .AddParameterListParameters(RequiredIdentityParameter) .WithBody(SyntaxFactory.Block( // return this.GetParentedNode<TRecursiveParent, TRecursiveType>(identity); SyntaxFactory.ReturnStatement( SyntaxFactory.InvocationExpression( Syntax.ThisDot(SyntaxFactory.GenericName(nameof(RecursiveTypeExtensions.GetParentedNode)).AddTypeArgumentListArguments( this.applyTo.RecursiveParent.TypeSyntax, this.applyTo.RecursiveType.TypeSyntax))) .AddArgumentListArguments(SyntaxFactory.Argument(IdentityParameterName)))))); // ParentedRecursiveType<IRecursiveParent<IRecursiveType>, IRecursiveType> IRecursiveParent.GetParentedNode(<#= templateType.RequiredIdentityField.TypeName #> identity) { var parentedVar = SyntaxFactory.IdentifierName("parented"); var returnType = Syntax.GetTypeSyntax(typeof(ParentedRecursiveTypeNonGeneric)); this.innerMembers.Add( SyntaxFactory.MethodDeclaration( returnType, nameof(IRecursiveParent.GetParentedNode)) .WithExplicitInterfaceSpecifier(SyntaxFactory.ExplicitInterfaceSpecifier(Syntax.GetTypeSyntax(typeof(IRecursiveParent)))) .AddParameterListParameters(RequiredIdentityParameter) .WithBody(SyntaxFactory.Block( // var parented = this.GetParentedNode(identity); SyntaxFactory.LocalDeclarationStatement(SyntaxFactory.VariableDeclaration(varType).AddVariables( SyntaxFactory.VariableDeclarator(parentedVar.Identifier).WithInitializer(SyntaxFactory.EqualsValueClause( SyntaxFactory.InvocationExpression(Syntax.ThisDot(SyntaxFactory.IdentifierName(nameof(RecursiveTypeExtensions.GetParentedNode)))) .AddArgumentListArguments(SyntaxFactory.Argument(IdentityParameterName)))))), // return new ParentedRecursiveType<IRecursiveParent<IRecursiveType>, IRecursiveType>(parented.Value, parented.Parent); SyntaxFactory.ReturnStatement(SyntaxFactory.ObjectCreationExpression(returnType).AddArgumentListArguments( SyntaxFactory.Argument(SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, parentedVar, SyntaxFactory.IdentifierName(nameof(ParentedRecursiveTypeNonGeneric.Value)))), SyntaxFactory.Argument(SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, parentedVar, SyntaxFactory.IdentifierName(nameof(ParentedRecursiveTypeNonGeneric.Parent))))))))); ////System.Collections.Generic.IReadOnlyCollection<<#= templateType.RecursiveType.TypeName #>> IRecursiveParent<<#= templateType.RecursiveType.TypeName #>>.Children //// => return this.Children; this.innerMembers.Add( SyntaxFactory.PropertyDeclaration( Syntax.IReadOnlyCollectionOf(this.generator.applyToMetaType.RecursiveType.TypeSyntax), nameof(IRecursiveParent <IRecursiveType> .Children)) .WithExplicitInterfaceSpecifier(SyntaxFactory.ExplicitInterfaceSpecifier(irecursiveParentOfT)) .WithExpressionBody(SyntaxFactory.ArrowExpressionClause(thisDotChildren)) .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)) .AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(DebuggerBrowsableNeverAttribute)))); }
public override async Task RegisterCodeFixesAsync(CodeFixContext context) { foreach (var diagnostic in context.Diagnostics) { var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); ExpressionSyntax?syntaxNode = root.FindNode(diagnostic.Location.SourceSpan, getInnermostNodeForTie: true) as ExpressionSyntax; if (syntaxNode is null) { continue; } var container = Utils.GetContainingFunction(syntaxNode); if (container.BlockOrExpression == null) { return; } if (!container.IsAsync) { if (!(container.Function is MethodDeclarationSyntax || container.Function is AnonymousFunctionExpressionSyntax)) { // We don't support converting whatever this is into an async method. return; } } var semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false); var enclosingSymbol = semanticModel.GetEnclosingSymbol(diagnostic.Location.SourceSpan.Start, context.CancellationToken); if (enclosingSymbol == null) { return; } var hasReturnValue = ((enclosingSymbol as IMethodSymbol)?.ReturnType as INamedTypeSymbol)?.IsGenericType ?? false; var options = await CommonFixes.ReadMethodsAsync(context, CommonInterest.FileNamePatternForMethodsThatSwitchToMainThread, context.CancellationToken); int positionForLookup = diagnostic.Location.SourceSpan.Start; ISymbol cancellationTokenSymbol = Utils.FindCancellationToken(semanticModel, positionForLookup, context.CancellationToken).FirstOrDefault(); foreach (var option in options) { // We're looking for methods that either require no parameters, // or (if we have one to give) that have just one parameter that is a CancellationToken. var proposedMethod = Utils.FindMethodGroup(semanticModel, option) .FirstOrDefault(m => !m.Parameters.Any(p => !p.HasExplicitDefaultValue) || (cancellationTokenSymbol != null && m.Parameters.Length == 1 && Utils.IsCancellationTokenParameter(m.Parameters[0]))); if (proposedMethod == null) { // We can't find it, so don't offer to use it. continue; } if (proposedMethod.IsStatic) { OfferFix(option.ToString()); } else { foreach (var candidate in Utils.FindInstanceOf(proposedMethod.ContainingType, semanticModel, positionForLookup, context.CancellationToken)) { if (candidate.Item1) { OfferFix($"{candidate.Item2.Name}.{proposedMethod.Name}"); } else { OfferFix($"{candidate.Item2.ContainingNamespace}.{candidate.Item2.ContainingType.Name}.{candidate.Item2.Name}.{proposedMethod.Name}"); } } } void OfferFix(string fullyQualifiedMethod) { context.RegisterCodeFix(CodeAction.Create($"Use 'await {fullyQualifiedMethod}'", ct => Fix(fullyQualifiedMethod, proposedMethod, hasReturnValue, ct), fullyQualifiedMethod), context.Diagnostics); } } async Task <Solution> Fix(string fullyQualifiedMethod, IMethodSymbol methodSymbol, bool hasReturnValue, CancellationToken cancellationToken) { var assertionStatementToRemove = syntaxNode !.FirstAncestorOrSelf <StatementSyntax>(); int typeAndMethodDelimiterIndex = fullyQualifiedMethod.LastIndexOf('.'); IdentifierNameSyntax methodName = SyntaxFactory.IdentifierName(fullyQualifiedMethod.Substring(typeAndMethodDelimiterIndex + 1)); ExpressionSyntax invokedMethod = Utils.MemberAccess(fullyQualifiedMethod.Substring(0, typeAndMethodDelimiterIndex).Split('.'), methodName) .WithAdditionalAnnotations(Simplifier.Annotation); var invocationExpression = SyntaxFactory.InvocationExpression(invokedMethod); var cancellationTokenParameter = methodSymbol.Parameters.FirstOrDefault(Utils.IsCancellationTokenParameter); if (cancellationTokenParameter != null && cancellationTokenSymbol != null) { var arg = SyntaxFactory.Argument(SyntaxFactory.IdentifierName(cancellationTokenSymbol.Name)); if (methodSymbol.Parameters.IndexOf(cancellationTokenParameter) > 0) { arg = arg.WithNameColon(SyntaxFactory.NameColon(SyntaxFactory.IdentifierName(cancellationTokenParameter.Name))); } invocationExpression = invocationExpression.AddArgumentListArguments(arg); } ExpressionSyntax awaitExpression = SyntaxFactory.AwaitExpression(invocationExpression); var addedStatement = SyntaxFactory.ExpressionStatement(awaitExpression) .WithAdditionalAnnotations(Simplifier.Annotation, Formatter.Annotation); var methodAnnotation = new SyntaxAnnotation(); CSharpSyntaxNode methodSyntax = container.Function.ReplaceNode(assertionStatementToRemove, addedStatement) .WithAdditionalAnnotations(methodAnnotation); Document newDocument = context.Document.WithSyntaxRoot(root.ReplaceNode(container.Function, methodSyntax)); var newSyntaxRoot = await newDocument.GetSyntaxRootAsync(cancellationToken); methodSyntax = (CSharpSyntaxNode)newSyntaxRoot.GetAnnotatedNodes(methodAnnotation).Single(); if (!container.IsAsync) { switch (methodSyntax) { case AnonymousFunctionExpressionSyntax anonFunc: semanticModel = await newDocument.GetSemanticModelAsync(cancellationToken); methodSyntax = FixUtils.MakeMethodAsync(anonFunc, hasReturnValue, semanticModel, cancellationToken); newDocument = newDocument.WithSyntaxRoot(newSyntaxRoot.ReplaceNode(anonFunc, methodSyntax)); break; case MethodDeclarationSyntax methodDecl: (newDocument, methodSyntax) = await FixUtils.MakeMethodAsync(methodDecl, newDocument, cancellationToken); break; } } return(newDocument.Project.Solution); } } }
public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node) { var visitedNode = (MethodDeclarationSyntax)base.VisitMethodDeclaration(node); if (ReferenceEquals(visitedNode, node) && _methodsWithOptionOverloads.Contains(node.Identifier.ValueText)) { // Don't generate methods where the body would call an overload. // The logic is a bit more complicated and there are only // two methods anyway. They can be written out by hand in the // partial class. return(SyntaxFactory.IncompleteMember()); } var returnTypeSymbol = _semanticModel.GetTypeInfo(node.ReturnType).Type as INamedTypeSymbol; bool isAsync = returnTypeSymbol != null && (returnTypeSymbol.Equals(_taskTypeSymbol) || returnTypeSymbol.ConstructedFrom.Equals(_taskOfTTypeSymbol)); if (isAsync) { visitedNode = visitedNode.AddModifiers(SyntaxFactory.Token(SyntaxKind.AsyncKeyword)); var invocation = visitedNode.DescendantNodes().OfType <InvocationExpressionSyntax>().First(); visitedNode = visitedNode.ReplaceNode(invocation, SyntaxFactory.AwaitExpression(invocation)); } // wrap with try/catch visitedNode = visitedNode.WithBody(SyntaxFactory.Block(SyntaxFactory.TryStatement( block: visitedNode.Body, catches: SyntaxFactory.SingletonList( SyntaxFactory.CatchClause() .WithDeclaration( SyntaxFactory.CatchDeclaration( SyntaxFactory.IdentifierName("System.Exception")) .WithIdentifier( SyntaxFactory.Identifier("ex"))) .WithBlock( SyntaxFactory.Block( SyntaxFactory.SeparatedList( new StatementSyntax[] { SyntaxFactory.ExpressionStatement(SyntaxFactory.InvocationExpression(SyntaxFactory.IdentifierName("ProcessException")).AddArgumentListArguments(SyntaxFactory.Argument(SyntaxFactory.IdentifierName("ex")))), SyntaxFactory.ThrowStatement(), })))), @finally: null))); if (isAsync && returnTypeSymbol.TypeArguments.FirstOrDefault() is INamedTypeSymbol argumentType && argumentType.IsGenericType && _responseTypeSymbols.Contains(argumentType.ConstructedFrom)) { var awaitSyntax = visitedNode.DescendantNodes().OfType <AwaitExpressionSyntax>().First(); visitedNode = visitedNode.ReplaceNode(awaitSyntax, SyntaxFactory.InvocationExpression(SyntaxFactory.IdentifierName("ProcessResponse")).AddArgumentListArguments(SyntaxFactory.Argument(awaitSyntax))); } return(visitedNode); }
/// <summary> /// Generate the statements for HttpClient handler configuration. /// </summary> /// <param name="curlOptions">The curl options.</param> /// <returns>Collection of <see cref="MemberDeclarationSyntax" />.</returns> /// <remarks> /// var handler = new HttpClientHandler(); /// handler.UseCookies = false; /// </remarks> private IEnumerable <MemberDeclarationSyntax> ConfigureHandlerStatements(CurlOptions curlOptions) { var statementSyntaxs = new LinkedList <MemberDeclarationSyntax>(); var handlerInitialization = RoslynExtensions.CreateVariableFromNewObjectExpression( HandlerVariableName, nameof(HttpClientHandler)); statementSyntaxs.AddLast( SyntaxFactory.GlobalStatement(SyntaxFactory.LocalDeclarationStatement(handlerInitialization))); if (curlOptions.HasCookies) { var memberAssignmentExpression = RoslynExtensions.CreateMemberAssignmentExpression( HandlerVariableName, "UseCookies", SyntaxFactory.LiteralExpression(SyntaxKind.FalseLiteralExpression)); statementSyntaxs.AddLast( SyntaxFactory.GlobalStatement(SyntaxFactory.ExpressionStatement(memberAssignmentExpression))); } if (curlOptions.HasProxy && IsSupportedProxy(curlOptions.ProxyUri)) { var memberAssignmentExpression = CreateProxyStatements(curlOptions); statementSyntaxs.AddLast( SyntaxFactory.GlobalStatement(SyntaxFactory.ExpressionStatement(memberAssignmentExpression))); } if (curlOptions.HasCertificate && IsSupportedCertificate(curlOptions.CertificateType)) { var memberAssignmentExpression = RoslynExtensions.CreateMemberAssignmentExpression( HandlerVariableName, "ClientCertificateOptions", RoslynExtensions.CreateMemberAccessExpression("ClientCertificateOption", "Manual")); statementSyntaxs.AddLast( SyntaxFactory.GlobalStatement(SyntaxFactory.ExpressionStatement(memberAssignmentExpression))); var newCertificateArguments = new LinkedList <ArgumentSyntax>(); newCertificateArguments.AddLast(RoslynExtensions.CreateStringLiteralArgument(curlOptions.CertificateFileName)); if (curlOptions.HasCertificatePassword) { newCertificateArguments.AddLast(RoslynExtensions.CreateStringLiteralArgument(curlOptions.CertificatePassword)); } var newCertificateExpression = RoslynExtensions.CreateObjectCreationExpression( "X509Certificate2", newCertificateArguments.ToArray()); var certificateAssignmentExpression = RoslynExtensions.CreateInvocationExpression( HandlerVariableName, "ClientCertificates", "Add", SyntaxFactory.Argument(newCertificateExpression)); statementSyntaxs.AddLast( SyntaxFactory.GlobalStatement(SyntaxFactory.ExpressionStatement(certificateAssignmentExpression))); } if (curlOptions.Insecure) { var parameterListSyntax = RoslynExtensions.CreateParameterListSyntax( "requestMessage", "certificate", "chain", "policyErrors"); var lambdaExpression = SyntaxFactory.ParenthesizedLambdaExpression( parameterListSyntax, SyntaxFactory.LiteralExpression(SyntaxKind.TrueLiteralExpression, SyntaxFactory.Token(SyntaxKind.TrueKeyword))); statementSyntaxs.AddLast( SyntaxFactory.GlobalStatement( SyntaxFactory.ExpressionStatement( RoslynExtensions.CreateMemberAssignmentExpression( HandlerVariableName, "ServerCertificateCustomValidationCallback", lambdaExpression)))); } statementSyntaxs.TryAppendWhiteSpaceAtEnd(); return(statementSyntaxs); }
public ArgumentBridge(bool value) { Value = SyntaxFactory.Argument(value ? SyntaxFactory.LiteralExpression(SyntaxKind.TrueLiteralExpression) : SyntaxFactory.LiteralExpression(SyntaxKind.FalseLiteralExpression)); }
/// <summary> /// Generates the string content creation statements. /// </summary> /// <param name="curlOptions">The curl options.</param> /// <returns>Collection of <see cref="StatementSyntax"/>.</returns> /// <remarks> /// request.Content = new StringContent("{\"status\": \"resolved\"}", Encoding.UTF8, "application/json"); /// </remarks> private IEnumerable <StatementSyntax> CreateStringContentAssignmentStatement(CurlOptions curlOptions) { var expressions = new LinkedList <ExpressionSyntax>(); foreach (var data in curlOptions.UploadData) { if (data.IsUrlEncoded) { ExpressionSyntax dataExpression; if (data.IsFile) { dataExpression = CreateFileReadAllTextExpression(data.Content); } else { dataExpression = SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(data.Content)); } dataExpression = RoslynExtensions.CreateInvocationExpression("Uri", "EscapeDataString", SyntaxFactory.Argument(dataExpression)); if (data.HasName) { dataExpression = RoslynExtensions.CreateInterpolatedStringExpression($"{data.Name}=", dataExpression); } expressions.AddLast(dataExpression); continue; } if (data.Type == UploadDataType.BinaryFile) { var readFileExpression = CreateFileReadAllTextExpression(data.Content); expressions.AddLast(readFileExpression); continue; } if (data.Type == UploadDataType.InlineFile) { var readFileExpression = CreateFileReadAllTextExpression(data.Content); var replaceNewLines = RoslynExtensions.CreateInvocationExpression( "Regex", "Replace", SyntaxFactory.Argument(readFileExpression), RoslynExtensions.CreateStringLiteralArgument(@"(?:\r\n|\n|\r)"), SyntaxFactory.Argument(RoslynExtensions.CreateMemberAccessExpression("string", "Empty"))); expressions.AddLast(replaceNewLines); continue; } expressions.AddLast( SyntaxFactory.LiteralExpression( SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(data.Content))); } var statements = new LinkedList <StatementSyntax>(); ArgumentSyntax stringContentArgumentSyntax; if (expressions.Count > 1) { var contentListVariableName = "contentList"; statements.AddLast( SyntaxFactory.LocalDeclarationStatement( RoslynExtensions.CreateVariableFromNewObjectExpression(contentListVariableName, "List<string>"))); foreach (var expression in expressions) { statements.AddLast( SyntaxFactory.ExpressionStatement( RoslynExtensions.CreateInvocationExpression( contentListVariableName, "Add", SyntaxFactory.Argument(expression)))); } stringContentArgumentSyntax = SyntaxFactory.Argument( RoslynExtensions.CreateInvocationExpression( "string", "Join", RoslynExtensions.CreateStringLiteralArgument("&"), SyntaxFactory.Argument(SyntaxFactory.IdentifierName(contentListVariableName)))); } else { stringContentArgumentSyntax = SyntaxFactory.Argument(expressions.First.Value); } var stringContentCreation = CreateStringContentCreation( stringContentArgumentSyntax, curlOptions); statements.AddLast( SyntaxFactory.ExpressionStatement( RoslynExtensions.CreateMemberAssignmentExpression( RequestVariableName, RequestContentPropertyName, stringContentCreation))); statements.TryAppendWhiteSpaceAtEnd(); return(statements); }
public static ObjectCreationExpressionSyntax New(this TypeSyntax type, params ExpressionSyntax[] arguments) { return(SyntaxFactory.ObjectCreationExpression(type) .WithArgumentList(SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(arguments.Select(x => SyntaxFactory.Argument(x)), arguments.Skip(1).Select(_ => SyntaxFactory.Token(SyntaxKind.CommaToken)))))); }
protected static InvocationExpressionSyntax GetConstraintExpression(string constraintString, ExpressionSyntax expected) { if (expected == null) { return(null); } return(SyntaxFactory.InvocationExpression( SyntaxFactory.ParseExpression(constraintString), SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(expected))))); }
internal static InvocationExpressionSyntax OptionalGetValueOrDefault(ExpressionSyntax optionalOfTExpression, ExpressionSyntax defaultValue) { return(SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, optionalOfTExpression, SyntaxFactory.IdentifierName(nameof(ImmutableObjectGraph.Optional <int> .GetValueOrDefault))), SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(defaultValue))))); }
private async Task <Document> AddBackingFieldAsync(Document document, SyntaxNode equalsSyntax, CancellationToken cancellationToken) { var pds = equalsSyntax as PropertyDeclarationSyntax; var propName = pds.Identifier.ToString(); var fieldName = "_" + char.ToLowerInvariant(propName[0]) + propName.Substring(1); var fieldType = pds.GetTypeName(); var backingField = SyntaxFactory.FieldDeclaration( SyntaxFactory.VariableDeclaration( SyntaxFactory.ParseTypeName(fieldType), SyntaxFactory.SeparatedList( new[] { SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(fieldName)), }))) .AddModifiers(SyntaxFactory.Token(SyntaxKind.PrivateKeyword)); PropertyDeclarationSyntax newProperty = SyntaxFactory.PropertyDeclaration(SyntaxFactory.ParseTypeName(fieldType), propName) .AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword)); newProperty = newProperty.AddAccessorListAccessors( SyntaxFactory.AccessorDeclaration( SyntaxKind.GetAccessorDeclaration, SyntaxFactory.Block( SyntaxFactory.List(new[] { SyntaxFactory.ReturnStatement(SyntaxFactory.IdentifierName(fieldName)), })))); var setProperty = SyntaxFactory.ExpressionStatement( SyntaxFactory.AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.IdentifierName(fieldName), SyntaxFactory.IdentifierName("value")), SyntaxFactory.Token(SyntaxKind.SemicolonToken)); var onPropertyChangedCall = SyntaxFactory.ExpressionStatement( SyntaxFactory.InvocationExpression( SyntaxFactory.IdentifierName("OnPropertyChanged")) .AddArgumentListArguments( SyntaxFactory.Argument( SyntaxFactory.InvocationExpression( SyntaxFactory.IdentifierName("nameof")) .AddArgumentListArguments( SyntaxFactory.Argument( SyntaxFactory.IdentifierName(propName)))))); newProperty = newProperty.AddAccessorListAccessors( SyntaxFactory.AccessorDeclaration( SyntaxKind.SetAccessorDeclaration, SyntaxFactory.Block(SyntaxFactory.List(new[] { setProperty, onPropertyChangedCall, })))); var oldRoot = await document.GetSyntaxRootAsync(cancellationToken); var newNodes = new List <SyntaxNode> { backingField, newProperty, }; var newRoot = oldRoot.ReplaceNode(pds, newNodes); return(document.WithSyntaxRoot(newRoot)); }
static async Task <Document> UseContainsCheckAsync(Document document, InvocationExpressionSyntax invocation, string replacementMethod, CancellationToken cancellationToken) { var editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false); var memberAccess = (MemberAccessExpressionSyntax)invocation.Expression; var invocationExpressionSyntax = (InvocationExpressionSyntax)invocation.ArgumentList.Arguments[0].Expression; var anyMethodInvocation = (MemberAccessExpressionSyntax)invocationExpressionSyntax.Expression; var anyTarget = anyMethodInvocation.Expression; editor.ReplaceNode( invocation, invocation.WithArgumentList( SyntaxFactory.ArgumentList( SyntaxFactory.SeparatedList(invocationExpressionSyntax.ArgumentList.Arguments.Insert(0, SyntaxFactory.Argument(anyTarget))))) .WithExpression(memberAccess.WithName(SyntaxFactory.IdentifierName(replacementMethod)))); return(editor.GetChangedDocument()); }
private async Task <Document> ConvertToDependencyPropertyAsync(Document document, PropertyDeclarationSyntax autoProperty, ClassDeclarationSyntax cls, CancellationToken cancellationToken) { var type = autoProperty.Type.ToString(); var propName = autoProperty.Identifier.Text; var propNameProperty = $"{propName}Property"; var propNamePropertyChanged = $"On{propName}PropertyChanged"; var clsName = cls.Identifier.ToString(); var defaultValue = autoProperty.Initializer != null?autoProperty.Initializer.Value.ToString() : "null"; // http://roslynquoter.azurewebsites.net/ var members = new MemberDeclarationSyntax[] { SyntaxFactory.PropertyDeclaration( SyntaxFactory.IdentifierName(type), SyntaxFactory.Identifier(propName)) .WithModifiers( SyntaxFactory.TokenList( SyntaxFactory.Token( SyntaxKind.PublicKeyword))) .WithAccessorList( SyntaxFactory.AccessorList( SyntaxFactory.List <AccessorDeclarationSyntax>( new AccessorDeclarationSyntax[] { SyntaxFactory.AccessorDeclaration( SyntaxKind.GetAccessorDeclaration, SyntaxFactory.Block( SyntaxFactory.SingletonList <StatementSyntax>( SyntaxFactory.ReturnStatement( SyntaxFactory.CastExpression( SyntaxFactory.IdentifierName(type), SyntaxFactory.InvocationExpression( SyntaxFactory.IdentifierName( @"GetValue")) .WithArgumentList( SyntaxFactory.ArgumentList( SyntaxFactory.SingletonSeparatedList <ArgumentSyntax>( SyntaxFactory.Argument( SyntaxFactory.IdentifierName(propNameProperty)))) .WithOpenParenToken( SyntaxFactory.Token( SyntaxKind.OpenParenToken)) .WithCloseParenToken( SyntaxFactory.Token( SyntaxKind.CloseParenToken)))) .WithOpenParenToken( SyntaxFactory.Token( SyntaxKind.OpenParenToken)) .WithCloseParenToken( SyntaxFactory.Token( SyntaxKind.CloseParenToken))) .WithReturnKeyword( SyntaxFactory.Token( SyntaxKind.ReturnKeyword)) .WithSemicolonToken( SyntaxFactory.Token( SyntaxKind.SemicolonToken)))) .WithOpenBraceToken( SyntaxFactory.Token( SyntaxKind.OpenBraceToken)) .WithCloseBraceToken( SyntaxFactory.Token( SyntaxKind.CloseBraceToken))) .WithKeyword( SyntaxFactory.Token( SyntaxKind.GetKeyword)), SyntaxFactory.AccessorDeclaration( SyntaxKind.SetAccessorDeclaration, SyntaxFactory.Block( SyntaxFactory.SingletonList <StatementSyntax>( SyntaxFactory.ExpressionStatement( SyntaxFactory.InvocationExpression( SyntaxFactory.IdentifierName( @"SetValue")) .WithArgumentList( SyntaxFactory.ArgumentList( SyntaxFactory.SeparatedList <ArgumentSyntax>( new SyntaxNodeOrToken[] { SyntaxFactory.Argument( SyntaxFactory.IdentifierName(propNameProperty)), SyntaxFactory.Token( SyntaxKind.CommaToken), SyntaxFactory.Argument( SyntaxFactory.IdentifierName( @"value")) })) .WithOpenParenToken( SyntaxFactory.Token( SyntaxKind.OpenParenToken)) .WithCloseParenToken( SyntaxFactory.Token( SyntaxKind.CloseParenToken)))) .WithSemicolonToken( SyntaxFactory.Token( SyntaxKind.SemicolonToken)))) .WithOpenBraceToken( SyntaxFactory.Token( SyntaxKind.OpenBraceToken)) .WithCloseBraceToken( SyntaxFactory.Token( SyntaxKind.CloseBraceToken))) .WithKeyword( SyntaxFactory.Token( SyntaxKind.SetKeyword)) })) .WithOpenBraceToken( SyntaxFactory.Token( SyntaxKind.OpenBraceToken)) .WithCloseBraceToken( SyntaxFactory.Token( SyntaxKind.CloseBraceToken))), SyntaxFactory.FieldDeclaration( SyntaxFactory.VariableDeclaration( SyntaxFactory.IdentifierName( @"DependencyProperty")) .WithVariables( SyntaxFactory.SingletonSeparatedList <VariableDeclaratorSyntax>( SyntaxFactory.VariableDeclarator( SyntaxFactory.Identifier(propNameProperty)) .WithInitializer( SyntaxFactory.EqualsValueClause( SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName( @"DependencyProperty"), SyntaxFactory.IdentifierName( @"Register")) .WithOperatorToken( SyntaxFactory.Token( SyntaxKind.DotToken))) .WithArgumentList( SyntaxFactory.ArgumentList( SyntaxFactory.SeparatedList <ArgumentSyntax>( new SyntaxNodeOrToken[] { SyntaxFactory.Argument( SyntaxFactory.InvocationExpression( SyntaxFactory.IdentifierName( @"nameof")) .WithArgumentList( SyntaxFactory.ArgumentList( SyntaxFactory.SingletonSeparatedList <ArgumentSyntax>( SyntaxFactory.Argument( SyntaxFactory.IdentifierName(propName)))) .WithOpenParenToken( SyntaxFactory.Token( SyntaxKind.OpenParenToken)) .WithCloseParenToken( SyntaxFactory.Token( SyntaxKind.CloseParenToken)))), SyntaxFactory.Token( SyntaxKind.CommaToken), SyntaxFactory.Argument( SyntaxFactory.TypeOfExpression( SyntaxFactory.IdentifierName(type)) .WithKeyword( SyntaxFactory.Token( SyntaxKind.TypeOfKeyword)) .WithOpenParenToken( SyntaxFactory.Token( SyntaxKind.OpenParenToken)) .WithCloseParenToken( SyntaxFactory.Token( SyntaxKind.CloseParenToken))), SyntaxFactory.Token( SyntaxKind.CommaToken), SyntaxFactory.Argument( SyntaxFactory.TypeOfExpression( SyntaxFactory.IdentifierName(clsName)) .WithKeyword( SyntaxFactory.Token( SyntaxKind.TypeOfKeyword)) .WithOpenParenToken( SyntaxFactory.Token( SyntaxKind.OpenParenToken)) .WithCloseParenToken( SyntaxFactory.Token( SyntaxKind.CloseParenToken))), SyntaxFactory.Token( SyntaxKind.CommaToken), SyntaxFactory.Argument( SyntaxFactory.ObjectCreationExpression( SyntaxFactory.IdentifierName( @"PropertyMetadata")) .WithNewKeyword( SyntaxFactory.Token( SyntaxKind.NewKeyword)) .WithArgumentList( SyntaxFactory.ArgumentList( SyntaxFactory.SeparatedList <ArgumentSyntax>( new SyntaxNodeOrToken[] { SyntaxFactory.Argument( autoProperty.Initializer == null ? SyntaxFactory.DefaultExpression(SyntaxFactory.IdentifierName(type)) as ExpressionSyntax : SyntaxFactory.LiteralExpression( SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal( SyntaxFactory.TriviaList(), autoProperty.Initializer.Value.ToString(), autoProperty.Initializer.Value.ToString(), SyntaxFactory.TriviaList()))), SyntaxFactory.Token( SyntaxKind.CommaToken), SyntaxFactory.Argument( SyntaxFactory.IdentifierName(propNamePropertyChanged)) })) .WithOpenParenToken( SyntaxFactory.Token( SyntaxKind.OpenParenToken)) .WithCloseParenToken( SyntaxFactory.Token( SyntaxKind.CloseParenToken)))) })) .WithOpenParenToken( SyntaxFactory.Token( SyntaxKind.OpenParenToken)) .WithCloseParenToken( SyntaxFactory.Token( SyntaxKind.CloseParenToken)))) .WithEqualsToken( SyntaxFactory.Token( SyntaxKind.EqualsToken)))))) .WithModifiers( SyntaxFactory.TokenList( new [] { SyntaxFactory.Token( SyntaxKind.PublicKeyword), SyntaxFactory.Token( SyntaxKind.StaticKeyword), SyntaxFactory.Token( SyntaxKind.ReadOnlyKeyword) })) .WithSemicolonToken( SyntaxFactory.Token( SyntaxKind.SemicolonToken)), SyntaxFactory.MethodDeclaration( SyntaxFactory.PredefinedType( SyntaxFactory.Token( SyntaxKind.VoidKeyword)), SyntaxFactory.Identifier(propNamePropertyChanged)) .WithModifiers( SyntaxFactory.TokenList( new [] { SyntaxFactory.Token( SyntaxKind.PrivateKeyword), SyntaxFactory.Token( SyntaxKind.StaticKeyword) })) .WithParameterList( SyntaxFactory.ParameterList( SyntaxFactory.SeparatedList <ParameterSyntax>( new SyntaxNodeOrToken[] { SyntaxFactory.Parameter( SyntaxFactory.Identifier( @"d")) .WithType( SyntaxFactory.IdentifierName( @"DependencyObject")), SyntaxFactory.Token( SyntaxKind.CommaToken), SyntaxFactory.Parameter( SyntaxFactory.Identifier( @"e")) .WithType( SyntaxFactory.IdentifierName( @"DependencyPropertyChangedEventArgs")) })) .WithOpenParenToken( SyntaxFactory.Token( SyntaxKind.OpenParenToken)) .WithCloseParenToken( SyntaxFactory.Token( SyntaxKind.CloseParenToken))) .WithBody( SyntaxFactory.Block( SyntaxFactory.List <StatementSyntax>( new StatementSyntax[] { SyntaxFactory.LocalDeclarationStatement( SyntaxFactory.VariableDeclaration( SyntaxFactory.IdentifierName( @"var")) .WithVariables( SyntaxFactory.SingletonSeparatedList <VariableDeclaratorSyntax>( SyntaxFactory.VariableDeclarator( SyntaxFactory.Identifier( @"source")) .WithInitializer( SyntaxFactory.EqualsValueClause( SyntaxFactory.BinaryExpression( SyntaxKind.AsExpression, SyntaxFactory.IdentifierName( @"d"), SyntaxFactory.IdentifierName(clsName)) .WithOperatorToken( SyntaxFactory.Token( SyntaxKind.AsKeyword))) .WithEqualsToken( SyntaxFactory.Token( SyntaxKind.EqualsToken)))))) .WithSemicolonToken( SyntaxFactory.Token( SyntaxKind.SemicolonToken)), SyntaxFactory.IfStatement( SyntaxFactory.BinaryExpression( SyntaxKind.NotEqualsExpression, SyntaxFactory.IdentifierName( @"source"), SyntaxFactory.LiteralExpression( SyntaxKind.NullLiteralExpression) .WithToken( SyntaxFactory.Token( SyntaxKind.NullKeyword))) .WithOperatorToken( SyntaxFactory.Token( SyntaxKind.ExclamationEqualsToken)), SyntaxFactory.Block( //SyntaxFactory.SingletonList<StatementSyntax>( // SyntaxFactory.Token(SyntaxKind.SingleLineCommentTrivia)), SyntaxFactory.SingletonList <StatementSyntax>( SyntaxFactory.LocalDeclarationStatement( SyntaxFactory.VariableDeclaration( SyntaxFactory.IdentifierName( @"var")) .WithVariables( SyntaxFactory.SingletonSeparatedList <VariableDeclaratorSyntax>( SyntaxFactory.VariableDeclarator( SyntaxFactory.Identifier( @"value")) .WithInitializer( SyntaxFactory.EqualsValueClause( SyntaxFactory.CastExpression( SyntaxFactory.IdentifierName(type), SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName( @"e"), SyntaxFactory.IdentifierName( @"NewValue")) .WithOperatorToken( SyntaxFactory.Token( SyntaxKind.DotToken))) .WithOpenParenToken( SyntaxFactory.Token( SyntaxKind.OpenParenToken)) .WithCloseParenToken( SyntaxFactory.Token( SyntaxKind.CloseParenToken))) .WithEqualsToken( SyntaxFactory.Token( SyntaxKind.EqualsToken)))))) .WithSemicolonToken( SyntaxFactory.Token( SyntaxFactory.TriviaList(), SyntaxKind.SemicolonToken, SyntaxFactory.TriviaList( SyntaxFactory.Comment( @" // TODO: Handle new value.")))))) .WithOpenBraceToken( SyntaxFactory.Token( SyntaxKind.OpenBraceToken)) .WithCloseBraceToken( SyntaxFactory.Token( SyntaxKind.CloseBraceToken))) .WithIfKeyword( SyntaxFactory.Token( SyntaxKind.IfKeyword)) .WithOpenParenToken( SyntaxFactory.Token( SyntaxKind.OpenParenToken)) .WithCloseParenToken( SyntaxFactory.Token( SyntaxKind.CloseParenToken)) })) .WithOpenBraceToken( SyntaxFactory.Token( SyntaxKind.OpenBraceToken)) .WithCloseBraceToken( SyntaxFactory.Token( SyntaxKind.CloseBraceToken))) }; // Replace old with new var oldRoot = await document.GetSyntaxRootAsync(cancellationToken) .ConfigureAwait(false); var newRoot = oldRoot.ReplaceNode(autoProperty, members); return(document.WithSyntaxRoot(newRoot)); }
private MemberDeclarationSyntax CreateToDerivedTypeMethod(MetaType derivedType) { var derivedTypeName = GetFullyQualifiedSymbolName(derivedType.TypeSymbol); var thatLocal = SyntaxFactory.IdentifierName("that"); var body = new List <StatementSyntax>(); // var that = this as DerivedType; body.Add(SyntaxFactory.LocalDeclarationStatement( SyntaxFactory.VariableDeclaration( varType, SyntaxFactory.SingletonSeparatedList( SyntaxFactory.VariableDeclarator(thatLocal.Identifier) .WithInitializer(SyntaxFactory.EqualsValueClause( SyntaxFactory.BinaryExpression( SyntaxKind.AsExpression, SyntaxFactory.ThisExpression(), derivedTypeName))))))); // this.GetType() var thisDotGetType = SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ThisExpression(), SyntaxFactory.IdentifierName("GetType")), SyntaxFactory.ArgumentList()); // {0}.Equals(typeof(derivedType)) var thisTypeIsEquivalentToDerivedType = SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, thisDotGetType, SyntaxFactory.IdentifierName(nameof(Type.Equals))), SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument( SyntaxFactory.TypeOfExpression(derivedTypeName))))); var ifEquivalentTypeBlock = new List <StatementSyntax>(); var fieldsBeyond = derivedType.GetFieldsBeyond(this.generator.applyToMetaType); if (fieldsBeyond.Any()) { Func <MetaField, ExpressionSyntax> isUnchanged = v => SyntaxFactory.ParenthesizedExpression( v.IsRequired ? // ({0} == that.{1}) SyntaxFactory.BinaryExpression( SyntaxKind.EqualsExpression, v.NameAsField, SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, thatLocal, v.NameAsProperty)) : // (!{0}.IsDefined || {0}.Value == that.{1}) SyntaxFactory.BinaryExpression( SyntaxKind.LogicalOrExpression, SyntaxFactory.PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, Syntax.OptionalIsDefined(v.NameAsField)), SyntaxFactory.BinaryExpression( SyntaxKind.EqualsExpression, Syntax.OptionalValue(v.NameAsField), SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, thatLocal, v.NameAsProperty)))); var noChangesExpression = fieldsBeyond.Select(isUnchanged).ChainBinaryExpressions(SyntaxKind.LogicalAndExpression); ifEquivalentTypeBlock.Add(SyntaxFactory.IfStatement( noChangesExpression, SyntaxFactory.ReturnStatement(thatLocal))); } else { ifEquivalentTypeBlock.Add(SyntaxFactory.ReturnStatement(thatLocal)); } // if (that != null && this.GetType().IsEquivalentTo(typeof(derivedType))) { ... } body.Add(SyntaxFactory.IfStatement( SyntaxFactory.BinaryExpression( SyntaxKind.LogicalAndExpression, SyntaxFactory.BinaryExpression(SyntaxKind.NotEqualsExpression, thatLocal, SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression)), thisTypeIsEquivalentToDerivedType), SyntaxFactory.Block(ifEquivalentTypeBlock))); // return DerivedType.CreateWithIdentity(...) body.Add(SyntaxFactory.ReturnStatement( SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, derivedTypeName, CreateWithIdentityMethodName), this.generator.CreateArgumentList(this.generator.applyToMetaType.AllFields, asOptional: OptionalStyle.WhenNotRequired) .AddArguments(RequiredIdentityArgumentFromProperty) .AddArguments(this.generator.CreateArgumentList(fieldsBeyond, ArgSource.Argument).Arguments.ToArray())))); return(SyntaxFactory.MethodDeclaration( derivedTypeName, GetToTypeMethodName(derivedType.TypeSymbol.Name).Identifier) .AddModifiers( SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.VirtualKeyword)) .WithParameterList(this.generator.CreateParameterList(fieldsBeyond, ParameterStyle.OptionalOrRequired)) .WithBody(SyntaxFactory.Block(body))); }
public static InvocationExpressionSyntax InvokeWithNamedArguments(string target, string methodName, params string[] parameterNames) { var arguments = parameterNames.Select(pn => SyntaxFactory.Argument(SyntaxFactory.IdentifierName(pn))).AsArgumentList(); return(Invoke(target, methodName, arguments)); }
/// <summary> /// Emits the control builder invocation. /// </summary> public string EmitInvokeControlBuilder(Type controlType, string virtualPath) { UseType(controlType); var builderName = "c" + CurrentControlIndex + "_builder"; var untypedName = "c" + CurrentControlIndex + "_untyped"; var name = "c" + CurrentControlIndex; CurrentControlIndex++; CurrentStatements.Add( SyntaxFactory.LocalDeclarationStatement( SyntaxFactory.VariableDeclaration(SyntaxFactory.IdentifierName("var")).WithVariables( SyntaxFactory.VariableDeclarator(builderName).WithInitializer( SyntaxFactory.EqualsValueClause( SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName(ControlBuilderFactoryParameterName), SyntaxFactory.IdentifierName(GetControlBuilderFunctionName) ), SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(new[] { SyntaxFactory.Argument(EmitStringLiteral(virtualPath)) })) ) ) ) ) ) ); CurrentStatements.Add( SyntaxFactory.LocalDeclarationStatement( SyntaxFactory.VariableDeclaration(SyntaxFactory.IdentifierName("var")).WithVariables( SyntaxFactory.VariableDeclarator(untypedName).WithInitializer( SyntaxFactory.EqualsValueClause( SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName(builderName), SyntaxFactory.IdentifierName(BuildControlFunctionName) ), SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(new[] { SyntaxFactory.Argument(SyntaxFactory.IdentifierName(ControlBuilderFactoryParameterName)) })) ) ) ) ) ) ); CurrentStatements.Add( SyntaxFactory.LocalDeclarationStatement( SyntaxFactory.VariableDeclaration(SyntaxFactory.IdentifierName("var")).WithVariables( SyntaxFactory.VariableDeclarator(name).WithInitializer( SyntaxFactory.EqualsValueClause( SyntaxFactory.CastExpression(ParseTypeName(controlType), SyntaxFactory.IdentifierName(untypedName) ) ) ) ) ) ); return(name); }
public static InvocationExpressionSyntax InvokeMethodOnSelf(string methodName, params string[] parameterNames) { var arguments = parameterNames.Select(pn => SyntaxFactory.Argument(SyntaxFactory.IdentifierName(pn))); return(InvokeMethodOnSelf(methodName, arguments)); }
public ExpressionSyntax CreateDotvvmPropertyIdentifier(DotvvmProperty property) { if (property is GroupedDotvvmProperty) { var gprop = (GroupedDotvvmProperty)property; string fieldName; if (!cachedGroupedDotvvmProperties.TryGetValue(gprop, out fieldName)) { fieldName = $"_staticCachedGroupProperty_{cachedGroupedDotvvmProperties.Count}"; cachedGroupedDotvvmProperties.Add(gprop, fieldName); otherDeclarations.Add(SyntaxFactory.FieldDeclaration( SyntaxFactory.VariableDeclaration(ParseTypeName(typeof(DotvvmProperty)), SyntaxFactory.SingletonSeparatedList( SyntaxFactory.VariableDeclarator(fieldName) .WithInitializer(SyntaxFactory.EqualsValueClause( SyntaxFactory.InvocationExpression( SyntaxFactory.ParseName(gprop.PropertyGroup.DeclaringType.FullName + "." + gprop.PropertyGroup.DescriptorField.Name + "." + nameof(DotvvmPropertyGroup.GetDotvvmProperty)), SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList( SyntaxFactory.Argument(this.EmitStringLiteral(gprop.GroupMemberName)) )) ) )) ) ) )); } return(SyntaxFactory.ParseName(fieldName)); } else { return(SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, ParseTypeName(property.DeclaringType), SyntaxFactory.IdentifierName(property.Name + "Property"))); } }
public override SyntaxNode VisitMemberAccessExpression(MemberAccessExpressionSyntax node) { //1. 先处理查询类方法的lambda表达式内的实体成员访问 if (queryMethodCtx.HasAny && queryMethodCtx.Current.InLambdaExpression) //t.Customer.Name { var identifier = FindIndentifierForMemberAccessExpression(node); if (identifier != null) { var replacedIdentifier = queryMethodCtx.Current.ReplaceLambdaParameter(identifier); if (replacedIdentifier != null) { var sb = StringBuilderCache.Acquire(); BuildQueryMethodMemberAccess(node, replacedIdentifier, sb); //TODO:判断是否由上级处理换行 //return SyntaxFactory.ParseExpression(sb.ToString()).WithTrailingTrivia(GetEndOfLineTrivia(node, false)); return(SyntaxFactory.ParseExpression(StringBuilderCache.GetStringAndRelease(sb)).WithTriviaFrom(node)); } } } else if (cqlFilterLambdaParameter != null) { if (node.Expression is IdentifierNameSyntax identifier && identifier.Identifier.ValueText == cqlFilterLambdaParameter) { var sb = StringBuilderCache.Acquire(); CqlLambdaHelper.BuildCqlLambdaGetValue(sb, cqlFilterLambdaParameter, -1, node.Name.Identifier.ValueText, node, SemanticModel); return(SyntaxFactory.ParseExpression(StringBuilderCache.GetStringAndRelease(sb))); } } var expSymbol = SemanticModel.GetSymbolInfo(node).Symbol; //2. 判断有无拦截器 var interceptor = GetMemberAccessInterceptor(expSymbol); if (interceptor != null) { return(interceptor.VisitMemberAccess(node, expSymbol, this)); } //3. 正常处理成员访问 if (expSymbol != null) { //先处理存储类的属性或方法 var storeClass = TypeHelper.IsDataStoreClass(expSymbol.ContainingType); if (storeClass != null) { //根据DataStore名称找到相应的节点 var storeName = ((MemberAccessExpressionSyntax)node.Expression).Name; var storeNode = hub.DesignTree.FindDataStoreNodeByName(storeName.ToString()); var updateNode = SyntaxFactory.ParseExpression(string.Format("appbox.Store.{0}.Get({1}ul).{2}", storeClass, storeNode.Model.Id, node.Name)); return(updateNode.WithTriviaFrom(node)); } if (expSymbol.IsStatic && expSymbol is IMethodSymbol) //方法名称处理 { //处理需要转换类型的静态方法访问 var realTypeName = TypeHelper.GetRealTypeName(expSymbol.ContainingType); if (!string.IsNullOrEmpty(realTypeName)) { return(SyntaxFactory.ParseExpression($"{realTypeName}.{node.Name.Identifier.ValueText}")); } } else //非方法名称处理 { if (TypeHelper.IsEntityClass(expSymbol.ContainingType)) //处理实体成员访问 { //先处理TypeId静态成员(TODO:改用拦截器处理) if (node.Name.Identifier.ValueText == "TypeId") { var names = expSymbol.ContainingType.ToString().Split('.'); var appNode = hub.DesignTree.FindApplicationNodeByName(names[0]); var entityModelNode = hub.DesignTree.FindModelNodeByName(appNode.Model.Id, ModelType.Entity, names[2]); return(SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(entityModelNode.Model.Id))); } //判断成员是否属于实体成员 if (!expSymbol.ContainingType.ToString().In( new string[] { TypeHelper.Type_EntityBase, TypeHelper.Type_SysEntityBase, TypeHelper.Type_SqlEntityBase, TypeHelper.Type_CqlEntityBase })) { //TODO:判断是否AggregationRefField,返回的object类型,应使用BoxedValue处理 ITypeSymbol valueTypeSymbol = TypeHelper.GetSymbolType(expSymbol); var memberId = GetEntityMemberId(expSymbol); var oldTarget = (ExpressionSyntax)Visit(node.Expression); //TODO: cache methodName var methodName = (SimpleNameSyntax)SyntaxFactory.ParseName(TypeHelper.GenEntityMemberGetterOrSetter(valueTypeSymbol, true)); var getValueMethod = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, oldTarget, methodName); var arg1 = SyntaxFactory.Argument(SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(memberId))); var argList = SyntaxFactory.ArgumentList().AddArguments(arg1); return(SyntaxFactory.InvocationExpression(getValueMethod, argList)); } } else if (TypeHelper.IsEnumModel(expSymbol.ContainingType)) //处理枚举成员访问 { throw ExceptionHelper.NotImplemented(); //var names = expSymbol.ContainingType.ToString().Split('.'); //var enumModel = DesignHelper.DesignTimeModelContainer.GetEnumModel(names[0] + "." + names[2]); //int enumValue = 0; //for (int i = 0; i < enumModel.Items.Count; i++) //{ // if (enumModel.Items[i].Name == node.Name.Identifier.ValueText) // { // enumValue = enumModel.Items[i].Value; // } //} //return SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, //SyntaxFactory.Literal(enumValue)); } else if (expSymbol.IsStatic && (expSymbol is IPropertySymbol || expSymbol is IFieldSymbol)) { //处理需要转换为运行时类型的静态成员访问, eg: PersistentState.Detached var realTypeName = TypeHelper.GetRealTypeName(expSymbol.ContainingType); if (!string.IsNullOrEmpty(realTypeName)) { return(SyntaxFactory.ParseExpression($"{realTypeName}.{node.Name.Identifier.ValueText}")); } } } } return(base.VisitMemberAccessExpression(node)); }