/// <summary> /// This is jus a test to check the ability to preprocess the AST /// </summary> /// <param name="methodNode"></param> /// <param name="semanticModel"></param> /// <returns></returns> public static IMethodSymbol SimplifyASTForMethod(ref SyntaxNode methodNode, ref SemanticModel semanticModel) { var oldMethod = semanticModel.GetDeclaredSymbol(methodNode) as IMethodSymbol; var newMethodNode = MethodSimpifier.Test(methodNode); var annotation = new SyntaxAnnotation("Hi"); newMethodNode = newMethodNode.WithAdditionalAnnotations(annotation); var root = methodNode.SyntaxTree.GetRoot(); var newRoot = root.ReplaceNode(methodNode, newMethodNode); var oldCompilation = semanticModel.Compilation; var newCompilation = oldCompilation.ReplaceSyntaxTree(root.SyntaxTree, newRoot.SyntaxTree); var newSemanticModel = newCompilation.GetSemanticModel(newRoot.SyntaxTree); var recoveredMethodNode = newRoot.GetAnnotatedNodes(annotation).Single(); var method = newSemanticModel.GetDeclaredSymbol(recoveredMethodNode) as IMethodSymbol; methodNode = recoveredMethodNode; semanticModel = newSemanticModel; return method; }
private static bool CanRemoveTypeFromParameter( SyntaxNode node, SemanticModel semanticModel, CancellationToken cancellationToken) { // We reduce any the parameters that are contained inside ParameterList if (node != null && node.IsParentKind(SyntaxKind.ParameterList) && node.Parent.IsParentKind(SyntaxKind.ParenthesizedLambdaExpression)) { var parameterSyntax = (ParameterSyntax)node; if (parameterSyntax.Type != null) { var annotation = new SyntaxAnnotation(); var newParameterSyntax = parameterSyntax.WithType(null).WithAdditionalAnnotations(annotation); var oldLambda = node.FirstAncestorOrSelf<ParenthesizedLambdaExpressionSyntax>(); var newLambda = oldLambda.ReplaceNode(parameterSyntax, newParameterSyntax); var speculationAnalyzer = new SpeculationAnalyzer(oldLambda, newLambda, semanticModel, cancellationToken); newParameterSyntax = (ParameterSyntax)speculationAnalyzer.ReplacedExpression.GetAnnotatedNodesAndTokens(annotation).First(); var oldSymbol = semanticModel.GetDeclaredSymbol(parameterSyntax, cancellationToken); var newSymbol = speculationAnalyzer.SpeculativeSemanticModel.GetDeclaredSymbol(newParameterSyntax, cancellationToken); if (oldSymbol != null && newSymbol != null && oldSymbol.Type == newSymbol.Type) { return !speculationAnalyzer.ReplacementChangesSemantics(); } } } return false; }
protected override bool TryGetSimplifiedTypeNameInCaseContext(Document document, string fullyQualifiedTypeName, string firstEnumMemberName, int startPosition, int endPosition, CancellationToken cancellationToken, out string simplifiedTypeName) { simplifiedTypeName = string.Empty; var typeAnnotation = new SyntaxAnnotation(); var str = "case " + fullyQualifiedTypeName + "." + firstEnumMemberName + ":" + Environment.NewLine + " break;"; var textChange = new TextChange(new TextSpan(startPosition, endPosition - startPosition), str); var typeSpanToAnnotate = new TextSpan(startPosition + "case ".Length, fullyQualifiedTypeName.Length); var textWithCaseAdded = document.GetTextAsync(cancellationToken).WaitAndGetResult(cancellationToken).WithChanges(textChange); var documentWithCaseAdded = document.WithText(textWithCaseAdded); var syntaxRoot = documentWithCaseAdded.GetSyntaxRootSynchronously(cancellationToken); var nodeToReplace = syntaxRoot.DescendantNodes().FirstOrDefault(n => n.Span == typeSpanToAnnotate); if (nodeToReplace == null) { return false; } var updatedRoot = syntaxRoot.ReplaceNode(nodeToReplace, nodeToReplace.WithAdditionalAnnotations(typeAnnotation, Simplifier.Annotation)); var documentWithAnnotations = documentWithCaseAdded.WithSyntaxRoot(updatedRoot); var simplifiedDocument = Simplifier.ReduceAsync(documentWithAnnotations, cancellationToken: cancellationToken).Result; simplifiedTypeName = simplifiedDocument.GetSyntaxRootSynchronously(cancellationToken).GetAnnotatedNodesAndTokens(typeAnnotation).Single().ToString(); return true; }
private SyntaxToken AnnotationResolver( SyntaxNode node, TriviaLocation location, SyntaxAnnotation annotation, SyntaxNode callsite, MethodDeclarationSyntax method) { var token = node.GetAnnotatedNodesAndTokens(annotation).FirstOrDefault().AsToken(); if (token.RawKind != 0) { return token; } switch (location) { case TriviaLocation.BeforeBeginningOfSpan: return callsite.GetFirstToken(includeZeroWidth: true).GetPreviousToken(includeZeroWidth: true); case TriviaLocation.AfterEndOfSpan: return callsite.GetLastToken(includeZeroWidth: true).GetNextToken(includeZeroWidth: true); case TriviaLocation.AfterBeginningOfSpan: return method.Body.OpenBraceToken.GetNextToken(includeZeroWidth: true); case TriviaLocation.BeforeEndOfSpan: return method.Body.CloseBraceToken.GetPreviousToken(includeZeroWidth: true); } return Contract.FailWithReturn<SyntaxToken>("can't happen"); }
public static async Task<InsertionPoint> CreateAsync(SemanticDocument document, SyntaxNode node, CancellationToken cancellationToken) { var root = document.Root; var annotation = new SyntaxAnnotation(); var newRoot = root.AddAnnotations(SpecializedCollections.SingletonEnumerable(Tuple.Create(node, annotation))); return new InsertionPoint(await document.WithSyntaxRootAsync(newRoot, cancellationToken).ConfigureAwait(false), annotation); }
public static TypeSyntax GenerateTypeSyntax(this ITypeSymbol typeSymbol, SyntaxAnnotation simplifierAnnotation = null) { var typeSyntax = (TypeSyntax)generateTypeSyntaxMethod.Invoke(null, new object[] { typeSymbol }); if (simplifierAnnotation != null) return typeSyntax.WithAdditionalAnnotations(simplifierAnnotation); return typeSyntax; }
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var document = context.Document; if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles) return; var span = context.Span; if (!span.IsEmpty) return; var cancellationToken = context.CancellationToken; if (cancellationToken.IsCancellationRequested) return; var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (model.IsFromGeneratedCode(cancellationToken)) return; var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); SyntaxToken token = root.FindToken(span.Start); if (!token.IsKind(SyntaxKind.IdentifierToken)) return; var property = token.Parent as PropertyDeclarationSyntax; if (property == null || !property.Identifier.Span.Contains(span)) return; if (IsEmptyComputedProperty(property)) { context.RegisterRefactoring( CodeActionFactory.Create( token.Span, DiagnosticSeverity.Info, GettextCatalog.GetString("Convert to auto-property"), t2 => { var newRoot = root.ReplaceNode(property, CreateNewProperty(property).WithAdditionalAnnotations(Formatter.Annotation).WithLeadingTrivia(property.GetLeadingTrivia())); return Task.FromResult(document.WithSyntaxRoot(newRoot)); } ) ); return; } var field = GetBackingField(model, property); if (!IsValidField(field, property.Parent as TypeDeclarationSyntax)) return; //variable declarator->declaration->field declaration var backingFieldNode = root.FindNode(field.Locations.First().SourceSpan).Ancestors().OfType<FieldDeclarationSyntax>().First(); var propertyAnnotation = new SyntaxAnnotation(); var fieldAnnotation = new SyntaxAnnotation(); //annotate our property node and our field node root = root.ReplaceNode((SyntaxNode)property, property.WithAdditionalAnnotations(propertyAnnotation)); root = root.ReplaceNode((SyntaxNode)root.FindNode(backingFieldNode.Span), backingFieldNode.WithAdditionalAnnotations(fieldAnnotation)); context.RegisterRefactoring( CodeActionFactory.Create(token.Span, DiagnosticSeverity.Info, GettextCatalog.GetString("Convert to auto-property"), PerformAction(document, model, root, field.Name, CreateNewProperty(property), propertyAnnotation, fieldAnnotation)) ); }
internal SyntaxIdentifierWithTrailingTrivia(string text, GreenNode trailing, DiagnosticInfo[] diagnostics, SyntaxAnnotation[] annotations) : base(text, diagnostics, annotations) { if (trailing != null) { this.AdjustFlagsAndWidth(trailing); _trailing = trailing; } }
public static SyntaxNode RemoveInitializer(SyntaxNode root, ConstructorDeclarationSyntax constructor) { var annotation = new SyntaxAnnotation(); var ctor = constructor; var newRoot = root; newRoot = newRoot.ReplaceNode(ctor, ctor.WithAdditionalAnnotations(annotation)); ctor = (ConstructorDeclarationSyntax)newRoot.GetAnnotatedNodes(annotation).First(); var initializer = ctor.Initializer; if (RedundantInheritanceListCodeFixProvider.HasLineEnding(constructor.ParameterList)) { newRoot = newRoot.RemoveNode(initializer, SyntaxRemoveOptions.KeepNoTrivia); ctor = (ConstructorDeclarationSyntax)newRoot.GetAnnotatedNodes(annotation).First(); if (ctor.Body != null && ctor.Body.HasLeadingTrivia) { var lastTrivia = ctor.Body.GetLeadingTrivia().Last(); newRoot = lastTrivia.IsKind(SyntaxKind.EndOfLineTrivia) ? newRoot.ReplaceNode( ctor.Body, ctor.Body.WithoutLeadingTrivia()) : newRoot.ReplaceNode( ctor.Body, ctor.Body.WithLeadingTrivia(lastTrivia)); } } else { var trailingTrivia = SyntaxFactory.TriviaList(); if (initializer.HasTrailingTrivia) { trailingTrivia = initializer.GetTrailingTrivia(); } newRoot = newRoot.RemoveNode(initializer, SyntaxRemoveOptions.KeepNoTrivia); ctor = (ConstructorDeclarationSyntax)newRoot.GetAnnotatedNodes(annotation).First(); if (ctor.Body != null && ctor.Body.HasLeadingTrivia) { var lastTrivia = ctor.Body.GetLeadingTrivia().Last(); newRoot = newRoot.ReplaceNode( ctor.Body, ctor.Body.WithLeadingTrivia(trailingTrivia.Add(lastTrivia))); } else { if (initializer.HasTrailingTrivia) { newRoot = newRoot.ReplaceNode(ctor, ctor.WithTrailingTrivia(trailingTrivia)); } } } ctor = (ConstructorDeclarationSyntax)newRoot.GetAnnotatedNodes(annotation).First(); return newRoot.ReplaceNode(ctor, ctor.WithoutAnnotations(annotation)); }
internal WithTwoChildren(DiagnosticInfo[] diagnostics, SyntaxAnnotation[] annotations, GreenNode child0, GreenNode child1) : base(diagnostics, annotations) { this.SlotCount = 2; this.AdjustFlagsAndWidth(child0); _child0 = child0; this.AdjustFlagsAndWidth(child1); _child1 = child1; }
internal abstract Solution GetSolutionWithUpdatedOriginalType( Solution solutionWithFormattedInterfaceDocument, INamedTypeSymbol extractedInterfaceSymbol, IEnumerable<ISymbol> includedMembers, Dictionary<ISymbol, SyntaxAnnotation> symbolToDeclarationAnnotationMap, List<DocumentId> documentIds, SyntaxAnnotation typeNodeAnnotation, DocumentId documentIdWithTypeNode, CancellationToken cancellationToken);
private InsertionPoint(SemanticDocument document, SyntaxAnnotation annotation) { //Contract.ThrowIfNull(document); //Contract.ThrowIfNull(annotation); this.SemanticDocument = document; _annotation = annotation; _context = CreateLazyContextNode(); }
public void CodeCleaners_Annotation() { var document = CreateDocument("class C { }", LanguageNames.CSharp); var annotation = new SyntaxAnnotation(); document = document.WithSyntaxRoot(document.GetSyntaxRootAsync().Result.WithAdditionalAnnotations(annotation)); var cleanDocument = CodeCleaner.CleanupAsync(document, annotation).Result; Assert.Equal(document, cleanDocument); }
private ExtractMethodResult CreateExtractMethodResult( OperationStatus status, SemanticDocument semanticDocument, SyntaxAnnotation invocationAnnotation, SyntaxAnnotation methodAnnotation) { var newRoot = semanticDocument.Root; var annotatedTokens = newRoot.GetAnnotatedNodesAndTokens(invocationAnnotation); var methodDefinition = newRoot.GetAnnotatedNodesAndTokens(methodAnnotation).FirstOrDefault().AsNode(); return new SimpleExtractMethodResult(status, semanticDocument.Document, GetMethodNameAtInvocation(annotatedTokens), methodDefinition); }
public StatementResult( OperationStatus status, TextSpan originalSpan, TextSpan finalSpan, OptionSet options, bool selectionInExpression, SemanticDocument document, SyntaxAnnotation firstTokenAnnotation, SyntaxAnnotation lastTokenAnnotation) : base(status, originalSpan, finalSpan, options, selectionInExpression, document, firstTokenAnnotation, lastTokenAnnotation) { }
public override SyntaxNode VisitPropertyDeclaration(PropertyDeclarationSyntax property) { if (span.IntersectsWith(property.Span) && CodeGeneration.IsExpandableProperty(property, document)) { var annotation = new SyntaxAnnotation(); annotations.Add(annotation); return property.WithAdditionalAnnotations(annotation); } return base.VisitPropertyDeclaration(property); }
private static void HandleThisExpression(SyntaxNodeAnalysisContext context) { if (!context.Node.Parent.IsKind(SyntaxKind.SimpleMemberAccessExpression)) { return; } var memberAccessExpression = (MemberAccessExpressionSyntax)context.Node.Parent; var originalSymbolInfo = context.SemanticModel.GetSymbolInfo(memberAccessExpression, context.CancellationToken); if (originalSymbolInfo.Symbol == null) { return; } SyntaxNode speculationRoot; var annotation = new SyntaxAnnotation(); SemanticModel speculativeModel; StatementSyntax statement = context.Node.FirstAncestorOrSelf<StatementSyntax>(); if (statement != null) { var modifiedStatement = statement.ReplaceNode(memberAccessExpression, memberAccessExpression.Name.WithAdditionalAnnotations(annotation)); speculationRoot = modifiedStatement; if (!context.SemanticModel.TryGetSpeculativeSemanticModel(statement.SpanStart, modifiedStatement, out speculativeModel)) { return; } } else { ArrowExpressionClauseSyntax arrowExpressionClause = context.Node.FirstAncestorOrSelf<ArrowExpressionClauseSyntax>(); if (arrowExpressionClause == null) { return; } var modifiedArrowExpressionClause = arrowExpressionClause.ReplaceNode(memberAccessExpression, memberAccessExpression.Name.WithAdditionalAnnotations(annotation)); speculationRoot = modifiedArrowExpressionClause; if (!context.SemanticModel.TryGetSpeculativeSemanticModel(arrowExpressionClause.SpanStart, modifiedArrowExpressionClause, out speculativeModel)) { return; } } SyntaxNode mappedNode = speculationRoot.GetAnnotatedNodes(annotation).Single(); var newSymbolInfo = speculativeModel.GetSymbolInfo(mappedNode, context.CancellationToken); if (!Equals(originalSymbolInfo.Symbol, newSymbolInfo.Symbol)) { return; } context.ReportDiagnostic(Diagnostic.Create(Descriptor, context.Node.GetLocation())); }
public static Task<Document> CaseCorrectAsync(Document document, SyntaxAnnotation annotation, CancellationToken cancellationToken) { try { return (Task<Document>)caseCorrectAsyncMethod.Invoke(null, new object[] { document, annotation, cancellationToken }); } catch (TargetInvocationException ex) { ExceptionDispatchInfo.Capture(ex.InnerException).Throw(); return null; } }
public Expander( SemanticModel semanticModel, Func<SyntaxNode, bool> expandInsideNode, bool expandParameter, CancellationToken cancellationToken, SyntaxAnnotation annotationForReplacedAliasIdentifier = null) { _semanticModel = semanticModel; _expandInsideNode = expandInsideNode; _expandParameter = expandParameter; _cancellationToken = cancellationToken; _annotationForReplacedAliasIdentifier = annotationForReplacedAliasIdentifier; }
private static SyntaxNode RemoveDeclaration(SyntaxNode root, BaseListSyntax baseList, int redundantIndex) { var newBaseList = baseList .RemoveNode(baseList.Types[redundantIndex], SyntaxRemoveOptions.KeepNoTrivia) .WithAdditionalAnnotations(Formatter.Annotation); if (newBaseList.Types.Count != 0) { return root.ReplaceNode(baseList, newBaseList); } var baseTypeHadLineEnding = HasLineEnding(baseList.Types[redundantIndex]); var colonHadLineEnding = HasLineEnding(baseList.ColonToken); var typeNameHadLineEnding = HasLineEnding(((BaseTypeDeclarationSyntax)baseList.Parent).Identifier); var annotation = new SyntaxAnnotation(); var newRoot = root.ReplaceNode( baseList.Parent, baseList.Parent.WithAdditionalAnnotations(annotation)); var declaration = (BaseTypeDeclarationSyntax)newRoot.GetAnnotatedNodes(annotation).First(); newRoot = newRoot.RemoveNode(declaration.BaseList, SyntaxRemoveOptions.KeepNoTrivia); declaration = (BaseTypeDeclarationSyntax)newRoot.GetAnnotatedNodes(annotation).First(); var needsNewLine = !typeNameHadLineEnding && (colonHadLineEnding || baseTypeHadLineEnding); if (needsNewLine) { var trivia = SyntaxFactory.TriviaList(); if (declaration.Identifier.HasTrailingTrivia) { trivia = declaration.Identifier.TrailingTrivia; } trivia = colonHadLineEnding ? trivia.Add(baseList.ColonToken.TrailingTrivia.Last()) : trivia.AddRange(baseList.Types[redundantIndex].GetTrailingTrivia()); newRoot = newRoot.ReplaceToken( declaration.Identifier, declaration.Identifier .WithTrailingTrivia(trivia)); } declaration = (BaseTypeDeclarationSyntax)newRoot.GetAnnotatedNodes(annotation).First(); return newRoot.ReplaceNode( declaration, declaration.WithoutAnnotations(annotation)); }
protected GreenNode(ushort kind, DiagnosticInfo[] diagnostics, SyntaxAnnotation[] annotations) : this(kind, diagnostics) { if (annotations?.Length > 0) { foreach (var annotation in annotations) { if (annotation == null) throw new ArgumentException(paramName: nameof(annotations), message: "" /*CSharpResources.ElementsCannotBeNull*/); } this.flags |= NodeFlags.ContainsAnnotations; s_annotationsTable.Add(this, annotations); } }
internal SyntaxTokenWithTrivia(SyntaxKind kind, CSharpSyntaxNode leading, CSharpSyntaxNode trailing, DiagnosticInfo[] diagnostics, SyntaxAnnotation[] annotations) : base(kind, diagnostics, annotations) { if (leading != null) { this.AdjustFlagsAndWidth(leading); this.LeadingField = leading; } if (trailing != null) { this.AdjustFlagsAndWidth(trailing); this.TrailingField = trailing; } }
internal override Solution GetSolutionWithUpdatedOriginalType( Solution solutionWithFormattedInterfaceDocument, INamedTypeSymbol extractedInterfaceSymbol, IEnumerable<ISymbol> includedMembers, Dictionary<ISymbol, SyntaxAnnotation> symbolToDeclarationAnnotationMap, List<DocumentId> documentIds, SyntaxAnnotation typeNodeAnnotation, DocumentId documentIdWithTypeNode, CancellationToken cancellationToken) { var documentWithTypeNode = solutionWithFormattedInterfaceDocument.GetDocument(documentIdWithTypeNode); var root = documentWithTypeNode.GetCSharpSyntaxRootAsync(cancellationToken).WaitAndGetResult(cancellationToken); var typeDeclaration = root.GetAnnotatedNodes<TypeDeclarationSyntax>(typeNodeAnnotation).Single(); var docId = solutionWithFormattedInterfaceDocument.GetDocument(typeDeclaration.SyntaxTree).Id; var implementedInterfaceTypeSyntax = extractedInterfaceSymbol.TypeParameters.Any() ? SyntaxFactory.GenericName( SyntaxFactory.Identifier(extractedInterfaceSymbol.Name), SyntaxFactory.TypeArgumentList(SyntaxFactory.SeparatedList(extractedInterfaceSymbol.TypeParameters.Select(p => SyntaxFactory.ParseTypeName(p.Name))))) : SyntaxFactory.ParseTypeName(extractedInterfaceSymbol.Name); var baseList = typeDeclaration.BaseList ?? SyntaxFactory.BaseList(); var updatedBaseList = baseList.WithTypes(SyntaxFactory.SeparatedList(baseList.Types.Union(new[] { SyntaxFactory.SimpleBaseType(implementedInterfaceTypeSyntax) }))); if (!baseList.Types.Any()) { // If we're adding the first element to the base list, then we need to move // trivia from the type name itself to the end of the base list updatedBaseList = updatedBaseList.WithLeadingTrivia(SyntaxFactory.Space); if (typeDeclaration.TypeParameterList != null) { updatedBaseList = updatedBaseList.WithTrailingTrivia(typeDeclaration.TypeParameterList.GetTrailingTrivia()); typeDeclaration = typeDeclaration.WithTypeParameterList(typeDeclaration.TypeParameterList.WithoutTrailingTrivia()); } else { updatedBaseList = updatedBaseList.WithTrailingTrivia(typeDeclaration.Identifier.TrailingTrivia); typeDeclaration = typeDeclaration.WithIdentifier(typeDeclaration.Identifier.WithTrailingTrivia()); } } var updatedTypeDeclaration = typeDeclaration.WithBaseList(updatedBaseList.WithAdditionalAnnotations(Formatter.Annotation)); var updatedRoot = root.ReplaceNode(root.GetAnnotatedNodes<TypeDeclarationSyntax>(typeNodeAnnotation).Single(), updatedTypeDeclaration); var solutionWithOriginalTypeUpdated = solutionWithFormattedInterfaceDocument.WithDocumentSyntaxRoot(docId, updatedRoot, PreservationMode.PreserveIdentity); return solutionWithOriginalTypeUpdated; }
internal static IDocument ExpandProperty(this IDocument document, PropertyDeclarationSyntax property) { // Annotate the property declaration so we can find it later. var propertyAnnotation = new SyntaxAnnotation(); var newRoot = document.GetSyntaxRoot().ReplaceNode( property, property.WithAdditionalAnnotations(propertyAnnotation)); IFieldSymbol backingField; return document .UpdateSyntaxRoot(newRoot) .GetOrCreateBackingField(propertyAnnotation, out backingField) .ExpandProperty(propertyAnnotation, backingField); }
public static SyntaxToken ToIdentifierToken(this string identifier, bool isQueryContext = false) { string text = identifier.EscapeIdentifier(isQueryContext); if ((text.Length == 0) || (text[0] != '@')) { return SyntaxFactory.Identifier(text); } string valueText = identifier.StartsWith("@") ? identifier.Substring(1) : identifier; SyntaxTriviaList leading = new SyntaxTriviaList(); SyntaxToken token = SyntaxFactory.Identifier(leading, SyntaxKind.None, '@' + valueText, valueText, new SyntaxTriviaList()); if (!identifier.StartsWith("@")) { SyntaxAnnotation[] annotations = new SyntaxAnnotation[] { Simplifier.Annotation }; token = token.WithAdditionalAnnotations(annotations); } return token; }
public GeneratedCode( OperationStatus status, SemanticDocument document, SyntaxAnnotation methodNameAnnotation, SyntaxAnnotation callsiteAnnotation, SyntaxAnnotation methodDefinitionAnnotation) { Contract.ThrowIfNull(document); Contract.ThrowIfNull(methodNameAnnotation); Contract.ThrowIfNull(callsiteAnnotation); Contract.ThrowIfNull(methodDefinitionAnnotation); this.Status = status; this.SemanticDocument = document; this.MethodNameAnnotation = methodNameAnnotation; this.CallSiteAnnotation = callsiteAnnotation; this.MethodDefinitionAnnotation = methodDefinitionAnnotation; }
protected override bool TryGetSimplifiedTypeName(Document documentWithFullyQualifiedTypeName, TextSpan updatedTextSpan, CancellationToken cancellationToken, out string simplifiedTypeName) { simplifiedTypeName = string.Empty; var typeAnnotation = new SyntaxAnnotation(); var syntaxRoot = documentWithFullyQualifiedTypeName.GetSyntaxRootAsync(cancellationToken).WaitAndGetResult(cancellationToken); var nodeToReplace = syntaxRoot.DescendantNodes().FirstOrDefault(n => n.Span == updatedTextSpan); if (nodeToReplace == null) { return false; } var updatedRoot = syntaxRoot.ReplaceNode(nodeToReplace, nodeToReplace.WithAdditionalAnnotations(typeAnnotation, Simplifier.Annotation)); var documentWithAnnotations = documentWithFullyQualifiedTypeName.WithSyntaxRoot(updatedRoot); var simplifiedDocument = Simplifier.ReduceAsync(documentWithAnnotations, cancellationToken: cancellationToken).WaitAndGetResult(cancellationToken); simplifiedTypeName = simplifiedDocument.GetSyntaxRootAsync(cancellationToken).WaitAndGetResult(cancellationToken).GetAnnotatedNodesAndTokens(typeAnnotation).Single().ToString(); return true; }
internal SyntaxIdentifierWithTrivia( SyntaxKind contextualKind, string text, string valueText, GreenNode leading, GreenNode trailing, DiagnosticInfo[] diagnostics, SyntaxAnnotation[] annotations) : base(contextualKind, text, valueText, diagnostics, annotations) { if (leading != null) { this.AdjustFlagsAndWidth(leading); _leading = leading; } if (trailing != null) { this.AdjustFlagsAndWidth(trailing); _trailing = trailing; } }
internal async static Task<Document> GetChangeDocumentWithPragmaAdjustedAsync( Document document, TextSpan diagnosticSpan, SuppressionTargetInfo suppressionTargetInfo, Func<SyntaxToken, TextSpan, Task<SyntaxToken>> getNewStartToken, Func<SyntaxToken, TextSpan, Task<SyntaxToken>> getNewEndToken, CancellationToken cancellationToken) { var startToken = suppressionTargetInfo.StartToken; var endToken = suppressionTargetInfo.EndToken; var nodeWithTokens = suppressionTargetInfo.NodeWithTokens; var root = await nodeWithTokens.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); var startAndEndTokenAreTheSame = startToken == endToken; SyntaxToken newStartToken = await getNewStartToken(startToken, diagnosticSpan).ConfigureAwait(false); SyntaxToken newEndToken = endToken; if (startAndEndTokenAreTheSame) { var annotation = new SyntaxAnnotation(); newEndToken = root.ReplaceToken(startToken, newStartToken.WithAdditionalAnnotations(annotation)).GetAnnotatedTokens(annotation).Single(); var spanChange = newStartToken.LeadingTrivia.FullSpan.Length - startToken.LeadingTrivia.FullSpan.Length; diagnosticSpan = new TextSpan(diagnosticSpan.Start + spanChange, diagnosticSpan.Length); } newEndToken = await getNewEndToken(newEndToken, diagnosticSpan).ConfigureAwait(false); SyntaxNode newNode; if (startAndEndTokenAreTheSame) { newNode = nodeWithTokens.ReplaceToken(startToken, newEndToken); } else { newNode = nodeWithTokens.ReplaceTokens(new[] { startToken, endToken }, (o, n) => o == startToken ? newStartToken : newEndToken); } var newRoot = root.ReplaceNode(nodeWithTokens, newNode); return document.WithSyntaxRoot(newRoot); }
public void RoundTripSyntaxNodeWithMultipleReferencesToSameAnnotation() { var text = "public class C {}"; var tree = SyntaxFactory.ParseSyntaxTree(text); var annotation = new SyntaxAnnotation(); var root = tree.GetCompilationUnitRoot().WithAdditionalAnnotations(annotation, annotation); Assert.Equal(true, root.ContainsAnnotations); Assert.Equal(true, root.HasAnnotation(annotation)); var stream = new MemoryStream(); root.SerializeTo(stream); stream.Position = 0; var droot = CSharpSyntaxNode.DeserializeFrom(stream); var dtext = droot.ToFullString(); Assert.Equal(text, dtext); Assert.Equal(true, droot.ContainsAnnotations); Assert.Equal(true, droot.HasAnnotation(annotation)); Assert.Equal(true, droot.IsEquivalentTo(tree.GetCompilationUnitRoot())); }
protected abstract Task <TNodeUnderContainer> GetStatementOrInitializerContainingInvocationToExtractedMethodAsync(SyntaxAnnotation callsiteAnnotation, CancellationToken cancellationToken);
public static IList <SyntaxNode> MatchGetAnnotatedNodes(this PatternNode self, SyntaxNode node, SyntaxAnnotation syntaxAnnotation, SemanticModel semanticModel = null) { return(self.EnumerateGetAnnotatedNodes(node, syntaxAnnotation, semanticModel).ToList()); }
private static ExpressionSyntax GetNullCoalescing(ExpressionSyntax whenTrue, ExpressionSyntax whenFalse, ExpressionSyntax compared, SemanticModel semanticModel, SyntaxAnnotation annotation) { if (CSharpEquivalenceChecker.AreEquivalent(whenTrue, compared)) { var createdExpression = SyntaxFactory.BinaryExpression( SyntaxKind.CoalesceExpression, compared, whenFalse) .WithAdditionalAnnotations(annotation); return(createdExpression); } if (CSharpEquivalenceChecker.AreEquivalent(whenFalse, compared)) { var createdExpression = SyntaxFactory.BinaryExpression( SyntaxKind.CoalesceExpression, compared, whenTrue) .WithAdditionalAnnotations(annotation); return(createdExpression); } return(GetSimplificationFromInvocations(whenTrue, whenFalse, null, compared, semanticModel, annotation, isNullCoalescing: true)); }
/// <summary> /// Reduce the sub-trees annotated with <see cref="Annotation" /> found within the subtrees identified with the specified <paramref name="annotation"/>. /// The annotated node and all child nodes will be reduced. /// </summary> public static async Task <Document> ReduceAsync(Document document, SyntaxAnnotation annotation, OptionSet optionSet = null, CancellationToken cancellationToken = default(CancellationToken)) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); return(await ReduceAsync(document, root.GetAnnotatedNodesAndTokens(annotation).Select(t => t.FullSpan), optionSet, cancellationToken).ConfigureAwait(false)); }
private void Reduce( Document document, SyntaxNode root, ImmutableArray <NodeOrTokenToReduce> nodesAndTokensToReduce, IEnumerable <AbstractReducer> reducers, OptionSet optionSet, CancellationToken cancellationToken, SemanticModel semanticModel, ConcurrentDictionary <SyntaxNode, SyntaxNode> reducedNodesMap, ConcurrentDictionary <SyntaxToken, SyntaxToken> reducedTokensMap) { Contract.ThrowIfFalse(nodesAndTokensToReduce.Any()); // Reduce each node or token in the given list by running it through each reducer. var simplifyTasks = new Task[nodesAndTokensToReduce.Length]; for (int i = 0; i < nodesAndTokensToReduce.Length; i++) { var nodeOrTokenToReduce = nodesAndTokensToReduce[i]; simplifyTasks[i] = Task.Run(async() => { var nodeOrToken = nodeOrTokenToReduce.OriginalNodeOrToken; var simplifyAllDescendants = nodeOrTokenToReduce.SimplifyAllDescendants; var semanticModelForReduce = semanticModel; var currentNodeOrToken = nodeOrTokenToReduce.NodeOrToken; var isNode = nodeOrToken.IsNode; foreach (var reducer in reducers) { cancellationToken.ThrowIfCancellationRequested(); var rewriter = reducer.CreateExpressionRewriter(optionSet, cancellationToken); do { if (currentNodeOrToken.SyntaxTree != semanticModelForReduce.SyntaxTree) { // currentNodeOrToken was simplified either by a previous reducer or // a previous iteration of the current reducer. // Create a speculative semantic model for the simplified node for semantic queries. // Certain node kinds (expressions/statements) require non-null parent nodes during simplification. // However, the reduced nodes haven't been parented yet, so do the required parenting using the original node's parent. if (currentNodeOrToken.Parent == null && nodeOrToken.Parent != null && (currentNodeOrToken.IsToken || currentNodeOrToken.AsNode() is TExpressionSyntax || currentNodeOrToken.AsNode() is TStatementSyntax || currentNodeOrToken.AsNode() is TCrefSyntax)) { var annotation = new SyntaxAnnotation(); currentNodeOrToken = currentNodeOrToken.WithAdditionalAnnotations(annotation); var replacedParent = isNode ? nodeOrToken.Parent.ReplaceNode(nodeOrToken.AsNode(), currentNodeOrToken.AsNode()) : nodeOrToken.Parent.ReplaceToken(nodeOrToken.AsToken(), currentNodeOrToken.AsToken()); currentNodeOrToken = replacedParent .ChildNodesAndTokens() .Single((c) => c.HasAnnotation(annotation)); } if (isNode) { var currentNode = currentNodeOrToken.AsNode(); if (this.CanNodeBeSimplifiedWithoutSpeculation(nodeOrToken.AsNode())) { // Since this node cannot be speculated, we are replacing the Document with the changes and get a new SemanticModel SyntaxAnnotation marker = new SyntaxAnnotation(); var newRoot = root.ReplaceNode(nodeOrToken.AsNode(), currentNode.WithAdditionalAnnotations(marker)); var newDocument = document.WithSyntaxRoot(newRoot); semanticModelForReduce = await newDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); newRoot = await semanticModelForReduce.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); currentNodeOrToken = newRoot.DescendantNodes().Single((c) => c.HasAnnotation(marker)); } else { // Create speculative semantic model for simplified node. semanticModelForReduce = GetSpeculativeSemanticModel(ref currentNode, semanticModel, nodeOrToken.AsNode()); currentNodeOrToken = currentNode; } } } // Reduce the current node or token. currentNodeOrToken = rewriter.VisitNodeOrToken(currentNodeOrToken, semanticModelForReduce, simplifyAllDescendants); }while (rewriter.HasMoreWork); } // If nodeOrToken was simplified, add it to the appropriate dictionary of replaced nodes/tokens. if (currentNodeOrToken != nodeOrToken) { if (isNode) { reducedNodesMap[nodeOrToken.AsNode()] = currentNodeOrToken.AsNode(); } else { reducedTokensMap[nodeOrToken.AsToken()] = currentNodeOrToken.AsToken(); } } }, cancellationToken); } Task.WaitAll(simplifyTasks, cancellationToken); }
public abstract SyntaxNode Expand(SyntaxNode node, SemanticModel semanticModel, SyntaxAnnotation annotationForReplacedAliasIdentifier, Func <SyntaxNode, bool> expandInsideNode, bool expandParameter, CancellationToken cancellationToken);
public static IEnumerable <T> GetAnnotatedNodes <T>(this SyntaxNode node, SyntaxAnnotation syntaxAnnotation) where T : SyntaxNode { return(node.GetAnnotatedNodesAndTokens(syntaxAnnotation).Select(n => n.AsNode()).OfType <T>()); }
private static SyntaxNode GetUniformDepthRandomAnnotatedNode(SyntaxNode root, SyntaxAnnotation annotation) { //Console.WriteLine("Tree height for root: " + root); var levelNodes = new MultiValueDictionary <int, SyntaxNode>(); GetTreeNodeHeights(root, levelNodes); //foreach (var level in levelNodes.Keys) { // Console.WriteLine("level " + level + ": " + string.Join(", ", levelNodes[level].Select(n => n.ToString()).ToArray())); //} int levelIndex = RandomValueGenerator.Instance.GetInt(levelNodes.Count); var syntaxNodes = levelNodes.Values.ElementAt(levelIndex); int nodeIndex = RandomValueGenerator.Instance.GetInt(syntaxNodes.Count); SyntaxNode node = syntaxNodes.ElementAt(nodeIndex); //Console.WriteLine("random select node: " + node + ", level index=" + levelIndex + ", node index=" + nodeIndex); return(GetRandomAnnotatedNode(root, annotation)); }
protected async override Task <SyntaxNode> RewriteFieldNameAndAccessibility(string originalFieldName, bool makePrivate, Document document, SyntaxAnnotation declarationAnnotation, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var declarator = root.GetAnnotatedNodes <VariableDeclaratorSyntax>(declarationAnnotation).FirstOrDefault(); // There may be no field to rewrite if this document is part of a set of linked files // and the declaration is not conditionally compiled in this document's project. if (declarator == null) { return(root); } var tempAnnotation = new SyntaxAnnotation(); var newIdentifier = SyntaxFactory.Identifier(originalFieldName) .WithTrailingTrivia(declarator.Identifier.TrailingTrivia) .WithLeadingTrivia(declarator.Identifier.LeadingTrivia); var updatedDeclarator = declarator.WithIdentifier(newIdentifier).WithAdditionalAnnotations(tempAnnotation); root = root.ReplaceNode(declarator, updatedDeclarator); document = document.WithSyntaxRoot(root); var declaration = root.GetAnnotatedNodes <SyntaxNode>(tempAnnotation).First().Parent as VariableDeclarationSyntax; if (declaration.Variables.Count == 1) { var fieldSyntax = declaration.Parent as FieldDeclarationSyntax; var modifierKinds = new[] { SyntaxKind.PrivateKeyword, SyntaxKind.ProtectedKeyword, SyntaxKind.InternalKeyword, SyntaxKind.PublicKeyword }; if (makePrivate) { var modifiers = SpecializedCollections.SingletonEnumerable(SyntaxFactory.Token(SyntaxKind.PrivateKeyword)) .Concat(fieldSyntax.Modifiers.Where(m => !modifierKinds.Contains(m.Kind()))); root = root.ReplaceNode(fieldSyntax, fieldSyntax.WithModifiers( SyntaxFactory.TokenList(modifiers)) .WithAdditionalAnnotations(Formatter.Annotation) .WithLeadingTrivia(fieldSyntax.GetLeadingTrivia()) .WithTrailingTrivia(fieldSyntax.GetTrailingTrivia())); } } else if (declaration.Variables.Count > 1 && makePrivate) { document = document.WithSyntaxRoot(root); var codeGenService = new CSharpCodeGenerationService(document.Project.Solution.Workspace.Services.GetLanguageServices(LanguageNames.CSharp)); var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); declarator = root.GetAnnotatedNodes <VariableDeclaratorSyntax>(tempAnnotation).First(); declaration = declarator.Parent as VariableDeclarationSyntax; var field = semanticModel.GetDeclaredSymbol(declarator, cancellationToken) as IFieldSymbol; var fieldToAdd = declarationAnnotation.AddAnnotationToSymbol(CodeGenerationSymbolFactory.CreateFieldSymbol( field.GetAttributes(), Accessibility.Private, new DeclarationModifiers().WithIsStatic(field.IsStatic).WithIsReadOnly(field.IsReadOnly).WithIsConst(field.IsConst), field.Type, field.Name, field.HasConstantValue, field.ConstantValue, declarator.Initializer)); var withField = await codeGenService.AddFieldAsync(document.Project.Solution, field.ContainingType, fieldToAdd, new CodeGenerationOptions(), cancellationToken).ConfigureAwait(false); root = await withField.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); declarator = root.GetAnnotatedNodes <VariableDeclaratorSyntax>(tempAnnotation).First(); declaration = declarator.Parent as VariableDeclarationSyntax; return(root.RemoveNode(declarator, SyntaxRemoveOptions.KeepNoTrivia)); } return(root); }
public override SyntaxNode Expand(SyntaxNode node, SemanticModel semanticModel, SyntaxAnnotation annotationForReplacedAliasIdentifier, Func <SyntaxNode, bool> expandInsideNode, bool expandParameter, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.Simplifier_ExpandNode, cancellationToken)) { if (node is AttributeSyntax || node is AttributeArgumentSyntax || node is ConstructorInitializerSyntax || node is ExpressionSyntax || node is FieldDeclarationSyntax || node is StatementSyntax || node is CrefSyntax || node is XmlNameAttributeSyntax || node is TypeConstraintSyntax || node is BaseTypeSyntax) { var rewriter = new Expander(semanticModel, expandInsideNode, expandParameter, cancellationToken, annotationForReplacedAliasIdentifier); return(rewriter.Visit(node)); } else { throw new ArgumentException(CSharpWorkspaceResources.Only_attributes_constructor_initializers_expressions_or_statements_can_be_made_explicit, nameof(node)); } } }
public RemoveAnnotationRewriter(SyntaxAnnotation annotationToRemove) : base(visitIntoStructuredTrivia: false) { this.annotationToRemove = annotationToRemove ?? throw new ArgumentNullException(nameof(annotationToRemove)); }
public AwaitCallRewriter(SyntaxAnnotation callAnnotation) : base(visitIntoStructuredTrivia: false) { this.callAnnotation = callAnnotation ?? throw new ArgumentNullException(nameof(callAnnotation)); }
public static SyntaxToken GetTokenWithAnnotation(this SemanticDocument document, SyntaxAnnotation annotation) { return(document.Root.GetAnnotatedNodesAndTokens(annotation).Single().AsToken()); }
private static CodeAction GetActionToExecute(CodeFixContext context, SyntaxNode root, SyntaxNode nodeToChange, SyntaxNode nodeToAdd, SyntaxAnnotation annotation) { return(CodeAction.Create( Title, c => { var nodeToAddWithoutAnnotation = RemoveAnnotation(nodeToAdd, annotation); var newRoot = root.ReplaceNode( nodeToChange, nodeToAddWithoutAnnotation.WithTriviaFrom(nodeToChange).WithAdditionalAnnotations(Formatter.Annotation)); return Task.FromResult(context.Document.WithSyntaxRoot(newRoot)); })); }
protected async override Task <SyntaxNode> RewriteFieldNameAndAccessibility(string originalFieldName, bool makePrivate, Document document, SyntaxAnnotation declarationAnnotation, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var declarator = root.GetAnnotatedNodes <VariableDeclarationSyntax>(declarationAnnotation).FirstOrDefault(); // There may be no field to rewrite if this document is part of a set of linked files // and the declaration is not conditionally compiled in this document's project. if (declarator == null) { return(root); } var tempAnnotation = new SyntaxAnnotation(); var escapedName = originalFieldName.EscapeIdentifier(); var newIdentifier = SyntaxFactory.Identifier( leading: SyntaxTriviaList.Create(SyntaxFactory.ElasticMarker), contextualKind: SyntaxKind.IdentifierName, text: escapedName, valueText: originalFieldName, trailing: SyntaxTriviaList.Create(SyntaxFactory.ElasticMarker)) .WithTrailingTrivia(declarator.Identifier.TrailingTrivia) .WithLeadingTrivia(declarator.Identifier.LeadingTrivia); var updatedDeclarator = declarator.WithIdentifier(newIdentifier).WithAdditionalAnnotations(tempAnnotation); root = root.ReplaceNode(declarator, updatedDeclarator); document = document.WithSyntaxRoot(root); var declaration = root.GetAnnotatedNodes <SyntaxNode>(tempAnnotation).First().Parent as VariableDeclarationSyntax; if (declaration != null) { var fieldSyntax = declaration.Parent as FieldDeclarationSyntax; var modifierKinds = new[] { SyntaxKind.PrivateKeyword, SyntaxKind.ProtectedKeyword, SyntaxKind.InternalKeyword, SyntaxKind.PublicKeyword }; if (makePrivate) { var modifiers = SpecializedCollections.SingletonEnumerable(SyntaxFactory.Token(SyntaxKind.PrivateKeyword)) .Concat(fieldSyntax.Modifiers.Where(m => !modifierKinds.Contains(m.Kind()))); root = root.ReplaceNode(fieldSyntax, fieldSyntax.WithModifiers( SyntaxFactory.TokenList(modifiers)) .WithAdditionalAnnotations(Formatter.Annotation) .WithLeadingTrivia(fieldSyntax.GetLeadingTrivia()) .WithTrailingTrivia(fieldSyntax.GetTrailingTrivia())); } } return(root); }
private static ConstructorDeclarationSyntax GetConstructor(SyntaxNode newRoot, SyntaxAnnotation annotation) { return((ConstructorDeclarationSyntax)newRoot.GetAnnotatedNodes(annotation).First()); }
public SyntaxNode Replace(SyntaxNode root, SemanticModel model, Func <SyntaxNode, Tuple <SyntaxTree, SemanticModel> > updater) { var discards = root .DescendantNodes() .OfType <DiscardDesignationSyntax>(); var outVars = root .DescendantNodes() .OfType <ArgumentSyntax>() .Where(arg => arg.Expression is DeclarationExpressionSyntax && arg.RefOrOutKeyword.Kind() == SyntaxKind.OutKeyword); var outDiscardVars = root .DescendantNodes() .OfType <ArgumentSyntax>() .Where(arg => { if (arg.Expression is IdentifierNameSyntax ins && ins.Identifier.ValueText == DISCARD_IDENTIFIER && arg.RefOrOutKeyword.Kind() == SyntaxKind.OutKeyword) { var si = model.GetSymbolInfo(arg.Expression); return(si.Symbol == null || si.Symbol.Kind == SymbolKind.Discard); } return(false); }); var discardAssigments = root .DescendantNodes() .OfType <AssignmentExpressionSyntax>() .Where(assignment => { if (assignment.Left is IdentifierNameSyntax ins && ins.Identifier.ValueText == DISCARD_IDENTIFIER) { var si = model.GetSymbolInfo(assignment.Left); return(si.Symbol == null || si.Symbol.Kind == SymbolKind.Discard); } return(false); }); var updatedStatements = new Dictionary <StatementSyntax, List <LocalDeclarationStatementSyntax> >(); var updatedDiscards = new Dictionary <DiscardDesignationSyntax, string>(); var updatedDiscardVars = new Dictionary <ArgumentSyntax, string>(); var tempIndex = 0; foreach (var discard in discards) { try { var typeInfo = model.GetTypeInfo(discard.Parent); var beforeStatement = discard.Ancestors().OfType <StatementSyntax>().FirstOrDefault(); if (beforeStatement != null) { if (typeInfo.Type != null) { string instance = DISCARD_VARIABLE + ++tempIndex; if (beforeStatement.Parent != null) { var info = LocalUsageGatherer.GatherInfo(model, beforeStatement.Parent); while (info.DirectlyOrIndirectlyUsedLocals.Any(s => s.Name == instance) || info.Names.Contains(instance)) { instance = DISCARD_VARIABLE + ++tempIndex; } } var locals = updatedStatements.ContainsKey(beforeStatement) ? updatedStatements[beforeStatement] : new List <LocalDeclarationStatementSyntax>(); var varDecl = SyntaxFactory.VariableDeclaration(SyntaxHelper.GenerateTypeSyntax(typeInfo.Type, model, discard.Parent.GetLocation().SourceSpan.Start)).WithVariables(SyntaxFactory.SingletonSeparatedList <VariableDeclaratorSyntax>( SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(instance)) )); var local = SyntaxFactory.LocalDeclarationStatement(varDecl).NormalizeWhitespace().WithTrailingTrivia(SyntaxFactory.Whitespace("\n")); locals.Add(local); updatedStatements[beforeStatement] = locals; updatedDiscards[discard] = instance; } else if (discard.Parent is DeclarationPatternSyntax && !(discard.Parent.Parent is IsPatternExpressionSyntax)) { string instance = DISCARD_VARIABLE + ++tempIndex; if (beforeStatement.Parent != null) { var info = LocalUsageGatherer.GatherInfo(model, beforeStatement.Parent); while (info.DirectlyOrIndirectlyUsedLocals.Any(s => s.Name == instance) || info.Names.Contains(instance)) { instance = DISCARD_VARIABLE + ++tempIndex; } } updatedDiscards[discard] = instance; } } } catch (Exception e) { throw new ReplacerException(discard, e); } } foreach (var discardVar in outDiscardVars) { try { var typeInfo = model.GetTypeInfo(discardVar.Expression); if (typeInfo.Type != null) { var beforeStatement = discardVar.Ancestors().OfType <StatementSyntax>().FirstOrDefault(); if (beforeStatement != null) { string instance = DISCARD_VARIABLE + ++tempIndex; if (beforeStatement.Parent != null) { var info = LocalUsageGatherer.GatherInfo(model, beforeStatement.Parent); while (info.DirectlyOrIndirectlyUsedLocals.Any(s => s.Name == instance) || info.Names.Contains(instance)) { instance = DISCARD_VARIABLE + ++tempIndex; } } var locals = updatedStatements.ContainsKey(beforeStatement) ? updatedStatements[beforeStatement] : new List <LocalDeclarationStatementSyntax>(); var varDecl = SyntaxFactory.VariableDeclaration(SyntaxHelper.GenerateTypeSyntax(typeInfo.Type, model, discardVar.Expression.GetLocation().SourceSpan.Start)).WithVariables(SyntaxFactory.SingletonSeparatedList <VariableDeclaratorSyntax>( SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(instance)) )); var local = SyntaxFactory.LocalDeclarationStatement(varDecl).NormalizeWhitespace().WithTrailingTrivia(SyntaxFactory.Whitespace("\n")); locals.Add(local); updatedStatements[beforeStatement] = locals; updatedDiscardVars[discardVar] = instance; } } } catch (Exception e) { throw new ReplacerException(discardVar, e); } } foreach (var outVar in outVars) { try { if (((DeclarationExpressionSyntax)outVar.Expression).Designation.Kind() == SyntaxKind.DiscardDesignation) { continue; } var typeInfo = model.GetTypeInfo(outVar.Expression); if (typeInfo.Type != null) { var beforeStatement = outVar.Ancestors().OfType <StatementSyntax>().FirstOrDefault(); if (beforeStatement != null) { if (outVar.Expression is DeclarationExpressionSyntax de) { var designation = de.Designation as SingleVariableDesignationSyntax; if (designation != null) { var locals = updatedStatements.ContainsKey(beforeStatement) ? updatedStatements[beforeStatement] : new List <LocalDeclarationStatementSyntax>(); var varDecl = SyntaxFactory.VariableDeclaration(SyntaxHelper.GenerateTypeSyntax(typeInfo.Type, model, outVar.Expression.GetLocation().SourceSpan.Start)).WithVariables(SyntaxFactory.SingletonSeparatedList <VariableDeclaratorSyntax>( SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(designation.Identifier.ValueText)) )); locals.Add(SyntaxFactory.LocalDeclarationStatement(varDecl).NormalizeWhitespace().WithTrailingTrivia(SyntaxFactory.Whitespace("\n"))); updatedStatements[beforeStatement] = locals; } } } } } catch (Exception e) { throw new ReplacerException(outVar, e); } } var annotatedStatemnts = new Dictionary <SyntaxAnnotation, List <LocalDeclarationStatementSyntax> >(); var annotatedDiscards = new Dictionary <SyntaxAnnotation, string>(); var annotatedDiscardVars = new Dictionary <SyntaxAnnotation, string>(); var annotatedAssigments = new List <SyntaxAnnotation>(); var keys = updatedStatements.Keys.Cast <SyntaxNode>() .Concat(updatedDiscards.Keys.Cast <SyntaxNode>()) .Concat(updatedDiscardVars.Keys.Cast <SyntaxNode>()) .Concat(discardAssigments); root = root.ReplaceNodes(keys, (n1, n2) => { var annotation = new SyntaxAnnotation(); if (n1 is AssignmentExpressionSyntax) { annotatedAssigments.Add(annotation); } else if (n1 is DiscardDesignationSyntax) { annotatedDiscards[annotation] = updatedDiscards[(DiscardDesignationSyntax)n1]; } else if (n1 is ArgumentSyntax) { annotatedDiscardVars[annotation] = updatedDiscardVars[(ArgumentSyntax)n1]; } else { annotatedStatemnts[annotation] = updatedStatements[(StatementSyntax)n1]; } n2 = n2.WithAdditionalAnnotations(annotation); return(n2); }); foreach (var annotation in annotatedDiscards.Keys) { var annotatedNode = root.GetAnnotatedNodes(annotation).First(); var name = annotatedDiscards[annotation]; root = root.ReplaceNode(annotatedNode, SyntaxFactory.SingleVariableDesignation(SyntaxFactory.Identifier(name)).NormalizeWhitespace()); } foreach (var annotation in annotatedDiscardVars.Keys) { var annotatedNode = root.GetAnnotatedNodes(annotation).First(); var name = annotatedDiscardVars[annotation]; root = root.ReplaceNode(annotatedNode, ((ArgumentSyntax)annotatedNode).WithExpression(SyntaxFactory.IdentifierName(name))); } foreach (var annotation in annotatedAssigments) { var annotatedNode = root.GetAnnotatedNodes(annotation).First(); root = root.ReplaceNode(annotatedNode, ((AssignmentExpressionSyntax)annotatedNode).WithLeft(SyntaxFactory.IdentifierName("Bridge.Script.Discard"))); } outVars = root .DescendantNodes() .OfType <ArgumentSyntax>() .Where(arg => arg.Expression is DeclarationExpressionSyntax && arg.RefOrOutKeyword.Kind() == SyntaxKind.OutKeyword); root = root.ReplaceNodes(outVars, (n1, n2) => { var designation = ((DeclarationExpressionSyntax)n2.Expression).Designation as SingleVariableDesignationSyntax; if (designation == null) { return(n2); } return(SyntaxFactory.Argument(SyntaxFactory.IdentifierName(designation.Identifier)).WithRefKindKeyword(SyntaxFactory.Token(SyntaxKind.OutKeyword)).WithRefOrOutKeyword(SyntaxFactory.Token(SyntaxKind.OutKeyword)).NormalizeWhitespace()); }); foreach (var annotation in annotatedStatemnts.Keys) { var annotatedNode = root.GetAnnotatedNodes(annotation).First(); var varStatements = annotatedStatemnts[annotation]; if (annotatedNode.Parent is BlockSyntax || !(annotatedNode is StatementSyntax)) { root = root.InsertNodesBefore(annotatedNode, varStatements); } else { var list = new List <StatementSyntax>(varStatements); list.Add((StatementSyntax)annotatedNode); root = root.ReplaceNode(annotatedNode, SyntaxFactory.Block(list).NormalizeWhitespace()); } } var discardPatterns = root.DescendantNodes().OfType <IsPatternExpressionSyntax>().Where(pattern => pattern.Pattern is DeclarationPatternSyntax dp && dp.Designation.Kind() == SyntaxKind.DiscardDesignation); if (discardPatterns.Any()) { root = root.ReplaceNodes(discardPatterns, (n1, n2) => { return(SyntaxFactory.LiteralExpression(SyntaxKind.TrueLiteralExpression, SyntaxFactory.Token(SyntaxKind.TrueKeyword))); }); } return(root); }
private static CompilationUnitSyntax MoveUsingsInsideNamespace(CompilationUnitSyntax compilationUnit, SyntaxAnnotation warningAnnotation) { // Get the compilation unit usings and set them up to format when moved. var usingsToAdd = compilationUnit.Usings.Select( directive => directive.WithAdditionalAnnotations(Formatter.Annotation, warningAnnotation)); // Remove usings and fix leading trivia for compilation unit. var compilationUnitWithoutUsings = compilationUnit.WithUsings(default);
private static ExpressionSyntax GetSimplificationFromInvocations(ExpressionSyntax expression1, ExpressionSyntax expression2, ExpressionSyntax condition, ExpressionSyntax compared, SemanticModel semanticModel, SyntaxAnnotation annotation, bool isNullCoalescing) { var methodCall2 = expression2 as InvocationExpressionSyntax; if (!(expression1 is InvocationExpressionSyntax methodCall1) || methodCall2 == null) { return(null); } var methodSymbol1 = semanticModel.GetSymbolInfo(methodCall1).Symbol; var methodSymbol2 = semanticModel.GetSymbolInfo(methodCall2).Symbol; if (methodSymbol1 == null || methodSymbol2 == null || !methodSymbol1.Equals(methodSymbol2)) { return(null); } var newArgumentList = SyntaxFactory.ArgumentList(); for (var i = 0; i < methodCall1.ArgumentList.Arguments.Count; i++) { var arg1 = methodCall1.ArgumentList.Arguments[i]; var arg2 = methodCall2.ArgumentList.Arguments[i]; var expr1 = arg1.Expression.RemoveParentheses(); var expr2 = arg2.Expression.RemoveParentheses(); if (!CSharpEquivalenceChecker.AreEquivalent(expr1, expr2)) { ExpressionSyntax createdExpression; if (isNullCoalescing) { var arg1IsCompared = CSharpEquivalenceChecker.AreEquivalent(expr1, compared); var expression = arg1IsCompared ? expr2 : expr1; createdExpression = SyntaxFactory.BinaryExpression(SyntaxKind.CoalesceExpression, compared, expression); } else { createdExpression = SyntaxFactory.ConditionalExpression(condition, expr1, expr2); } newArgumentList = newArgumentList.AddArguments( SyntaxFactory.Argument( arg1.NameColon, arg1.RefOrOutKeyword, createdExpression.WithAdditionalAnnotations(annotation))); } else { newArgumentList = newArgumentList.AddArguments(arg1.WithExpression(arg1.Expression.RemoveParentheses())); } } return(methodCall1.WithArgumentList(newArgumentList)); }
private async Task <Document> AddImportDirectivesFromSyntaxesAsync( Document document, CodeGenerationPreferences preferences, IEnumerable <SyntaxNode> syntaxNodes, IAddImportsService addImportsService, SyntaxGenerator generator, bool allowInHiddenRegions, CancellationToken cancellationToken) { using var _1 = ArrayBuilder <SyntaxNode> .GetInstance(out var importsToAdd); using var _2 = ArrayBuilder <SyntaxNode> .GetInstance(out var nodesToSimplify); var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var model = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); var nodesWithExplicitNamespaces = syntaxNodes .Select(n => (syntaxnode: n, namespaceSymbol: GetExplicitNamespaceSymbol(n, model))); var addedSymbols = new HashSet <INamespaceSymbol>(); foreach (var(node, namespaceSymbol) in nodesWithExplicitNamespaces) { if (namespaceSymbol is null) { continue; } cancellationToken.ThrowIfCancellationRequested(); nodesToSimplify.Add(node); if (addedSymbols.Contains(namespaceSymbol)) { continue; } var namespaceSyntax = GenerateNamespaceImportDeclaration(namespaceSymbol, generator); if (addImportsService.HasExistingImport(model.Compilation, root, node, namespaceSyntax, generator)) { continue; } if (IsInsideNamespace(node, namespaceSymbol, model, cancellationToken)) { continue; } addedSymbols.Add(namespaceSymbol); importsToAdd.Add(namespaceSyntax); } if (nodesToSimplify.Count == 0) { return(document); } var annotation = new SyntaxAnnotation(); root = root.ReplaceNodes( nodesToSimplify, (o, r) => r.WithAdditionalAnnotations(Simplifier.Annotation, annotation)); var first = root.DescendantNodesAndSelf().First(x => x.HasAnnotation(annotation)); var last = root.DescendantNodesAndSelf().Last(x => x.HasAnnotation(annotation)); var context = first.GetCommonRoot(last); root = addImportsService.AddImports( model.Compilation, root, context, importsToAdd, generator, preferences, allowInHiddenRegions, cancellationToken); return(document.WithSyntaxRoot(root)); }
private static ConditionalExpressionSyntax GetConditionalExpression(ExpressionSyntax condition, ExpressionSyntax expressionTrue, ExpressionSyntax expressionFalse, SyntaxAnnotation annotation) { return(SyntaxFactory.ConditionalExpression( condition, expressionTrue, expressionFalse) .WithAdditionalAnnotations(annotation)); }
private (ImmutableArray <SyntaxNode> imports, IEnumerable <INamespaceSymbol> namespaceSymbols, SyntaxNode?context) GetImportDirectivesFromSyntaxesAsync( IEnumerable <SyntaxNode> syntaxNodes, ref SyntaxNode root, SemanticModel model, IAddImportsService addImportsService, SyntaxGenerator generator, CancellationToken cancellationToken ) { var importsToAdd = ArrayBuilder <SyntaxNode> .GetInstance(); var nodesWithExplicitNamespaces = syntaxNodes .Select(n => (syntaxnode: n, namespaceSymbol: GetExplicitNamespaceSymbol(n, model))) .Where(x => x.namespaceSymbol != null); var nodesToSimplify = ArrayBuilder <SyntaxNode> .GetInstance(); var addedSymbols = new HashSet <INamespaceSymbol>(); foreach (var(node, namespaceSymbol) in nodesWithExplicitNamespaces) { cancellationToken.ThrowIfCancellationRequested(); nodesToSimplify.Add(node); if (addedSymbols.Contains(namespaceSymbol)) { continue; } var namespaceSyntax = GenerateNamespaceImportDeclaration(namespaceSymbol, generator); if (addImportsService.HasExistingImport(model.Compilation, root, node, namespaceSyntax)) { continue; } if (IsInsideNamespace(node, namespaceSymbol, model, cancellationToken)) { continue; } addedSymbols.Add(namespaceSymbol); importsToAdd.Add(namespaceSyntax); } if (nodesToSimplify.Count == 0) { nodesToSimplify.Free(); return(importsToAdd.ToImmutableAndFree(), addedSymbols, null); } var annotation = new SyntaxAnnotation(); root = root.ReplaceNodes( nodesToSimplify, (o, r) => r.WithAdditionalAnnotations(Simplifier.Annotation, annotation)); var first = root.DescendantNodesAndSelf().First(x => x.HasAnnotation(annotation)); var last = root.DescendantNodesAndSelf().Last(x => x.HasAnnotation(annotation)); nodesToSimplify.Free(); return(importsToAdd.ToImmutableAndFree(), addedSymbols, first.GetCommonRoot(last)); }
public static async Task <(Document containingDocument, SyntaxAnnotation typeAnnotation)> AddTypeToNewFileAsync( Solution solution, string containingNamespaceDisplay, string fileName, ProjectId projectId, IEnumerable <string> folders, INamedTypeSymbol newSymbol, Document hintDocument, CleanCodeGenerationOptionsProvider fallbackOptions, CancellationToken cancellationToken) { var newDocumentId = DocumentId.CreateNewId(projectId, debugName: fileName); var newDocumentPath = PathUtilities.CombinePaths(PathUtilities.GetDirectoryName(hintDocument.FilePath), fileName); var solutionWithInterfaceDocument = solution.AddDocument(newDocumentId, fileName, text: "", folders: folders, filePath: newDocumentPath); var newDocument = solutionWithInterfaceDocument.GetRequiredDocument(newDocumentId); var newSemanticModel = await newDocument.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); var context = new CodeGenerationContext( contextLocation: newSemanticModel.SyntaxTree.GetLocation(new TextSpan()), generateMethodBodies: true); // need to remove the root namespace from the containing namespace display because it is implied // For C# this does nothing as there is no root namespace (root namespace is empty string) var generateTypeService = newDocument.GetRequiredLanguageService <IGenerateTypeService>(); var rootNamespace = generateTypeService.GetRootNamespace(newDocument.Project.CompilationOptions); var index = rootNamespace.IsEmpty() ? -1 : containingNamespaceDisplay.IndexOf(rootNamespace); // if we did find the root namespace as the first element, then we remove it // this may leave us with an extra "." character at the start, but when we split it shouldn't matter var namespaceWithoutRoot = index == 0 ? containingNamespaceDisplay.Remove(index, rootNamespace.Length) : containingNamespaceDisplay; var namespaceParts = namespaceWithoutRoot.Split('.').Where(s => !string.IsNullOrEmpty(s)); var newTypeDocument = await CodeGenerator.AddNamespaceOrTypeDeclarationAsync( new CodeGenerationSolutionContext( newDocument.Project.Solution, context, fallbackOptions), newSemanticModel.GetEnclosingNamespace(0, cancellationToken), newSymbol.GenerateRootNamespaceOrType(namespaceParts.ToArray()), cancellationToken).ConfigureAwait(false); var newCleanupOptions = await newTypeDocument.GetCodeCleanupOptionsAsync(fallbackOptions, cancellationToken).ConfigureAwait(false); var formattingService = newTypeDocument.GetLanguageService <INewDocumentFormattingService>(); if (formattingService is not null) { newTypeDocument = await formattingService.FormatNewDocumentAsync(newTypeDocument, hintDocument, newCleanupOptions, cancellationToken).ConfigureAwait(false); } var syntaxRoot = await newTypeDocument.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var typeAnnotation = new SyntaxAnnotation(); var syntaxFacts = newTypeDocument.GetRequiredLanguageService <ISyntaxFactsService>(); var declarationNode = syntaxRoot.DescendantNodes().First(syntaxFacts.IsTypeDeclaration); var annotatedRoot = syntaxRoot.ReplaceNode(declarationNode, declarationNode.WithAdditionalAnnotations(typeAnnotation)); newTypeDocument = newTypeDocument.WithSyntaxRoot(annotatedRoot); var simplified = await Simplifier.ReduceAsync(newTypeDocument, newCleanupOptions.SimplifierOptions, cancellationToken).ConfigureAwait(false); var formattedDocument = await Formatter.FormatAsync(simplified, newCleanupOptions.FormattingOptions, cancellationToken).ConfigureAwait(false); return(formattedDocument, typeAnnotation); }
private static async Task <T> FindNodeWithAnnotationAsync <T>(Document document, SyntaxAnnotation annotation, CancellationToken cancellationToken) where T : SyntaxNode { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); return(root .GetAnnotatedNodesAndTokens(annotation) .Single() .AsNode() as T); }
private async Task <Result> EncapsulateFieldAsync(IFieldSymbol field, Document document, bool updateReferences, CancellationToken cancellationToken) { var originalField = field; var finalNames = GeneratePropertyAndFieldNames(field); var finalFieldName = finalNames.Item1; var generatedPropertyName = finalNames.Item2; // Annotate the field declarations so we can find it after rename. var fieldDeclaration = field.DeclaringSyntaxReferences.First(); var declarationAnnotation = new SyntaxAnnotation(); document = document.WithSyntaxRoot(fieldDeclaration.SyntaxTree.GetRoot(cancellationToken).ReplaceNode(fieldDeclaration.GetSyntax(cancellationToken), fieldDeclaration.GetSyntax(cancellationToken).WithAdditionalAnnotations(declarationAnnotation))); var solution = document.Project.Solution; foreach (var linkedDocumentId in document.GetLinkedDocumentIds()) { var linkedDocument = solution.GetDocument(linkedDocumentId); var linkedRoot = await linkedDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var linkedFieldNode = linkedRoot.FindNode(fieldDeclaration.Span); if (linkedFieldNode.Span != fieldDeclaration.Span) { continue; } var updatedRoot = linkedRoot.ReplaceNode(linkedFieldNode, linkedFieldNode.WithAdditionalAnnotations(declarationAnnotation)); solution = solution.WithDocumentSyntaxRoot(linkedDocumentId, updatedRoot); } document = solution.GetDocument(document.Id); // Resolve the annotated symbol and prepare for rename. var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var compilation = semanticModel.Compilation; field = field.GetSymbolKey().Resolve(compilation, cancellationToken: cancellationToken).Symbol as IFieldSymbol; var solutionNeedingProperty = solution; // We couldn't resolve field after annotating its declaration. Bail if (field == null) { return(null); } solutionNeedingProperty = await UpdateReferencesAsync( updateReferences, solution, document, field, finalFieldName, generatedPropertyName, cancellationToken).ConfigureAwait(false); document = solutionNeedingProperty.GetDocument(document.Id); var markFieldPrivate = field.DeclaredAccessibility != Accessibility.Private; var rewrittenFieldDeclaration = await RewriteFieldNameAndAccessibility(finalFieldName, markFieldPrivate, document, declarationAnnotation, cancellationToken).ConfigureAwait(false); document = await Formatter.FormatAsync(document.WithSyntaxRoot(rewrittenFieldDeclaration), Formatter.Annotation, cancellationToken : cancellationToken).ConfigureAwait(false); solution = document.Project.Solution; foreach (var linkedDocumentId in document.GetLinkedDocumentIds()) { var linkedDocument = solution.GetDocument(linkedDocumentId); var updatedLinkedRoot = await RewriteFieldNameAndAccessibility(finalFieldName, markFieldPrivate, linkedDocument, declarationAnnotation, cancellationToken).ConfigureAwait(false); var updatedLinkedDocument = await Formatter.FormatAsync(linkedDocument.WithSyntaxRoot(updatedLinkedRoot), Formatter.Annotation, cancellationToken : cancellationToken).ConfigureAwait(false); solution = updatedLinkedDocument.Project.Solution; } document = solution.GetDocument(document.Id); semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); compilation = semanticModel.Compilation; var newRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var newDeclaration = newRoot.GetAnnotatedNodes <SyntaxNode>(declarationAnnotation).First(); field = semanticModel.GetDeclaredSymbol(newDeclaration, cancellationToken) as IFieldSymbol; var generatedProperty = GenerateProperty(generatedPropertyName, finalFieldName, originalField.DeclaredAccessibility, originalField, field.ContainingType, new SyntaxAnnotation(), document, cancellationToken); var codeGenerationService = document.GetLanguageService <ICodeGenerationService>(); var solutionWithProperty = await AddPropertyAsync( document, document.Project.Solution, field, generatedProperty, cancellationToken).ConfigureAwait(false); return(new Result(solutionWithProperty, originalField.ToDisplayString(), originalField.GetGlyph())); }
private static StatementSyntax GetSimplified(StatementSyntax statement1, StatementSyntax statement2, ExpressionSyntax condition, ExpressionSyntax compared, SemanticModel semanticModel, SyntaxAnnotation annotation, bool isNullCoalescing) { if (statement1 is ReturnStatementSyntax return1 && statement2 is ReturnStatementSyntax return2) { var retExpr1 = return1.Expression.RemoveParentheses(); var retExpr2 = return2.Expression.RemoveParentheses(); var createdExpression = isNullCoalescing ? GetNullCoalescing(retExpr1, retExpr2, compared, semanticModel, annotation) : GetConditionalExpression(condition, return1.Expression, return2.Expression, annotation); return(SyntaxFactory.ReturnStatement(createdExpression)); } var expressionStatement1 = statement1 as ExpressionStatementSyntax; var expressionStatement2 = statement2 as ExpressionStatementSyntax; var expression1 = expressionStatement1.Expression.RemoveParentheses(); var expression2 = expressionStatement2.Expression.RemoveParentheses(); var assignment = GetSimplifiedAssignment(expression1, expression2, condition, compared, semanticModel, annotation, isNullCoalescing); if (assignment != null) { return(SyntaxFactory.ExpressionStatement(assignment)); } var expression = GetSimplificationFromInvocations(expression1, expression2, condition, compared, semanticModel, annotation, isNullCoalescing); return(expression != null ? SyntaxFactory.ExpressionStatement(expression) : null); }
public static IEnumerable <SyntaxNode> EnumerateGetAnnotatedNodes(this PatternNode self, SyntaxNode node, SyntaxAnnotation syntaxAnnotation, SemanticModel semanticModel = null) { return(self.Enumerate(node.GetAnnotatedNodes(syntaxAnnotation), semanticModel)); }
private static ExpressionSyntax GetSimplifiedAssignment(ExpressionSyntax expression1, ExpressionSyntax expression2, ExpressionSyntax condition, ExpressionSyntax compared, SemanticModel semanticModel, SyntaxAnnotation annotation, bool isNullCoalescing) { var assignment1 = expression1 as AssignmentExpressionSyntax; var assignment2 = expression2 as AssignmentExpressionSyntax; var canBeSimplified = assignment1 != null && assignment2 != null && CSharpEquivalenceChecker.AreEquivalent(assignment1.Left, assignment2.Left) && assignment1.Kind() == assignment2.Kind(); if (!canBeSimplified) { return(null); } var createdExpression = isNullCoalescing ? GetNullCoalescing(assignment1.Right, assignment2.Right, compared, semanticModel, annotation) : GetConditionalExpression(condition, assignment1.Right, assignment2.Right, annotation); return(SyntaxFactory.AssignmentExpression( assignment1.Kind(), assignment1.Left, createdExpression)); }
public async Task <Document> AddImportsAsync( Document document, IEnumerable <TextSpan> spans, Strategy strategy, bool safe, OptionSet?options, CancellationToken cancellationToken) { options ??= await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); Contract.ThrowIfNull(model); var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); var addImportsService = document.GetLanguageService <IAddImportsService>(); var generator = SyntaxGenerator.GetGenerator(document); // Create a simple interval tree for simplification spans. var spansTree = new SimpleIntervalTree <TextSpan>(TextSpanIntervalIntrospector.Instance, spans); var nodes = root.DescendantNodesAndSelf().Where(IsInSpan); var(importDirectivesToAdd, namespaceSymbols, context) = strategy switch { Strategy.AddImportsFromSymbolAnnotations => GetImportDirectivesFromAnnotatedNodesAsync(nodes, root, model, addImportsService, generator, cancellationToken), Strategy.AddImportsFromSyntaxes => GetImportDirectivesFromSyntaxesAsync(nodes, ref root, model, addImportsService, generator, cancellationToken), _ => throw new InvalidEnumArgumentException(nameof(strategy), (int)strategy, typeof(Strategy)), }; if (importDirectivesToAdd.Length == 0) { return(document.WithSyntaxRoot(root)); //keep any added simplifier annotations } if (safe) { // Mark the context with an annotation. // This will allow us to find it after we have called MakeSafeToAddNamespaces. var annotation = new SyntaxAnnotation(); document = document.WithSyntaxRoot(root.ReplaceNode(context, context.WithAdditionalAnnotations(annotation))); root = (await document.GetSyntaxRootAsync().ConfigureAwait(false)) !; model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); Contract.ThrowIfNull(model); // Make Safe to add namespaces document = document.WithSyntaxRoot( MakeSafeToAddNamespaces(root, namespaceSymbols, model, document.Project.Solution.Workspace, cancellationToken)); root = (await document.GetSyntaxRootAsync().ConfigureAwait(false)) !; model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); Contract.ThrowIfNull(model); // Find the context. It might be null if we have removed the context in the process of complexifying the tree. context = root.DescendantNodesAndSelf().FirstOrDefault(x => x.HasAnnotation(annotation)) ?? root; } var placeSystemNamespaceFirst = options.GetOption(GenerationOptions.PlaceSystemNamespaceFirst, document.Project.Language); root = addImportsService.AddImports(model.Compilation, root, context, importDirectivesToAdd, placeSystemNamespaceFirst, cancellationToken); return(document.WithSyntaxRoot(root)); bool IsInSpan(SyntaxNode node) => spansTree.HasIntervalThatOverlapsWith(node.FullSpan.Start, node.FullSpan.Length); }
/// <summary> /// Ensure that an event handler exists for a given event. /// </summary> /// <param name="thisDocument">The document corresponding to this operation.</param> /// <param name="targetDocument">The document to generate the event handler in if it doesn't /// exist.</param> /// <param name="className">The name of the type to generate the event handler in.</param> /// <param name="objectName">The name of the event member (if <paramref /// name="useHandlesClause"/> is true)</param> /// <param name="objectTypeName">The name of the type containing the event.</param> /// <param name="nameOfEvent">The name of the event member in <paramref /// name="objectTypeName"/></param> /// <param name="eventHandlerName">The name of the method to be hooked up to the /// event.</param> /// <param name="itemidInsertionPoint">The VS itemid of the file to generate the event /// handler in.</param> /// <param name="useHandlesClause">If true, a vb "Handles" clause will be generated for the /// handler.</param> /// <param name="additionalFormattingRule">An additional formatting rule that can be used to /// format the newly inserted method</param> /// <param name="cancellationToken">Cancellation token.</param> /// <returns>Either the unique id of the method if it already exists, or the unique id of /// the to be generated method, the text of the to be generated method, and the position in /// <paramref name="itemidInsertionPoint"/> where the text should be inserted.</returns> public static Tuple <string, string, VsTextSpan> EnsureEventHandler( Document thisDocument, Document targetDocument, string className, string objectName, string objectTypeName, string nameOfEvent, string eventHandlerName, uint itemidInsertionPoint, bool useHandlesClause, IFormattingRule additionalFormattingRule, CancellationToken cancellationToken) { var thisCompilation = thisDocument.Project.GetCompilationAsync(cancellationToken).WaitAndGetResult(cancellationToken); var type = thisCompilation.GetTypeByMetadataName(className); var existingEventHandlers = GetCompatibleEventHandlers(targetDocument, className, objectTypeName, nameOfEvent, cancellationToken); var existingHandler = existingEventHandlers.SingleOrDefault(e => e.Item1 == eventHandlerName); if (existingHandler != null) { return(Tuple.Create(existingHandler.Item2, (string)null, default(VsTextSpan))); } // Okay, it doesn't exist yet. Let's create it. var codeGenerationService = targetDocument.GetLanguageService <ICodeGenerationService>(); var syntaxFactory = targetDocument.GetLanguageService <SyntaxGenerator>(); var eventMember = GetEventSymbol(thisDocument, objectTypeName, nameOfEvent, type, cancellationToken); if (eventMember == null) { throw new InvalidOperationException(); } var eventType = ((IEventSymbol)eventMember).Type; if (eventType.Kind != SymbolKind.NamedType || ((INamedTypeSymbol)eventType).DelegateInvokeMethod == null) { throw new InvalidOperationException(ServicesVSResources.EventTypeIsInvalid); } var handlesExpressions = useHandlesClause ? new[] { syntaxFactory.MemberAccessExpression( objectName != null ? syntaxFactory.IdentifierName(objectName) : syntaxFactory.ThisExpression(), syntaxFactory.IdentifierName(nameOfEvent)) } : null; var invokeMethod = ((INamedTypeSymbol)eventType).DelegateInvokeMethod; var newMethod = CodeGenerationSymbolFactory.CreateMethodSymbol( attributes: null, accessibility: Accessibility.Protected, modifiers: new DeclarationModifiers(), returnType: targetDocument.Project.GetCompilationAsync(cancellationToken).WaitAndGetResult(cancellationToken).GetSpecialType(SpecialType.System_Void), explicitInterfaceSymbol: null, name: eventHandlerName, typeParameters: null, parameters: invokeMethod.Parameters.ToArray(), statements: null, handlesExpressions: handlesExpressions); var annotation = new SyntaxAnnotation(); newMethod = annotation.AddAnnotationToSymbol(newMethod); var codeModel = targetDocument.Project.LanguageServices.GetService <ICodeModelNavigationPointService>(); var syntaxFacts = targetDocument.Project.LanguageServices.GetService <ISyntaxFactsService>(); var targetSyntaxTree = targetDocument.GetSyntaxTreeAsync(cancellationToken).WaitAndGetResult(cancellationToken); var position = type.Locations.First(loc => loc.SourceTree == targetSyntaxTree).SourceSpan.Start; var destinationType = syntaxFacts.GetContainingTypeDeclaration(targetSyntaxTree.GetRoot(cancellationToken), position); var insertionPoint = codeModel.GetEndPoint(destinationType, EnvDTE.vsCMPart.vsCMPartBody); if (insertionPoint == null) { throw new InvalidOperationException(ServicesVSResources.MemberInsertionFailed); } var newType = codeGenerationService.AddMethod(destinationType, newMethod, new CodeGenerationOptions(autoInsertionLocation: false), cancellationToken); var newRoot = targetSyntaxTree.GetRoot(cancellationToken).ReplaceNode(destinationType, newType); newRoot = Simplifier.ReduceAsync(targetDocument.WithSyntaxRoot(newRoot), Simplifier.Annotation, null, cancellationToken).WaitAndGetResult(cancellationToken).GetSyntaxRootAsync(cancellationToken).WaitAndGetResult(cancellationToken); var formattingRules = additionalFormattingRule.Concat(Formatter.GetDefaultFormattingRules(targetDocument)); var workspace = targetDocument.Project.Solution.Workspace; newRoot = Formatter.Format(newRoot, Formatter.Annotation, workspace, workspace.Options, formattingRules, cancellationToken); var newMember = newRoot.GetAnnotatedNodesAndTokens(annotation).Single(); var newMemberText = newMember.ToFullString(); // In VB, the final newline is likely a statement terminator in the parent - just add // one on so that things don't get messed. if (!newMemberText.EndsWith(Environment.NewLine, StringComparison.Ordinal)) { newMemberText += Environment.NewLine; } return(Tuple.Create(ConstructMemberId(newMethod), newMemberText, insertionPoint.Value.ToVsTextSpan())); }