public async Task<IEnumerable<CodeAction>> GetRefactoringsAsync(Document document, TextSpan textSpan, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var node = root.FindNode(textSpan); var switchStatementNode = node as SwitchStatementSyntax; if (switchStatementNode == null) return null; var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var memberEx = switchStatementNode.Expression as MemberAccessExpressionSyntax; if (memberEx == null) return null; var symbolInfo = semanticModel.GetTypeInfo(memberEx.Name); var enumTypeInfo = symbolInfo.Type; if (enumTypeInfo.TypeKind != TypeKind.Enum) return null; var enumName = enumTypeInfo.Name; var nameSpace = enumTypeInfo.ContainingNamespace.Name; var enumType = Type.GetType(nameSpace + "." + enumName); if (enumType == null) return null; return new[] { CodeAction.Create("Explode Switch", c => ExplodeSwitch(document, root, semanticModel, switchStatementNode, c)) }; }
public async static Task<Solution> MakeAutoPropertyAsync(Document document, SyntaxNode root, PropertyDeclarationSyntax property, CancellationToken cancellationToken) { var semanticModel = await document.GetSemanticModelAsync(cancellationToken); var getterReturn = (ReturnStatementSyntax)property.AccessorList.Accessors.First(a => a.Keyword.ValueText == "get").Body.Statements.First(); var returnIdentifier = (IdentifierNameSyntax)(getterReturn.Expression is MemberAccessExpressionSyntax ? ((MemberAccessExpressionSyntax)getterReturn.Expression).Name : getterReturn.Expression); var returnIdentifierSymbol = semanticModel.GetSymbolInfo(returnIdentifier).Symbol; var variableDeclarator = (VariableDeclaratorSyntax)returnIdentifierSymbol.DeclaringSyntaxReferences.First().GetSyntax(); var fieldDeclaration = variableDeclarator.FirstAncestorOfType<FieldDeclarationSyntax>(); root = root.TrackNodes(returnIdentifier, fieldDeclaration, property); document = document.WithSyntaxRoot(root); root = await document.GetSyntaxRootAsync(cancellationToken); semanticModel = await document.GetSemanticModelAsync(cancellationToken); returnIdentifier = root.GetCurrentNode(returnIdentifier); returnIdentifierSymbol = semanticModel.GetSymbolInfo(returnIdentifier).Symbol; var newProperty = GetSimpleProperty(property, variableDeclarator) .WithTriviaFrom(property) .WithAdditionalAnnotations(Formatter.Annotation); var newSolution = await Renamer.RenameSymbolAsync(document.Project.Solution, returnIdentifierSymbol, property.Identifier.ValueText, document.Project.Solution.Workspace.Options, cancellationToken); document = newSolution.GetDocument(document.Id); root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); root = root.InsertNodesAfter(root.GetCurrentNode(property), new[] { newProperty }); var multipleVariableDeclaration = fieldDeclaration.Declaration.Variables.Count > 1; if (multipleVariableDeclaration) { var newfieldDeclaration = fieldDeclaration.WithDeclaration(fieldDeclaration.Declaration.RemoveNode(variableDeclarator, SyntaxRemoveOptions.KeepNoTrivia)); root = root.RemoveNode(root.GetCurrentNode<SyntaxNode>(property), SyntaxRemoveOptions.KeepNoTrivia); root = root.ReplaceNode(root.GetCurrentNode(fieldDeclaration), newfieldDeclaration); } else { root = root.RemoveNodes(root.GetCurrentNodes<SyntaxNode>(new SyntaxNode[] { fieldDeclaration, property }), SyntaxRemoveOptions.KeepNoTrivia); } document = document.WithSyntaxRoot(root); return document.Project.Solution; }
private static async Task<Document> GetTransformedDocumentFromSingleLineAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var queryExpression = (QueryExpressionSyntax)syntaxRoot.FindNode(diagnostic.Location.SourceSpan).Parent; var replaceMap = new Dictionary<SyntaxToken, SyntaxToken>(); var nodeList = CreateQueryNodeList(queryExpression); for (var i = 0; i < nodeList.Length; i++) { var token = nodeList[i].GetFirstToken(); var precedingToken = token.GetPreviousToken(); var triviaList = precedingToken.TrailingTrivia.AddRange(token.LeadingTrivia); var processedTriviaList = triviaList .Where(t => t.IsKind(SyntaxKind.MultiLineCommentTrivia)) .ToSyntaxTriviaList() .Add(SyntaxFactory.Space); if (processedTriviaList.Count > 1) { processedTriviaList = processedTriviaList.Insert(0, SyntaxFactory.Space); } replaceMap.Add(precedingToken, precedingToken.WithTrailingTrivia(processedTriviaList)); replaceMap.Add(token, token.WithLeadingTrivia()); } var newSyntaxRoot = syntaxRoot.ReplaceTokens(replaceMap.Keys, (t1, t2) => replaceMap[t1]).WithoutFormatting(); return document.WithSyntaxRoot(newSyntaxRoot); }
protected override async Task<SignatureHelpItems> GetItemsWorkerAsync(Document document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); InvocationExpressionSyntax invocationExpression; if (!TryGetInvocationExpression(root, position, document.GetLanguageService<ISyntaxFactsService>(), triggerInfo.TriggerReason, cancellationToken, out invocationExpression)) { return null; } var semanticModel = await document.GetSemanticModelForNodeAsync(invocationExpression, cancellationToken).ConfigureAwait(false); var within = semanticModel.GetEnclosingNamedTypeOrAssembly(position, cancellationToken); if (within == null) { return null; } // get the regular signature help items var symbolDisplayService = document.Project.LanguageServices.GetService<ISymbolDisplayService>(); var methodGroup = semanticModel.GetMemberGroup(invocationExpression.Expression, cancellationToken) .OfType<IMethodSymbol>() .FilterToVisibleAndBrowsableSymbols(document.ShouldHideAdvancedMembers(), semanticModel.Compilation); // try to bind to the actual method var symbolInfo = semanticModel.GetSymbolInfo(invocationExpression, cancellationToken); var matchedMethodSymbol = symbolInfo.Symbol as IMethodSymbol; // if the symbol could be bound, replace that item in the symbol list if (matchedMethodSymbol != null && matchedMethodSymbol.IsGenericMethod) { methodGroup = methodGroup.Select(m => matchedMethodSymbol.OriginalDefinition == m ? matchedMethodSymbol : m); } methodGroup = methodGroup.Sort(symbolDisplayService, semanticModel, invocationExpression.SpanStart); var expressionType = semanticModel.GetTypeInfo(invocationExpression.Expression, cancellationToken).Type as INamedTypeSymbol; var anonymousTypeDisplayService = document.Project.LanguageServices.GetService<IAnonymousTypeDisplayService>(); var documentationCommentFormattingService = document.Project.LanguageServices.GetService<IDocumentationCommentFormattingService>(); var textSpan = SignatureHelpUtilities.GetSignatureHelpSpan(invocationExpression.ArgumentList); var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>(); if (methodGroup.Any()) { return CreateSignatureHelpItems( GetMethodGroupItems(invocationExpression, semanticModel, symbolDisplayService, anonymousTypeDisplayService, documentationCommentFormattingService, within, methodGroup, cancellationToken), textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken)); } else if (expressionType != null && expressionType.TypeKind == TypeKind.Delegate) { return CreateSignatureHelpItems( GetDelegateInvokeItems(invocationExpression, semanticModel, symbolDisplayService, anonymousTypeDisplayService, documentationCommentFormattingService, within, expressionType, cancellationToken), textSpan, GetCurrentArgumentState(root, position, syntaxFacts, textSpan, cancellationToken)); } else { return null; } }
/// <summary> /// Réordonne les membres d'un type. /// </summary> /// <param name="document">Le document.</param> /// <param name="type">Le type.</param> /// <param name="jetonAnnulation">Le jeton d'annulation.</param> /// <returns>Le nouveau document.</returns> private async Task<Document> OrdonnerMembres(Document document, TypeDeclarationSyntax type, CancellationToken jetonAnnulation) { // On récupère la racine. var racine = await document .GetSyntaxRootAsync(jetonAnnulation) .ConfigureAwait(false); var modèleSémantique = await document.GetSemanticModelAsync(jetonAnnulation); // Pour une raison étrange, TypeDeclarationSyntax n'expose pas WithMembers() alors que les trois classes qui en héritent l'expose. // Il faut donc gérer les trois cas différemment... SyntaxNode nouveauType; if (type is ClassDeclarationSyntax) { nouveauType = (type as ClassDeclarationSyntax) .WithMembers(SyntaxFactory.List(Partagé.OrdonnerMembres(type.Members, modèleSémantique))); } else if (type is InterfaceDeclarationSyntax) { nouveauType = (type as InterfaceDeclarationSyntax) .WithMembers(SyntaxFactory.List(Partagé.OrdonnerMembres(type.Members, modèleSémantique))); } else { nouveauType = (type as StructDeclarationSyntax) .WithMembers(SyntaxFactory.List(Partagé.OrdonnerMembres(type.Members, modèleSémantique))); } // Et on met à jour la racine. var nouvelleRacine = racine.ReplaceNode(type, nouveauType); return document.WithSyntaxRoot(nouvelleRacine); }
private static async Task<Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var settings = SettingsHelper.GetStyleCopSettings(document.Project.AnalyzerOptions, cancellationToken); var enumMemberDeclaration = (EnumMemberDeclarationSyntax)syntaxRoot.FindNode(diagnostic.Location.SourceSpan); var enumDeclaration = (EnumDeclarationSyntax)enumMemberDeclaration.Parent; var memberIndex = enumDeclaration.Members.IndexOf(enumMemberDeclaration); var precedingSeparatorToken = enumDeclaration.Members.GetSeparator(memberIndex - 1); // determine the indentation for enum members (which is parent + 1 step) var parentIndentationSteps = IndentationHelper.GetIndentationSteps(settings.Indentation, enumDeclaration); var indentation = IndentationHelper.GenerateWhitespaceTrivia(settings.Indentation, parentIndentationSteps + 1); // combine all trivia between the separator and the enum member and place them after the separator, followed by a new line. var enumMemberDeclarationFirstToken = enumMemberDeclaration.GetFirstToken(); var sharedTrivia = TriviaHelper.MergeTriviaLists(precedingSeparatorToken.TrailingTrivia, enumMemberDeclarationFirstToken.LeadingTrivia); var newTrailingTrivia = SyntaxFactory.TriviaList(sharedTrivia) .WithoutTrailingWhitespace() .Add(SyntaxFactory.CarriageReturnLineFeed); // replace the trivia for the tokens var replacements = new Dictionary<SyntaxToken, SyntaxToken> { [precedingSeparatorToken] = precedingSeparatorToken.WithTrailingTrivia(newTrailingTrivia), [enumMemberDeclarationFirstToken] = enumMemberDeclarationFirstToken.WithLeadingTrivia(indentation), }; var newSyntaxRoot = syntaxRoot.ReplaceTokens(replacements.Keys, (original, rewritten) => replacements[original]); var newDocument = document.WithSyntaxRoot(newSyntaxRoot.WithoutFormatting()); return newDocument; }
public static async Task<Document> ReplaceNodeAsync(Document document, SyntaxNode @old, SyntaxNode @new, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken); var newRoot = root.ReplaceNode(@old, @new); var newDocument = document.WithSyntaxRoot(newRoot); return newDocument; }
private static async Task<Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var whereToken = syntaxRoot.FindToken(diagnostic.Location.SourceSpan.Start); var precedingToken = whereToken.GetPreviousToken(); var endToken = syntaxRoot.FindToken(diagnostic.Location.SourceSpan.End); var afterEndToken = endToken.GetNextToken(); var parentIndentation = GetParentIndentation(whereToken); var settings = SettingsHelper.GetStyleCopSettings(document.Project.AnalyzerOptions, cancellationToken); var indentationTrivia = SyntaxFactory.Whitespace(parentIndentation + IndentationHelper.GenerateIndentationString(settings.Indentation, 1)); var replaceMap = new Dictionary<SyntaxToken, SyntaxToken>() { [precedingToken] = precedingToken.WithTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed), [whereToken] = whereToken.WithLeadingTrivia(indentationTrivia), [endToken] = endToken.WithTrailingTrivia(RemoveUnnecessaryWhitespaceTrivia(endToken).Add(SyntaxFactory.CarriageReturnLineFeed)), }; if (afterEndToken.IsKind(SyntaxKind.EqualsGreaterThanToken)) { replaceMap.Add(afterEndToken, afterEndToken.WithLeadingTrivia(indentationTrivia)); } else if (afterEndToken.IsKind(SyntaxKind.OpenBraceToken)) { replaceMap.Add(afterEndToken, afterEndToken.WithLeadingTrivia(SyntaxFactory.Whitespace(parentIndentation))); } else if (afterEndToken.IsKind(SyntaxKind.WhereKeyword)) { replaceMap.Add(afterEndToken, afterEndToken.WithLeadingTrivia(indentationTrivia)); } var newSyntaxRoot = syntaxRoot.ReplaceTokens(replaceMap.Keys, (t1, t2) => replaceMap[t1]).WithoutFormatting(); return document.WithSyntaxRoot(newSyntaxRoot); }
static async Task UpdateDocument(ConcurrentDictionary <DocumentId, Dictionary <DeclaredSymbolInfoKind, List <DeclaredSymbolInfoWrapper> > > result, Microsoft.CodeAnalysis.Document document, CancellationToken cancellationToken) { var syntaxFactsService = document.GetLanguageService <ISyntaxFactsService> (); var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var infos = new Dictionary <DeclaredSymbolInfoKind, List <DeclaredSymbolInfoWrapper> > (); foreach (var kind in AllKinds) { infos [kind] = new List <DeclaredSymbolInfoWrapper> (); } foreach (var current in root.DescendantNodesAndSelf(n => !(n is BlockSyntax))) { cancellationToken.ThrowIfCancellationRequested(); var kind = current.Kind(); if (kind == SyntaxKind.ConstructorDeclaration || kind == SyntaxKind.IndexerDeclaration) { continue; } if (syntaxFactsService.TryGetDeclaredSymbolInfo(current, out DeclaredSymbolInfo info)) { var declaredSymbolInfo = new DeclaredSymbolInfoWrapper(current, document.Id, info); infos[info.Kind].Add(declaredSymbolInfo); } } RemoveDocument(result, document.Id); result.TryAdd(document.Id, infos); }
private async Task<Document> FormatXmlAsync(Document document, LiteralExpressionSyntax sleSyntax, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken); var tree = root.SyntaxTree; //Get the character position of the LiteralExpressionSyntax FileLinePositionSpan position = tree.GetLineSpan(sleSyntax.Span); int cSpace = position.StartLinePosition.Character; //Figure out the preceeding trivia since we can't get the column position from GetLineSpan var parentTrivia = sleSyntax.GetLeadingTrivia().ToFullString(); var xml = sleSyntax.GetFirstToken().ValueText; var newXmlText = FormatXml(xml); //Process each line of the formatted XML and prepend the parent trivia & spaces string[] xmlLines = newXmlText.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None); for (int i = 1; i < xmlLines.Length; i++) { xmlLines[i] = parentTrivia + new String(' ', (cSpace + 2)) + xmlLines[i]; } newXmlText = String.Join("\r\n", xmlLines); var newXmlValue = "@\"" + newXmlText + "\""; var newNode = SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Token(SyntaxTriviaList.Empty, SyntaxKind.StringLiteralToken, newXmlValue, newXmlText, SyntaxTriviaList.Empty)); var newRoot = root.ReplaceNode(sleSyntax, newNode); return document.WithSyntaxRoot(newRoot); }
private static async Task<Document> AddConfigureAwaitAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken, bool continueOnCapturedContext) { SyntaxKind continueOnCapturedContextSyntax; switch (continueOnCapturedContext) { case true: continueOnCapturedContextSyntax = SyntaxKind.TrueLiteralExpression; break; default: continueOnCapturedContextSyntax = SyntaxKind.FalseLiteralExpression; break; } var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var awaitExpression = (AwaitExpressionSyntax)root.FindNode(diagnostic.Location.SourceSpan); var expression = awaitExpression.Expression; var newExpression = SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, expression, SyntaxFactory.IdentifierName(nameof(Task.ConfigureAwait))), SyntaxFactory.ArgumentList( SyntaxFactory.SingletonSeparatedList( SyntaxFactory.Argument( SyntaxFactory.LiteralExpression(continueOnCapturedContextSyntax))))); var newRoot = root.ReplaceNode(expression, newExpression); var newDocument = document.WithSyntaxRoot(newRoot); return newDocument; }
private static async Task<Document> ChangeToThenByAsync(Document document, SyntaxNode syntaxNode, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken); var newRoot = root.ReplaceNode(syntaxNode, SyntaxFactory.IdentifierName("ThenBy")); return document.WithSyntaxRoot(newRoot); }
private static async Task<Document> RemoveTrailingWhiteSpaceAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var trivia = root.FindTrivia(diagnostic.Location.SourceSpan.End - 1); SyntaxNode newRoot; if (trivia.IsKind(SyntaxKind.WhitespaceTrivia)) { newRoot = root.ReplaceTrivia(trivia, new SyntaxTrivia[] { }); } else if (trivia.IsKind(SyntaxKind.SingleLineDocumentationCommentTrivia, SyntaxKind.MultiLineDocumentationCommentTrivia)) { var commentText = trivia.ToFullString(); var commentLines = commentText.Split(new[] { Environment.NewLine }, StringSplitOptions.None); var newComment = ""; var builder = new System.Text.StringBuilder(); builder.Append(newComment); for (int i = 0; i < commentLines.Length; i++) { var commentLine = commentLines[i]; builder.Append(Regex.Replace(commentLine, @"\s+$", "")); if (i < commentLines.Length - 1) builder.Append(Environment.NewLine); } newComment = builder.ToString(); newRoot = root.ReplaceTrivia(trivia, SyntaxFactory.SyntaxTrivia(SyntaxKind.DocumentationCommentExteriorTrivia, newComment)); } else { var triviaNoTrailingWhiteSpace = Regex.Replace(trivia.ToFullString(), @"\s+$", ""); newRoot = root.ReplaceTrivia(trivia, SyntaxFactory.ParseTrailingTrivia(triviaNoTrailingWhiteSpace)); } return document.WithSyntaxRoot(newRoot); }
private static async Task<Document> DeleteDeclarationFromDocument(SyntaxNode node, Document curentDocument) { var root = await curentDocument.GetSyntaxRootAsync(); var newTypeDeclarationParent = node.Parent.RemoveNode(node, SyntaxRemoveOptions.KeepNoTrivia); var newRoot = root.ReplaceNode(node.Parent, newTypeDeclarationParent); return curentDocument.WithSyntaxRoot(newRoot); }
private async Task<Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken token) { var syntaxRoot = await document.GetSyntaxRootAsync(token).ConfigureAwait(false); var newDocument = this.CreateCodeFix(document, diagnostic, syntaxRoot); return newDocument; }
private static async Task<Document> GetTransformedDocumentAsync(Document document, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var settings = document.Project.AnalyzerOptions.GetStyleCopSettings(); var fileHeader = FileHeaderHelpers.ParseFileHeader(root); SyntaxNode newSyntaxRoot; if (fileHeader.IsMissing) { newSyntaxRoot = AddHeader(document, root, document.Name, settings); } else { var trivia = root.GetLeadingTrivia(); var commentIndex = TriviaHelper.IndexOfFirstNonWhitespaceTrivia(trivia, false); // Safe to do this as fileHeader.IsMissing is false. var isMultiLineComment = trivia[commentIndex].IsKind(SyntaxKind.MultiLineCommentTrivia); var xmlFileHeader = FileHeaderHelpers.ParseXmlFileHeader(root); if (isMultiLineComment && !xmlFileHeader.IsMalformed) { newSyntaxRoot = ReplaceWellFormedMultiLineCommentHeader(document, root, settings, commentIndex, xmlFileHeader); } else { newSyntaxRoot = ReplaceHeader(document, root, settings, xmlFileHeader.IsMalformed); } } return document.WithSyntaxRoot(newSyntaxRoot); }
public async Task<Solution> EnforceAsync(Document document) { if (document == null) { throw new ArgumentNullException(nameof(document)); } // The compiler will actually do the heavy lifting for us on this one: when it generates the semantic model // it creates diagnostic notes for usings that are unused with the id "CS8019". SemanticModel semanticModel = await document.GetSemanticModelAsync(); IEnumerable<Diagnostic> diagnostics = semanticModel.GetDiagnostics().Where(d => d.Id == "CS8019"); // Save the leading trivia to reattach after we have removed the unused roots SyntaxNode oldRoot = await document.GetSyntaxRootAsync(); SyntaxTriviaList leadingTrivia = oldRoot.GetLeadingTrivia(); // Now we need to go through the diagnostics in reverse order (so we don't corrupt our spans), find the // relevant SyntaxNodes, and remove them. diagnostics = diagnostics.OrderByDescending(d => d.Location.SourceSpan.Start); SyntaxNode newRoot = oldRoot; foreach (Diagnostic diagnostic in diagnostics) { newRoot = newRoot.RemoveNodes( newRoot.DescendantNodes(diagnostic.Location.SourceSpan), SyntaxRemoveOptions.KeepNoTrivia); } if (newRoot != oldRoot) { Log.WriteInformation("{0}: Removing unused usings", document.Name); document = document.WithSyntaxRoot(newRoot.WithLeadingTrivia(leadingTrivia)); } return document.Project.Solution; }
private async Task<Document> FormatXmlAsync(Document document, ArgumentSyntax argSntax, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken); var tree = root.SyntaxTree; //Get the character position of the ArgumentSyntax FileLinePositionSpan position = tree.GetLineSpan(argSntax.Span); int cSpace = position.StartLinePosition.Character; //Get the parent VariableDeclaration to figure out the preceeding trivia since we can't //get the column position from GetLineSpan (bug?) var parent = argSntax.Ancestors().Where(t => t.IsKind(SyntaxKind.VariableDeclaration)).FirstOrDefault(); var parentTrivia = parent.GetLeadingTrivia().ToFullString(); var xml = argSntax.Expression.GetFirstToken().ValueText; var newXml = FormatXml(xml); //Process each line of the formatted XML and prepend the parent trivia & spaces string[] xmlLines = newXml.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None); for (int i = 1; i < xmlLines.Length; i++) { xmlLines[i] = parentTrivia + new String(' ', (cSpace - 14)) + xmlLines[i]; } newXml = String.Join("\r\n", xmlLines); newXml = "@\"" + newXml + "\""; var newNode = SyntaxFactory.Argument(null, SyntaxFactory.Token(SyntaxKind.None), SyntaxFactory.IdentifierName(newXml)); var newRoot = root.ReplaceNode(argSntax, newNode); return document.WithSyntaxRoot(newRoot); }
static async Task<SyntaxNode> GetNewRootWithAddedNamespaces(Document document, SyntaxNode relativeToNode, CancellationToken cancellationToken, ImmutableHashSet<string> namespaceQualifiedStrings) { var namespaceWithUsings = relativeToNode .GetAncestorsOrThis<NamespaceDeclarationSyntax>() .FirstOrDefault(ns => ns.DescendantNodes().OfType<UsingDirectiveSyntax>().Any()); var root = await document.GetSyntaxRootAsync(cancellationToken); SyntaxNode newRoot; var usings = namespaceQualifiedStrings .Select(ns => UsingDirective(ParseName(ns).WithAdditionalAnnotations(Simplifier.Annotation))); if (namespaceWithUsings != null) { var newNamespaceDeclaration = namespaceWithUsings.WithUsings(namespaceWithUsings.Usings.AddRange(usings)); newRoot = root.ReplaceNode(namespaceWithUsings, newNamespaceDeclaration); } else { var compilationUnit = (CompilationUnitSyntax)root; newRoot = compilationUnit.WithUsings(compilationUnit.Usings.AddRange(usings)); } return newRoot; }
private static async Task<Document> RemoveUnreachableCodeAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var node = root.FindNode(diagnostic.Location.SourceSpan); var newDoc = document.WithSyntaxRoot(RemoveUnreachableStatement(root, node)); return newDoc; }
private static async Task<Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var token = syntaxRoot.FindToken(diagnostic.Location.SourceSpan.Start); var triviaList = token.LeadingTrivia; var index = triviaList.Count - 1; while (!triviaList[index].IsKind(SyntaxKind.EndOfLineTrivia)) { index--; } var lastEndOfLine = index; while (!triviaList[index].IsKind(SyntaxKind.SingleLineDocumentationCommentTrivia)) { index--; } var lastDocumentation = index; var newLeadingTrivia = triviaList.Take(lastDocumentation + 1).Concat(triviaList.Skip(lastEndOfLine + 1)); var newSyntaxRoot = syntaxRoot.ReplaceToken(token, token.WithLeadingTrivia(newLeadingTrivia)); return document.WithSyntaxRoot(newSyntaxRoot); }
private static async Task<Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var indentationOptions = IndentationOptions.FromDocument(document); var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var violatingTrivia = syntaxRoot.FindTrivia(diagnostic.Location.SourceSpan.Start); var stringBuilder = new StringBuilder(); var column = violatingTrivia.GetLineSpan().StartLinePosition.Character; foreach (var c in violatingTrivia.ToFullString()) { if (c == '\t') { var offsetWithinTabColumn = column % indentationOptions.TabSize; var spaceCount = indentationOptions.TabSize - offsetWithinTabColumn; stringBuilder.Append(' ', spaceCount); column += spaceCount; } else { stringBuilder.Append(c); column++; } } var newSyntaxRoot = syntaxRoot.ReplaceTrivia(violatingTrivia, SyntaxFactory.Whitespace(stringBuilder.ToString())); return document.WithSyntaxRoot(newSyntaxRoot); }
public async Task<bool> IsValidAsync( Document document, int position, string expressionValue, CancellationToken cancellationToken) { var expression = SyntaxFactory.ParseExpression(expressionValue); var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var token = root.FindToken(position); if (token.Kind() == SyntaxKind.CloseBraceToken && token.GetPreviousToken().Kind() != SyntaxKind.None) { token = token.GetPreviousToken(); } var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var info = semanticModel.GetSpeculativeSymbolInfo(token.SpanStart, expression, SpeculativeBindingOption.BindAsExpression); if (info.Symbol == null) { return false; } // We seem to have bound successfully. However, if it bound to a local, then make // sure that that local isn't after the statement that we're currently looking at. if (info.Symbol.Kind == SymbolKind.Local) { var statement = info.Symbol.Locations.First().FindToken(cancellationToken).GetAncestor<StatementSyntax>(); if (statement != null && position < statement.SpanStart) { return false; } } return true; }
private static async Task<Document> CallAsExtensionAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var root = (CompilationUnitSyntax)await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var diagnosticSpan = diagnostic.Location.SourceSpan; var staticInvocationExpression = root .FindToken(diagnosticSpan.Start) .Parent.AncestorsAndSelf() .OfType<InvocationExpressionSyntax>() .First(); var childNodes = staticInvocationExpression.ChildNodes(); var parameterExpressions = CallExtensionMethodAsExtensionAnalyzer.GetParameterExpressions(childNodes); var firstArgument = parameterExpressions.FirstOrDefault(); var callerMethod = childNodes.OfType<MemberAccessExpressionSyntax>().FirstOrDefault(); root = ReplaceStaticCallWithExtionMethodCall( root, staticInvocationExpression, firstArgument, callerMethod.Name, CallExtensionMethodAsExtensionAnalyzer.CreateArgumentListSyntaxFrom(parameterExpressions.Skip(1)) ).WithAdditionalAnnotations(Formatter.Annotation); var semanticModel = await document.GetSemanticModelAsync(); root = ImportNeededNamespace(root, semanticModel, callerMethod).WithAdditionalAnnotations(Formatter.Annotation); var newDocument = document.WithSyntaxRoot(root); return newDocument; }
private IEnumerable<BinaryExpressionSyntax> FindArithmeticOperationsOnVariables(Document document) { var root = document.GetSyntaxRootAsync().Result; return root.DescendantNodes().OfType<BinaryExpressionSyntax>() .Where(exp => exp.OperatorToken.RawKind == PlusToken || exp.OperatorToken.RawKind == MinusToken || exp.OperatorToken.RawKind == AsteriskToken || exp.OperatorToken.RawKind == SlashToken); }
async Task<Document> MakeUppercaseAsync(Document document, InvocationExpressionSyntax invocation, CancellationToken cancellationToken) { var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var typeSymbol = semanticModel.GetSymbolInfo(invocation.Expression, cancellationToken).Symbol; var nfluentCheck = semanticModel.Compilation.NFluentCheckType(); if (typeSymbol == null || nfluentCheck == null) return document; var newMethod = typeSymbol.Name == "AreEqual" ? "IsEqualTo" : "IsNotEqualTo"; var checkThat = CheckThat(nfluentCheck, invocation.ArgumentList.Arguments[1]); var replacement = InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, checkThat, IdentifierName(newMethod)), ArgumentList(SingletonSeparatedList(invocation.ArgumentList.Arguments[0]))) .WithTriviaFrom(invocation); var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var newSyntaxRoot = syntaxRoot.ReplaceNode(invocation, replacement); var newDocument = document.WithSyntaxRoot(newSyntaxRoot); var withUsings = await UsingHelpers.AddUsingsAsync(newDocument, replacement, cancellationToken, nfluentCheck.ContainingNamespace); return withUsings; }
private async Task<Document> MakeLambdaExpressionAsync(Document document, AnonymousMethodExpressionSyntax anonMethod, CancellationToken cancellationToken) { var parent = anonMethod.Parent; var parameterList = anonMethod.ParameterList != null ? anonMethod.ParameterList : SyntaxFactory.ParameterList(); SyntaxNode body; if (anonMethod.Block != null && anonMethod.Block.Statements.Count == 1) { body = anonMethod.Block.Statements.ElementAt(0).ChildNodes().ElementAt(0); } else if (anonMethod.Block != null) { body = anonMethod.Body; } else { body = SyntaxFactory.Block(); } var lambdaExpr = SyntaxFactory. ParenthesizedLambdaExpression(parameterList, (CSharpSyntaxNode)body); var newParent = parent.ReplaceNode(anonMethod, lambdaExpr); var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var newRoot = root.ReplaceNode(parent, newParent); return document.WithSyntaxRoot(newRoot); }
private static async Task<Document> RemoveRedundantComparisonAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var comparison = root.FindToken(diagnostic.Location.SourceSpan.Start).Parent.AncestorsAndSelf().OfType<BinaryExpressionSyntax>().First(); var semanticModel = await document.GetSemanticModelAsync(cancellationToken); bool constValue; ExpressionSyntax replacer; var rightConst = semanticModel.GetConstantValue(comparison.Right); if (rightConst.HasValue) { constValue = (bool)rightConst.Value; replacer = comparison.Left; } else { var leftConst = semanticModel.GetConstantValue(comparison.Left); constValue = (bool)leftConst.Value; replacer = comparison.Right; } if ((!constValue && comparison.IsKind(SyntaxKind.EqualsExpression)) || (constValue && comparison.IsKind(SyntaxKind.NotEqualsExpression))) replacer = SyntaxFactory.PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, replacer); replacer = replacer.WithAdditionalAnnotations(Formatter.Annotation); var newRoot = root.ReplaceNode(comparison, replacer); var newDocument = document.WithSyntaxRoot(newRoot); return newDocument; }
private static async Task<Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); SyntaxToken token = root.FindToken(diagnostic.Location.SourceSpan.Start); if (!token.IsKind(SyntaxKind.CloseBracketToken)) { return document; } if (token.IsFirstInLine()) { return document; } SyntaxToken precedingToken = token.GetPreviousToken(); if (!precedingToken.TrailingTrivia.Any(SyntaxKind.WhitespaceTrivia)) { return document; } SyntaxToken corrected = precedingToken.WithoutTrailingWhitespace().WithoutFormatting(); SyntaxNode transformed = root.ReplaceToken(precedingToken, corrected); Document updatedDocument = document.WithSyntaxRoot(transformed); return updatedDocument; }
public static new async Task<SemanticDocument> CreateAsync(Document document, CancellationToken cancellationToken) { var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); return new SemanticDocument(document, text, root.SyntaxTree, root, model); }
static async Task UpdateDocument(ConcurrentDictionary <DocumentId, Dictionary <DeclaredSymbolInfoKind, List <DeclaredSymbolInfo> > > result, Microsoft.CodeAnalysis.Document document, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var infos = new Dictionary <DeclaredSymbolInfoKind, List <DeclaredSymbolInfo> > (); foreach (var kind in AllKinds) { infos [kind] = new List <DeclaredSymbolInfo> (); } foreach (var current in root.DescendantNodesAndSelf(n => !(n is BlockSyntax))) { cancellationToken.ThrowIfCancellationRequested(); DeclaredSymbolInfo declaredSymbolInfo; if (current.TryGetDeclaredSymbolInfo(out declaredSymbolInfo)) { var kind = declaredSymbolInfo.Kind; if (kind == DeclaredSymbolInfoKind.Constructor || kind == DeclaredSymbolInfoKind.Module || kind == DeclaredSymbolInfoKind.Indexer) { continue; } declaredSymbolInfo.DocumentId = document.Id; infos[kind].Add(declaredSymbolInfo); } } RemoveDocument(result, document.Id); result.TryAdd(document.Id, infos); }
private async Task<Document> FixSpacingAsync(Document document, IfStatementSyntax ifStatement, CancellationToken c) { // This method will generate a new if-statement node with a single space between the if-keyword and the opening parenthesis. var generator = SyntaxGenerator.GetGenerator(document); // The new if-statement will need to retain the same statements as the old if-statement. var ifBlock = ifStatement.Statement as BlockSyntax; var ifBlockStatements = ifBlock.Statements; // The new if-statement should retain the formatting of the trivia before and after the if-statement. // The following statements extract the original trivia. var ifKeyword = ifStatement.IfKeyword; var leadingTrivia = ifKeyword.LeadingTrivia; var closeBrace = ifBlock.CloseBraceToken; var trailingTrivia = closeBrace.TrailingTrivia; // If-statements generated using SyntaxGenerator are formatted with the desired spacing by default so this is not specified explicitly. var newIfStatement = generator.IfStatement(ifStatement.Condition, ifBlockStatements).WithLeadingTrivia(leadingTrivia).WithTrailingTrivia(trailingTrivia); // This statement gets the top of the syntax tree so that the old if-statement node can be replaced with the new one. var root = await document.GetSyntaxRootAsync(); // A new root is created with the old if-statement replaced by the new one. var newRoot = root.ReplaceNode(ifStatement, newIfStatement); // A new document with the new root is returned. var newDocument = document.WithSyntaxRoot(newRoot); return newDocument; }
public (SyntaxTree syntaxTree, SemanticModel semModel) GetDocumentModels(Microsoft.CodeAnalysis.Document document) { var root = document.GetSyntaxRootAsync().Result; var syntaxTree = root.SyntaxTree; var semModel = document.GetSemanticModelAsync().Result; return(syntaxTree, semModel); }
protected override void CommandCallback(object sender, EventArgs e) { IWpfTextView textView = ServiceProvider.GetWpfTextView(); if (textView == null) { return; } SnapshotPoint caretPosition = textView.Caret.Position.BufferPosition; ITextSnapshotLine caretLine = caretPosition.GetContainingLine(); if (caretLine == null) { return; } Document document = caretPosition.Snapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document == null) { return; } (SyntaxNode syntaxRoot, SemanticModel semanticModel) = ThreadHelper.JoinableTaskFactory.Run( async() => (await document.GetSyntaxRootAsync(), await document.GetSemanticModelAsync())); if (syntaxRoot == null || semanticModel == null) { return; } TextSpan lineSpan = TextSpan.FromBounds(caretLine.Start.Position, caretLine.End.Position); var memberNode = syntaxRoot.FindNode(lineSpan) as MemberDeclarationSyntax; if (memberNode == null) { return; } PXContext context = new PXContext(semanticModel.Compilation); if (!context.IsPlatformReferenced) { return; } ISymbol memberSymbol = GetMemberSymbol(memberNode, semanticModel, caretPosition); if (!CheckMemberSymbol(memberSymbol, context)) { return; } NavigateToHandlerOrDeclaration(document, textView, memberSymbol, memberNode, semanticModel, context); }
public async Task <(SyntaxTree syntaxTree, SemanticModel semModel)> GetDocumentModelsAsync(Microsoft.CodeAnalysis.Document document) { var root = await document.GetSyntaxRootAsync(); var syntaxTree = root.SyntaxTree; var semModel = await document.GetSemanticModelAsync(); return(syntaxTree, semModel); }
/// <summary> /// Get the Type of the selected text. e.g. for a local variable, we need to get the type of the /// variable instead of the variable itself /// </summary> /// <returns></returns> private ISymbol getChosenSymbol() { ISymbol selected = null; var textView = getTextView(); Microsoft.CodeAnalysis.Document codeDoc = GetRoslynDocument(); //textfeature extension method var semanticModel = codeDoc.GetSemanticModelAsync().Result; SyntaxNode rootNode = codeDoc.GetSyntaxRootAsync().Result; var pos = textView.Caret.Position.BufferPosition; var st = rootNode.FindToken(pos); var curNode = rootNode.FindNode( new Microsoft.CodeAnalysis.Text.TextSpan(pos.Position, 0)); if (curNode == null) { curNode = st.Parent; } var sym = GetSymbolResolvableByILSpy(semanticModel, curNode); if (sym != null) { return(sym); } var parentKind = st.Parent.RawKind; //credit: https://github.com/verysimplenick/GoToDnSpy/blob/master/GoToDnSpy/GoToDnSpy.cs //a SyntaxNode is parent of a SyntaxToken if (st.RawKind == (int)SyntaxKind.IdentifierToken) { selected = semanticModel.LookupSymbols(pos.Position, name: st.Text).FirstOrDefault(); } else { var symbolInfo = semanticModel.GetSymbolInfo(st.Parent); selected = symbolInfo.Symbol ?? (symbolInfo.GetType().GetProperty("CandidateSymbols") .GetValue(symbolInfo) as IEnumerable <ISymbol>)?.FirstOrDefault(); } var localSymbol = selected as ILocalSymbol; var rs = (localSymbol == null) ? selected : localSymbol.Type; return(rs); }
protected virtual async Task CommandCallbackAsync() { IWpfTextView textView = await ServiceProvider.GetWpfTextViewAsync(); if (textView == null) { return; } SnapshotPoint caretPosition = textView.Caret.Position.BufferPosition; ITextSnapshotLine caretLine = caretPosition.GetContainingLine(); if (caretLine == null) { return; } Document document = caretPosition.Snapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document == null || !document.SupportsSyntaxTree /*|| document.SourceCodeKind ==*/) { return; } Task <SyntaxNode> syntaxRootTask = document.GetSyntaxRootAsync(Package.DisposalToken); Task <SemanticModel> semanticModelTask = document.GetSemanticModelAsync(Package.DisposalToken); await Task.WhenAll(syntaxRootTask, semanticModelTask); #pragma warning disable VSTHRD002, VSTHRD103 // Avoid problematic synchronous waits - the results are already obtained SyntaxNode syntaxRoot = syntaxRootTask.Result; SemanticModel semanticModel = semanticModelTask.Result; #pragma warning restore VSTHRD002, VSTHRD103 if (syntaxRoot == null || semanticModel == null || !IsPlatformReferenced(semanticModel) || Package.DisposalToken.IsCancellationRequested) { return; } TextSpan caretSpan = GetTextSpanFromCaret(caretPosition, caretLine); List <DiagnosticData> diagnosticData = await GetDiagnosticsAsync(document, caretSpan); SyntaxNode nodeWithDiagnostic = syntaxRoot.FindNode(caretSpan); if (nodeWithDiagnostic != null) { await SuppressDiagnosticsAsync(diagnosticData, document, syntaxRoot, semanticModel, nodeWithDiagnostic); } }
private static async Task <Document> AddMigrationMethod(Document document, TypeDeclarationSyntax typeDecl, CancellationToken ct) { var semanticModel = await document.GetSemanticModelAsync(ct); var typeSymbol = semanticModel.GetDeclaredSymbol(typeDecl, ct); var latestMigrationMethod = MigrationHashHelper.GetMigrationMethods(typeSymbol).LastOrDefault(); var latestVersion = latestMigrationMethod?.ToVersion ?? 0; var dataArgumentTypeName = latestMigrationMethod?.ReturnType.Name ?? "JToken"; var method = GetMigrationMethod(latestVersion + 1, dataArgumentTypeName, ct); var typeDeclWithUpdatedMigrationHash = MigrationHashHelper.UpdateMigrationHash(typeDecl, ct, semanticModel); var typeDeclWithAddedMigrationMethod = AddMember(typeDeclWithUpdatedMigrationHash, method); var root = (CompilationUnitSyntax)await document.GetSyntaxRootAsync(ct); var rootWithNewTypeDecl = root.ReplaceNode(typeDecl, typeDeclWithAddedMigrationMethod); return(document.WithSyntaxRoot(rootWithNewTypeDecl)); }
static async Task UpdateDocument(ConcurrentDictionary <DocumentId, List <DeclaredSymbolInfo> > result, Microsoft.CodeAnalysis.Document document, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var infos = new List <DeclaredSymbolInfo> (); foreach (var current in root.DescendantNodesAndSelf(CSharpSyntaxFactsService.DescentIntoSymbolForDeclarationSearch)) { cancellationToken.ThrowIfCancellationRequested(); DeclaredSymbolInfo declaredSymbolInfo; if (current.TryGetDeclaredSymbolInfo(out declaredSymbolInfo)) { declaredSymbolInfo.Document = document; infos.Add(declaredSymbolInfo); } } RemoveDocument(result, document.Id); result.TryAdd(document.Id, infos); }
// Helpers/Refactoring private static async Task GetRefactoringActionsAsync(CodeRefactoringProvider refactorer, Document document, List <CodeAction> actions, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false) ?? throw new Exception("Document is not found");; var context = new CodeRefactoringContext(document, root.FullSpan, action => actions.Add(action), cancellationToken); await refactorer.ComputeRefactoringsAsync(context).ConfigureAwait(false); }
private async System.Threading.Tasks.Task CommandCallbackAsync() { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); IWpfTextView textView = await ServiceProvider.GetWpfTextViewAsync(); if (textView == null) { return; } SnapshotPoint caretPosition = textView.Caret.Position.BufferPosition; ITextSnapshotLine caretLine = caretPosition.GetContainingLine(); if (caretLine == null) { return; } Document document = caretPosition.Snapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document == null) { return; } await TaskScheduler.Default; //Go to background thread SyntaxNode syntaxRoot = await document.GetSyntaxRootAsync(); SemanticModel semanticModel = await document.GetSemanticModelAsync(); if (syntaxRoot == null || semanticModel == null) { return; } //TextSpan lineSpan = TextSpan.FromBounds(caretLine.Start.Position, caretLine.End.Position); //var memberNode = syntaxRoot.FindNode(lineSpan) as MemberDeclarationSyntax; // if (memberNode == null) // return; SyntaxNode fixedRoot; #region todo if (textView.Selection.IsActive && !textView.Selection.IsEmpty) // if has selection { // todo: check selection //// Find all nodes within the span and format them //var selectionSpan = TextSpan.FromBounds(textView.Selection.Start.Position, textView.Selection.End.Position); //SyntaxNode topNode = syntaxRoot.FindNode(selectionSpan); // can, return top node that intersects with selectionSpan, so we need SpanWalker here //if (topNode == null) // return; // nothing to format (e.g. selection contains only trivia) //var spanWalker = new SpanWalker(selectionSpan); //spanWalker.Visit(topNode); //if (spanWalker.NodesWithinSpan.Count == 0) // return; //fixedRoot = syntaxRoot.ReplaceNodes(spanWalker.NodesWithinSpan, (o, r) => formatter.Format(o, semanticModel)); } else { } #endregion fixedRoot = new AngleBracesBqlRewriter(semanticModel).Visit(syntaxRoot); var newDocument = document.WithSyntaxRoot(fixedRoot); SyntaxNode newSyntaxRoot = await newDocument.GetSyntaxRootAsync(); SemanticModel newSemanticModel = await newDocument.GetSemanticModelAsync(); if (newSyntaxRoot == null || newSemanticModel == null) { return; } // have to format, because cannot save all original indention BqlFormatter formatter = BqlFormatter.FromTextView(textView); var formatedRoot = formatter.Format(newSyntaxRoot, newSemanticModel); await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); // Return to UI thread if (!textView.TextBuffer.EditInProgress) { var formattedDocument = document.WithSyntaxRoot(formatedRoot); ApplyChanges(document, formattedDocument); } }
private async Task CommandCallbackAsync() { IWpfTextView textView = await ServiceProvider.GetWpfTextViewAsync(); if (textView == null || Package.DisposalToken.IsCancellationRequested) { return; } SnapshotPoint caretPosition = textView.Caret.Position.BufferPosition; ITextSnapshotLine caretLine = caretPosition.GetContainingLine(); if (caretLine == null) { return; } Document document = caretPosition.Snapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document == null || Package.DisposalToken.IsCancellationRequested) { return; } Task <SyntaxNode> syntaxRootTask = document.GetSyntaxRootAsync(); Task <SemanticModel> semanticModelTask = document.GetSemanticModelAsync(); await Task.WhenAll(syntaxRootTask, semanticModelTask); #pragma warning disable VSTHRD002, VSTHRD103 // Avoid problematic synchronous waits - the results are already obtained SyntaxNode syntaxRoot = syntaxRootTask.Result; SemanticModel semanticModel = semanticModelTask.Result; #pragma warning restore VSTHRD002, VSTHRD103 if (syntaxRoot == null || semanticModel == null) { return; } TextSpan lineSpan = TextSpan.FromBounds(caretLine.Start.Position, caretLine.End.Position); if (!(syntaxRoot.FindNode(lineSpan) is MemberDeclarationSyntax memberNode)) { return; } PXContext context = new PXContext(semanticModel.Compilation, Acuminator.Utilities.CodeAnalysisSettings.Default); if (!context.IsPlatformReferenced || Package.DisposalToken.IsCancellationRequested) { return; } ISymbol memberSymbol = GetMemberSymbol(memberNode, semanticModel, caretPosition); if (!CheckMemberSymbol(memberSymbol, context)) { return; } await NavigateToHandlerOrDeclarationAsync(document, textView, memberSymbol, memberNode, semanticModel, context); }
private async Task AddNamespaces(Project project, MSDocument msDocument) { // We use the syntax tree to find all declareded classes inside this dockument var syntaxRoot = await msDocument.GetSyntaxRootAsync(); // We need the semanic model to query some informations of nodes var semanticModel = await msDocument.GetSemanticModelAsync(); var referencedNamespaces = GetRelatedNamespaces(syntaxRoot, semanticModel); // Use the syntax tree to get all namepace definitions inside var namespaces = syntaxRoot.DescendantNodesAndSelf().OfType <NamespaceDeclarationSyntax>(); foreach (var namespaceDeclarationSyntax in namespaces) { // Get the symbol for namespace from model to get full name of namespace var namespaceSymbol = semanticModel.GetDeclaredSymbol(namespaceDeclarationSyntax); var namespaceName = namespaceSymbol.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat); // Check for exisiting namespace var @namespace = project.Namespaces.FirstOrDefault(x => x.Name.Equals(namespaceName)); if (@namespace == null) { @namespace = new Namespace(Guid.NewGuid(), namespaceName, project); project.Namespaces.Add(@namespace); _namespaceToNamespaceMapping.Add(@namespace, referencedNamespaces); } else { _namespaceToNamespaceMapping[@namespace] = _namespaceToNamespaceMapping[@namespace] .Union(referencedNamespaces).ToList(); } // Use the syntax tree to get all classes declarations inside var classes = namespaceDeclarationSyntax.DescendantNodes().OfType <ClassDeclarationSyntax>(); // Handle each class declaration inside the namespace foreach (var classDeclaration in classes) { var symbol = semanticModel.GetDeclaredSymbol(classDeclaration); var baseList = classDeclaration.BaseList; var referencedClasses = GetReturnType(baseList, semanticModel); CreateClass(classDeclaration, symbol, @namespace, referencedClasses, referencedNamespaces, semanticModel, msDocument.FilePath); } // Use the syntax tree to get all interface declations inside var interfaces = namespaceDeclarationSyntax.DescendantNodes().OfType <InterfaceDeclarationSyntax>(); foreach (var interfaceDeclaration in interfaces) { var symbol = semanticModel.GetDeclaredSymbol(interfaceDeclaration); var baseList = interfaceDeclaration.BaseList; var referencedClasses = GetReturnType(baseList, semanticModel); CreateClass(interfaceDeclaration, symbol, @namespace, referencedClasses, referencedNamespaces, semanticModel, msDocument.FilePath); } } }
/// <summary> /// This function is the callback used to execute the command when the menu item is clicked. /// See the constructor to see how the menu item is associated with this function using /// OleMenuCommandService service and MenuCommand class. /// </summary> /// <param name="sender">Event sender.</param> /// <param name="e">Event args.</param> #pragma warning disable VSTHRD100 // Avoid async void methods private async void MenuItemCallback(object sender, EventArgs e) #pragma warning restore VSTHRD100 // Avoid async void methods { try { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); _statusBar.SetText(""); var dnSpyPath = ReadDnSpyPath()?.Trim(_pathTrimChars); var loadPrevious = ReadLoadPrevious(); if (string.IsNullOrWhiteSpace(dnSpyPath)) { MessageBox.Show("You must specify dnSpy path in options", "[GoToDnSpy] Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if (!File.Exists(dnSpyPath)) { MessageBox.Show($"File '{dnSpyPath}' doesn't exist!", "[GoToDnSpy] Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } var textView = GetTextView(); if (textView == null) { _statusBar.SetText("Can't get a text view, please open the file and execute the command while a document window is active."); return; } SnapshotPoint caretPosition = textView.Caret.Position.BufferPosition; Microsoft.CodeAnalysis.Document document = caretPosition.Snapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document == null) { _statusBar.SetText("You should execute the command while a document window is active."); return; } SyntaxNode rootSyntaxNode = await document.GetSyntaxRootAsync().ConfigureAwait(true); SyntaxToken st = rootSyntaxNode.FindToken(caretPosition); SemanticModel semanticModel = await document.GetSemanticModelAsync().ConfigureAwait(true); ISymbol symbol = null; var parentKind = st.Parent.Kind(); if (st.Kind() == SyntaxKind.IdentifierToken && ( parentKind == SyntaxKind.PropertyDeclaration || parentKind == SyntaxKind.FieldDeclaration || parentKind == SyntaxKind.MethodDeclaration || parentKind == SyntaxKind.NamespaceDeclaration || parentKind == SyntaxKind.DestructorDeclaration || parentKind == SyntaxKind.ConstructorDeclaration || parentKind == SyntaxKind.OperatorDeclaration || parentKind == SyntaxKind.ConversionOperatorDeclaration || parentKind == SyntaxKind.EnumDeclaration || parentKind == SyntaxKind.EnumMemberDeclaration || parentKind == SyntaxKind.ClassDeclaration || parentKind == SyntaxKind.EventDeclaration || parentKind == SyntaxKind.EventFieldDeclaration || parentKind == SyntaxKind.InterfaceDeclaration || parentKind == SyntaxKind.StructDeclaration || parentKind == SyntaxKind.DelegateDeclaration || parentKind == SyntaxKind.IndexerDeclaration || parentKind == SyntaxKind.VariableDeclarator )) { symbol = semanticModel.LookupSymbols(caretPosition.Position, name: st.Text).FirstOrDefault(); } else { SymbolInfo si = semanticModel.GetSymbolInfo(st.Parent); symbol = si.Symbol ?? si.CandidateSymbols.FirstOrDefault(); } TryPreprocessLocal(ref symbol); string memberName = null; MemberType memberType = 0; // todo: view SLaks.Ref12.Services.RoslynSymbolResolver if (symbol == null || ( (!TryHandleAsType(symbol, out INamedTypeSymbol typeSymbol)) && (!TryHandleAsMember(symbol, out typeSymbol, out memberName, out memberType)) )) { var msg = $"{st.Text} is not a valid identifier. token: {st}, Kind: {st.Kind()}"; _statusBar.SetText(msg); Debug.WriteLine(msg); return; } string typeNamespace = GetFullNamespace(typeSymbol); string typeName = typeNamespace + "." + typeSymbol.MetadataName; string asmDef = GetAssemblyDefinition(typeSymbol.ContainingAssembly); string asmPath = GetAssemblyPath(semanticModel, asmDef); if (string.IsNullOrWhiteSpace(asmPath)) { _statusBar.SetText($"Assembly '{asmDef}' with type {typeName} not found;"); return; } else if (!File.Exists(asmPath)) { MessageBox.Show($"Try build project first;\nAssembly '{asmDef}' with type {typeName} not found, path:\n{asmPath}", "[GoToDnSpy] Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } // for netstandard path will be c:\▮▮▮▮\dotnet\sdk\packs\NETStandard.Library.Ref\2.1.0\ref\netstandard2.1\ // also can be with netstandard.library (via nupkg) if (asmPath.IndexOf("NETStandard.Library.Ref", StringComparison.Ordinal) > 0 || asmPath.IndexOf("netstandard.library", StringComparison.Ordinal) > 0 || asmPath.IndexOf("microsoft.netcore.app.ref", StringComparison.Ordinal) > 0) { const string baseUrl = "https://source.dot.net"; var docId = GetDocumentationCommentId(memberName is null ? typeSymbol : symbol); var assemblyName = NetstandardMapper.Get(typeNamespace, typeName); if (assemblyName != null) { var url = baseUrl + "/" + assemblyName + "/a.html#" + GetMD5Hash(docId, 16); System.Diagnostics.Process.Start(new ProcessStartInfo() { UseShellExecute = true, FileName = url, }); return; } } System.Diagnostics.Process.Start(dnSpyPath, BuildDnSpyArguments(asmPath, typeName, memberName, memberType, loadPrevious)); } catch (Exception ex) { _statusBar.SetText(ex.Message); MessageBox.Show($"Some error in GoToDnSpy extensiton.\n Please take a screenshot and create issue on github with this error\n{ex}", "[GoToDnSpy] Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
/// <summary> /// This function is the callback used to execute the command when the menu item is clicked. /// See the constructor to see how the menu item is associated with this function using /// OleMenuCommandService service and MenuCommand class. /// </summary> /// <param name="sender">Event sender.</param> /// <param name="e">Event args.</param> private void MenuItemCallback(object sender, EventArgs e) { ThreadHelper.ThrowIfNotOnUIThread(); try { _statusBar.SetText(""); var dnSpyPath = ReadDnSpyPath()?.Trim(new [] { '\r', '\n', ' ', '\'', '\"' }); if (string.IsNullOrWhiteSpace(dnSpyPath)) { MessageBox.Show("Set dnSpy path in options first!", "[GoToDnSpy] Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if (!File.Exists(dnSpyPath)) { MessageBox.Show($"File '{dnSpyPath}' not exists!", "[GoToDnSpy] Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } var textView = GetTextView(); if (textView == null) { _statusBar.SetText("Can't get text view, please open the file and execute the function while a document window is active."); return; } SnapshotPoint caretPosition = textView.Caret.Position.BufferPosition; Microsoft.CodeAnalysis.Document document = caretPosition.Snapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document == null) { _statusBar.SetText("Execute the function while a document window is active."); return; } SyntaxNode rootSyntaxNode = ThreadHelper.JoinableTaskFactory.Run(() => document.GetSyntaxRootAsync()); SyntaxToken st = rootSyntaxNode.FindToken(caretPosition); SemanticModel semanticModel = ThreadHelper.JoinableTaskFactory.Run(() => document.GetSemanticModelAsync()); ISymbol symbol = null; var parentKind = st.Parent.Kind(); if (st.Kind() == SyntaxKind.IdentifierToken && ( parentKind == SyntaxKind.PropertyDeclaration || parentKind == SyntaxKind.FieldDeclaration || parentKind == SyntaxKind.MethodDeclaration || parentKind == SyntaxKind.NamespaceDeclaration || parentKind == SyntaxKind.DestructorDeclaration || parentKind == SyntaxKind.ConstructorDeclaration || parentKind == SyntaxKind.OperatorDeclaration || parentKind == SyntaxKind.ConversionOperatorDeclaration || parentKind == SyntaxKind.EnumDeclaration || parentKind == SyntaxKind.EnumMemberDeclaration || parentKind == SyntaxKind.ClassDeclaration || parentKind == SyntaxKind.EventDeclaration || parentKind == SyntaxKind.EventFieldDeclaration || parentKind == SyntaxKind.InterfaceDeclaration || parentKind == SyntaxKind.StructDeclaration || parentKind == SyntaxKind.DelegateDeclaration || parentKind == SyntaxKind.IndexerDeclaration || parentKind == SyntaxKind.VariableDeclarator )) { symbol = semanticModel.LookupSymbols(caretPosition.Position, name: st.Text).FirstOrDefault(); } else { SymbolInfo si = semanticModel.GetSymbolInfo(st.Parent); symbol = si.Symbol ?? (si.GetType().GetProperty("CandidateSymbols").GetValue(si) as IEnumerable <ISymbol>)?.FirstOrDefault(); } TryPreprocessLocal(ref symbol); string memberName = null; MemberType memberType = 0; // todo: view SLaks.Ref12.Services.RoslynSymbolResolver if (symbol == null || ( (!TryHandleAsType(symbol, out INamedTypeSymbol typeSymbol)) && (!TryHandleAsMember(symbol, out typeSymbol, out memberName, out memberType)) )) { var msg = $"{st.Text} is not a valid identifier. token: {st.ToString()}, Kind: {st.Kind()}"; _statusBar.SetText(msg); Debug.WriteLine(msg); return; } string typeNamespace = GetFullNamespace(typeSymbol); string typeName = typeNamespace + "." + typeSymbol.MetadataName; string asmDef = GetAssemblyDefinition(typeSymbol.ContainingAssembly); string asmPath = GetAssemblyPath(semanticModel, asmDef); if (string.IsNullOrWhiteSpace(asmPath)) { _statusBar.SetText($"Assembly '{asmDef}' with type {typeName} not found;"); return; } else if (!File.Exists(asmPath)) { MessageBox.Show($"Try build project first;\nAssembly '{asmDef}' with type {typeName} not found, path:\n{asmPath}", "[GoToDnSpy] Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } System.Diagnostics.Process.Start(dnSpyPath, BuildDnSpyArguments(asmPath, typeName, memberName, memberType)); } catch (Exception ex) { _statusBar.SetText(ex.Message.ToString()); MessageBox.Show($"Some error in GoToDnSpy extensiton.\n Please take screenshot and create issue on github with this error\n{ex.ToString()}", "[GoToDnSpy] Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } }