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)) }; }
private static async Task<Document> MakeMock(Document document, SyntaxNode invokationSyntax, CancellationToken cancellationToken) { var testSemanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var testInitMethodDecl = TestSemanticHelper.GetTestInitializeMethod(testSemanticModel); var declaredFields = testInitMethodDecl.Parent.ChildNodes().OfType<FieldDeclarationSyntax>().ToArray(); var suts = testInitMethodDecl.GetSuts(testSemanticModel, declaredFields); var memberAccessExpressions = invokationSyntax.DescendantNodes() .OfType<ExpressionSyntax>() .Where(x => x is InvocationExpressionSyntax || x is MemberAccessExpressionSyntax) .Select(expr => { var memberAccess = expr as MemberAccessExpressionSyntax; var invokationExpression = expr as InvocationExpressionSyntax; var expression = invokationExpression == null ? memberAccess : invokationExpression.Expression; return expression; }); var invokedMethodsOfMocks = memberAccessExpressions.SelectMany(expressionSyntax => MocksAnalyzingEngine.GetInvokedMethodsOfMock(expressionSyntax, testSemanticModel, suts)) .DistinctBy(x => string.Join(",", x.FieldsToSetup.SelectMany(y => y.Field.Select(z => z))) + "," + x.MethodOrPropertySymbol) .ToArray(); if (invokedMethodsOfMocks.Length == 0) return document; var editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false); ChangesMaker.ApplyChanges(invokationSyntax, editor, invokedMethodsOfMocks); return editor.GetChangedDocument(); }
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 Document RemoveUnnecessaryUsings(Document doc, Compilation compilation) { #region CodeContracts Contract.Requires(doc != null); Contract.Requires(compilation != null); Contract.Ensures(Contract.Result<Document>() != null); #endregion CodeContracts var st = doc.GetSyntaxTreeAsync().Result; var sm = doc.GetSemanticModelAsync().Result; //var assembly = Assembly.LoadFrom(@"C:\cci\Microsoft.Research\Imported\Tools\Roslyn\v4.5.1\Microsoft.CodeAnalysis.CSharp.Features.dll"); //var assembly = Assembly.LoadFrom(@"C:\cci\Microsoft.Research\CCTools\ReviewBot\bin\Debug\Microsoft.CodeAnalysis.CSharp.Features.dll"); //var assembly = Assembly.LoadFrom(@"..\..\..\packages\Microsoft.CodeAnalysis.Features.0.7.4040207-beta\lib\net45\Microsoft.CodeAnalysis.CSharp.Features.dll"); //var assembly = Assembly.LoadFrom(@"C:\Users\t-scottc\Desktop\Signed_20140201.1\Microsoft.CodeAnalysis.CSharp.Features.dll"); //var assembly = Assembly.LoadFrom(@"C:\Users\t-scottc\workspace\roslyn\Binaries\Debug\Microsoft.CodeAnalysis.CSharp.Workspaces.dll"); Assembly assembly; if (TryGetMicrosoftCodeAnalysisCSharpFeatures(out assembly)) { var type = assembly.GetType("Microsoft.CodeAnalysis.CSharp.RemoveUnnecessaryImports.CSharpRemoveUnnecessaryImportsService"); var method = type.GetMethod("RemoveUnnecessaryImports"); var service = Activator.CreateInstance(type); return method.Invoke(service, new object[] { doc, sm, st.GetRoot(), CancellationToken.None }) as Document; } else { Output.WriteWarning("Can't run the refactoring to remove using"); return doc; } }
protected override void VisitDocument(Document document, SyntaxNode root) { CSharpSyntaxWalker walker; SemanticModel semanticModel = (SemanticModel)document.GetSemanticModelAsync().Result; if (bool.Parse(ConfigurationManager.AppSettings["IsGeneralTaskifierDetectionEnabled"])) { walker = new GeneralTaskifierDetectionWalker { Result = Result, SemanticModel = semanticModel, Document = document }; walker.Visit(root); } if (bool.Parse(ConfigurationManager.AppSettings["IsThreadUsageDetectionEnabled"])) { walker = new ThreadUsageDetectionWalker { Result = Result, SemanticModel = semanticModel, Document = document }; walker.Visit(root); } if (bool.Parse(ConfigurationManager.AppSettings["IsTasksUsageDetectionEnabled"])) { walker = new TasksUsageDetectionWalker { Result = Result, SemanticModel = semanticModel, Document = document }; walker.Visit(root); } if (bool.Parse(ConfigurationManager.AppSettings["IsSimplifierDetectionEnabled"])) { walker = new SimplifierDetectionWalker { Result = Result, SemanticModel = semanticModel, Document = document }; walker.Visit(root); } }
protected override void VisitDocument(Document document, SyntaxNode root) { CSharpSyntaxWalker walker; SemanticModel semanticModel = (SemanticModel)document.GetSemanticModelAsync().Result; if (bool.Parse(ConfigurationManager.AppSettings["IsCPUAsyncDetectionEnabled"])) { walker = new CPUAsyncDetectionWalker { Result = Result, SemanticModel = semanticModel, Document = document }; walker.Visit(root); } if (bool.Parse(ConfigurationManager.AppSettings["IsAsyncAwaitDetectionEnabled"])) { walker = new AsyncAwaitConsultingDetectionWalker { Result = Result, SemanticModel = semanticModel, Document = document }; walker.Visit(root); } if (bool.Parse(ConfigurationManager.AppSettings["IsComplexPatternDetectionEnabled"])) { walker = new ComplexPatternDetectionWalker { Result = Result, SemanticModel = semanticModel, Document = document }; walker.Visit(root); } if (bool.Parse(ConfigurationManager.AppSettings["IsAsyncLibraryDetectionWalkerEnabled"])) { walker = new AsyncLibraryDetectionWalker { Result = Result, SemanticModel = semanticModel, Document = document }; walker.Visit(root); } }
static async Task <RefactoringSymbolInfo> InternalGetSymbolInfoAsync(Microsoft.CodeAnalysis.Document document, int offset, CancellationToken cancellationToken = default(CancellationToken)) { if (document == null) { return(RefactoringSymbolInfo.Empty); } var unit = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (unit != null) { var root = await unit.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); try { var token = root.FindToken(offset); if (!token.Span.IntersectsWith(offset)) { return(RefactoringSymbolInfo.Empty); } var symbol = unit.GetSymbolInfo(token.Parent, cancellationToken); return(new RefactoringSymbolInfo(symbol) { DeclaredSymbol = token.IsKind(SyntaxKind.IdentifierToken) ? unit.GetDeclaredSymbol(token.Parent, cancellationToken) : null, Node = token.Parent, Model = unit }); } catch (Exception) { return(RefactoringSymbolInfo.Empty); } } return(RefactoringSymbolInfo.Empty); }
private async Task<Solution> CreateMixin( IMixinCommand mixinCommand, Document document, ClassWithSourceCode childClass, CancellationToken cancellationToken) { // get service provider and read settings from storage var serviceProvider = Microsoft.VisualStudio.Shell.ServiceProvider.GlobalProvider; var settings = new Settings(serviceProvider); var model = await document.GetSemanticModelAsync(cancellationToken); if (mixinCommand.CanExecute(childClass,settings)) { // execute the command => we get a new class declaration var newClassDeclaration = mixinCommand.Execute(childClass.SourceCode, model,settings); // replace the old class declaration in the syntax tree var root = await model.SyntaxTree.GetRootAsync(cancellationToken); var newRoot = root.ReplaceNode(childClass.SourceCode, newClassDeclaration); // create a new document from the new syntax tree var newDocument = document.WithSyntaxRoot(newRoot); return newDocument.Project.Solution; } return null; }
private async Task<Document> InsertStopwatchToMeasureTime(Document document, IdentifierNameSyntax node, CancellationToken cancellationToken) { SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken); var nodes = new List<Tuple<SyntaxNode, SyntaxNode>>(); SyntaxNode nodeLine = GetRootNodeOfLine(node); SyntaxNode newNode = CommentLine(nodeLine); newNode = newNode.WithTrailingTrivia(newNode.GetTrailingTrivia() .AddRange(nodeLine.GetLeadingTrivia()) .Add(SyntaxFactory.SyntaxTrivia(SyntaxKind.SingleLineCommentTrivia, "timer.Stop();")) .Add(SyntaxFactory.EndOfLine(Environment.NewLine)) .AddRange(nodeLine.GetLeadingTrivia()) .Add(SyntaxFactory.SyntaxTrivia(SyntaxKind.SingleLineCommentTrivia, "TimeSpan elapsed = timer.Elapsed;")) .Add(SyntaxFactory.EndOfLine(Environment.NewLine))); nodes.Add(new Tuple<SyntaxNode, SyntaxNode>(nodeLine, newNode)); var methodDeclaration = node.FirstAncestorOfType(typeof(MethodDeclarationSyntax)) as MethodDeclarationSyntax; if (semanticModel == null) { return document; } SyntaxNode firstGetTime = TimeMeasurementCodeAnalyzer.GetNodesUsedToGetCurrentTime(semanticModel, methodDeclaration).First(); nodeLine = GetRootNodeOfLine(firstGetTime); newNode = CommentLine(nodeLine); newNode = newNode.WithTrailingTrivia(newNode.GetTrailingTrivia() .AddRange(nodeLine.GetLeadingTrivia()) .Add(SyntaxFactory.SyntaxTrivia(SyntaxKind.SingleLineCommentTrivia, "var timer = Stopwatch.StartNew();")) .Add(SyntaxFactory.EndOfLine(Environment.NewLine))); nodes.Add(new Tuple<SyntaxNode, SyntaxNode>(nodeLine, newNode)); document = await this.ReplaceNodesInDocumentAsync(document, cancellationToken, nodes.ToArray()); return await this.CheckNamespaceUsageAsync(document, cancellationToken, "System.Diagnostics"); }
private async Task<Document> RepairXmlCommentAsync(Document document, MethodDeclarationSyntax methodSyntax, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var methodSymbol = model.GetDeclaredSymbol(methodSyntax); var xml = methodSymbol.GetDocumentationCommentXml(); var documentTrivia = methodSyntax.GetLeadingTrivia().Where(n => n.Kind() == SyntaxKind.SingleLineDocumentationCommentTrivia).Last(); var documentText = documentTrivia.ToFullString().TrimEnd(); var invalidXml = Regex.Replace(documentText, @"^\s*///", "", RegexOptions.Multiline); var newXml = RpairXml(invalidXml); var newDocumentCommentText = Regex.Replace(newXml, @"^", "///", RegexOptions.Multiline) + "\r\n"; var newDocumentTrivia = SyntaxFactory.ParseLeadingTrivia(newDocumentCommentText)[0]; var newRoot = root.ReplaceTrivia(documentTrivia, newDocumentTrivia.WithAdditionalAnnotations(Formatter.Annotation)); var newDocument = document.WithSyntaxRoot(newRoot); return newDocument; }
internal static async Task<DebugLocationInfo> GetInfoAsync(Document document, int position, CancellationToken cancellationToken) { string name = null; int lineOffset = 0; // Note that we get the current partial solution here. Technically, this means that we may // not fully understand the signature of the member. But that's ok. We just need this // symbol so we can create a display string to put into the debugger. If we try to // find the document in the "CurrentSolution" then when we try to get the semantic // model below then it might take a *long* time as all dependent compilations are built. var tree = await document.GetCSharpSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var root = await tree.GetRootAsync(cancellationToken).ConfigureAwait(false); var token = root.FindToken(position); SyntaxNode memberDecl = token.GetAncestor<MemberDeclarationSyntax>(); // field or event field declarations may contain multiple variable declarators. Try finding the correct one. // If the position does not point to one, try using the first one. if (memberDecl != null && (memberDecl.Kind() == SyntaxKind.FieldDeclaration || memberDecl.Kind() == SyntaxKind.EventFieldDeclaration)) { SeparatedSyntaxList<VariableDeclaratorSyntax> variableDeclarators = ((BaseFieldDeclarationSyntax)memberDecl).Declaration.Variables; foreach (var declarator in variableDeclarators) { if (declarator.FullSpan.Contains(token.FullSpan)) { memberDecl = declarator; break; } } if (memberDecl == null) { memberDecl = variableDeclarators.Count > 0 ? variableDeclarators[0] : null; } } if (memberDecl != null) { var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var memberSymbol = semanticModel.GetDeclaredSymbol(memberDecl, cancellationToken); if (memberSymbol != null) { var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var lineNumber = text.Lines.GetLineFromPosition(position).LineNumber; var accessor = token.GetAncestor<AccessorDeclarationSyntax>(); var memberLine = accessor == null ? text.Lines.GetLineFromPosition(memberDecl.SpanStart).LineNumber : text.Lines.GetLineFromPosition(accessor.SpanStart).LineNumber; name = memberSymbol.ToDisplayString(s_nameFormat); lineOffset = lineNumber - memberLine; return new DebugLocationInfo(name, lineOffset); } } return default(DebugLocationInfo); }
private async Task<Document> CreateInterpolatedString(InvocationExpressionSyntax invocation, Document document, CancellationToken cancellationToken) { Assert(invocation.ArgumentList != null); Assert(invocation.ArgumentList.Arguments.Count >= 2); Assert(invocation.ArgumentList.Arguments[0].Expression.IsKind(SyntaxKind.StringLiteralExpression)); var semanticModel = await document.GetSemanticModelAsync(cancellationToken); var arguments = invocation.ArgumentList.Arguments; var text = ((LiteralExpressionSyntax)arguments[0].Expression).Token.ToString(); var builder = ImmutableArray.CreateBuilder<ExpressionSyntax>(); for (int i = 1; i < arguments.Count; i++) { builder.Add(CastAndParenthesize(arguments[i].Expression, semanticModel)); } var expandedArguments = builder.ToImmutable(); var interpolatedString = (InterpolatedStringExpressionSyntax)SyntaxFactory.ParseExpression("$" + text); var newInterpolatedString = InterpolatedStringRewriter.Visit(interpolatedString, expandedArguments); var root = await document.GetSyntaxRootAsync(cancellationToken); var newRoot = root.ReplaceNode(invocation, newInterpolatedString); return document.WithSyntaxRoot(newRoot); }
private async Task<Solution> RenameType(Document document, BaseTypeDeclarationSyntax typeDecl, CancellationToken cancellationToken) { try { var newName = GetDocumentName(document); // Get the symbol representing the type to be renamed. var semanticModel = await document.GetSemanticModelAsync(cancellationToken); var typeSymbol = semanticModel.GetDeclaredSymbol(typeDecl, cancellationToken); // Produce a new solution that has all references to that type renamed, including the declaration. var originalSolution = document.Project.Solution; var optionSet = originalSolution.Workspace.Options; var newSolution = await Renamer.RenameSymbolAsync(document.Project.Solution, typeSymbol, newName, optionSet, cancellationToken).ConfigureAwait(false); // Return the new solution with the now-uppercase type name. return newSolution; } catch (Exception e) { LogException(e); return document.Project.Solution; } }
/// <summary> /// Réordonne les assignations d'un constructeur. /// </summary> /// <param name="document">Le document.</param> /// <param name="constructeur">Le constructeur.</param> /// <param name="jetonAnnulation">Le jeton d'annulation.</param> /// <returns>Le nouveau document.</returns> private async Task<Document> OrdonnerAssignations(Document document, ConstructorDeclarationSyntax constructeur, CancellationToken jetonAnnulation) { // On récupère la racine et le modèle sémantique. var racine = await document .GetSyntaxRootAsync(jetonAnnulation) .ConfigureAwait(false); var modèleSémantique = await document.GetSemanticModelAsync(jetonAnnulation); // On récupère le corps du constructeur. var corps = constructeur.ChildNodes().First(nœud => nœud as BlockSyntax != null) as BlockSyntax; // On récupère toutes les conditions sur les paramètres. var conditions = Partagé.TrouveConditionsParametres(corps.Statements, constructeur.ParameterList, modèleSémantique); // On récupère les assignations et on les ordonne. var assignations = Partagé.TrouverAssignations(corps.Statements, modèleSémantique) .OrderBy(e => e.ToString()); // On construit le nouveau corps du constructeur. var corpsOrdonné = corps.WithStatements( SyntaxFactory.List( conditions .Concat(assignations) .Concat(corps.Statements .Except(conditions) .Except(assignations)))); // Et on met à jour la racine. var nouvelleRacine = racine.ReplaceNode(corps, corpsOrdonné); return document.WithSyntaxRoot(nouvelleRacine); }
public async Task<Document> AddSourceToAsync(Document document, ISymbol symbol, CancellationToken cancellationToken) { if (document == null) { throw new ArgumentNullException(nameof(document)); } var newSemanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var rootNamespace = newSemanticModel.GetEnclosingNamespace(0, cancellationToken); // Add the interface of the symbol to the top of the root namespace document = await CodeGenerator.AddNamespaceOrTypeDeclarationAsync( document.Project.Solution, rootNamespace, CreateCodeGenerationSymbol(document, symbol), CreateCodeGenerationOptions(newSemanticModel.SyntaxTree.GetLocation(new TextSpan()), symbol), cancellationToken).ConfigureAwait(false); var docCommentFormattingService = document.GetLanguageService<IDocumentationCommentFormattingService>(); var docWithDocComments = await ConvertDocCommentsToRegularComments(document, docCommentFormattingService, cancellationToken).ConfigureAwait(false); var docWithAssemblyInfo = await AddAssemblyInfoRegionAsync(docWithDocComments, symbol.GetOriginalUnreducedDefinition(), cancellationToken).ConfigureAwait(false); var node = await docWithAssemblyInfo.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var formattedDoc = await Formatter.FormatAsync( docWithAssemblyInfo, SpecializedCollections.SingletonEnumerable(node.FullSpan), options: null, rules: GetFormattingRules(docWithAssemblyInfo), cancellationToken: cancellationToken).ConfigureAwait(false); var reducers = this.GetReducers(); return await Simplifier.ReduceAsync(formattedDoc, reducers, null, cancellationToken).ConfigureAwait(false); }
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; }
/// <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 async Task<Document> IncreaseVisibility(Document document, SyntaxNode node, CancellationToken cancellationToken) { DocumentEditor editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false); SemanticModel model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); SyntaxNode declaration = editor.Generator.GetDeclaration(node); ISymbol symbol = editor.SemanticModel.GetDeclaredSymbol(node); System.Collections.Generic.IEnumerable<INamedTypeSymbol> ancestorTypes = symbol?.ContainingType?.GetBaseTypes() ?? Enumerable.Empty<INamedTypeSymbol>(); System.Collections.Generic.IEnumerable<ISymbol> hiddenOrOverriddenMembers = ancestorTypes.SelectMany(t => t.GetMembers(symbol.Name)); // Check if a public member was overridden if (hiddenOrOverriddenMembers.Any(s => s.DeclaredAccessibility == Accessibility.Public)) { IncreaseVisibility(editor, declaration, Accessibility.Public); return editor.GetChangedDocument(); } // Otherwise, check if a protected or internal member was overridden if (hiddenOrOverriddenMembers.Any(s => s.DeclaredAccessibility == Accessibility.ProtectedOrInternal)) { IncreaseVisibility(editor, declaration, Accessibility.ProtectedOrInternal); return editor.GetChangedDocument(); } // Otherwise, check if a protected member was overridden if (hiddenOrOverriddenMembers.Any(s => s.DeclaredAccessibility == Accessibility.Protected)) { IncreaseVisibility(editor, declaration, Accessibility.Protected); return editor.GetChangedDocument(); } // Otherwise, make no change return document; }
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; }
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; }
protected override async Task <ISymbol> GetSymbol(Document document, int tokenPosition, CancellationToken cancellationToken) { SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken); var syntaxTree = await semanticModel.SyntaxTree.GetRootAsync(cancellationToken); var token = syntaxTree.FindToken(tokenPosition); if (token.Parent is MethodDeclarationSyntax m) { return(ModelExtensions.GetDeclaredSymbol(semanticModel, m, cancellationToken)); } if (token.Parent is ClassDeclarationSyntax c) { return(ModelExtensions.GetDeclaredSymbol(semanticModel, c, cancellationToken)); } if (token.Parent is StructDeclarationSyntax s) { return(ModelExtensions.GetDeclaredSymbol(semanticModel, s, cancellationToken)); } return(null); }
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 <ImmutableArray <Diagnostic> > GetDiagnosticsForDocument(ImmutableArray <DiagnosticAnalyzer> analyzers, Microsoft.CodeAnalysis.Document doc, ImmutableHashSet <string> diagnostics, CancellationToken token) { var sol = doc.Project.Solution; var options = new CompilationWithAnalyzersOptions( new WorkspaceAnalyzerOptions( new AnalyzerOptions(ImmutableArray <AdditionalText> .Empty), sol.Options, sol), delegate(Exception exception, DiagnosticAnalyzer analyzer, Diagnostic diag) { LoggingService.LogError("Exception in diagnostic analyzer " + diag.Id + ":" + diag.GetMessage(), exception); }, true, false ); var model = await doc.GetSemanticModelAsync(token).ConfigureAwait(false); var compilationWithAnalyzer = model.Compilation.WithAnalyzers(analyzers, options); var diagnosticList = new List <Diagnostic> (); diagnosticList.AddRange(await compilationWithAnalyzer.GetAnalyzerSemanticDiagnosticsAsync(model, null, token).ConfigureAwait(false)); diagnosticList.AddRange(await compilationWithAnalyzer.GetAnalyzerSemanticDiagnosticsAsync(model, null, token).ConfigureAwait(false)); return(diagnosticList.ToImmutableArray()); }
private void TestSymbolSerialization(Document document, string symbolName) { var model = document.GetSemanticModelAsync().Result; var name = CS.SyntaxFactory.ParseName(symbolName); var symbol = model.GetSpeculativeSymbolInfo(0, name, SpeculativeBindingOption.BindAsExpression).Symbol; var root = (CS.Syntax.CompilationUnitSyntax)model.SyntaxTree.GetRoot(); var annotation = SymbolAnnotation.Create(symbol); var rootWithAnnotation = root.WithAdditionalAnnotations(annotation); Assert.Equal(true, rootWithAnnotation.ContainsAnnotations); Assert.Equal(true, rootWithAnnotation.HasAnnotation(annotation)); var stream = new MemoryStream(); rootWithAnnotation.SerializeTo(stream); stream.Position = 0; var droot = CS.CSharpSyntaxNode.DeserializeFrom(stream); Assert.Equal(true, droot.ContainsAnnotations); Assert.Equal(true, droot.HasAnnotation(annotation)); var dannotation = droot.GetAnnotations(SymbolAnnotation.Kind).SingleOrDefault(); Assert.NotNull(dannotation); Assert.NotSame(annotation, dannotation); Assert.Equal(annotation, dannotation); var id = SymbolAnnotation.GetSymbol(annotation, model.Compilation); var did = SymbolAnnotation.GetSymbol(dannotation, model.Compilation); Assert.Equal(true, id.Equals(did)); }
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 static Task<Document> ChangePropertySetAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken, FixType fixType) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var diagnosticSpan = diagnostic.Location.SourceSpan; var propertyStatement = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf().OfType<PropertyDeclarationSyntax>().First(); var semanticModel = await document.GetSemanticModelAsync(cancellationToken); var getAcessor = (propertyStatement.AccessorList.Accessors[0].Keyword.Text == "get") ? propertyStatement.AccessorList.Accessors[0] : propertyStatement.AccessorList.Accessors[1]; var setAcessor = (propertyStatement.AccessorList.Accessors[0].Keyword.Text == "set") ? propertyStatement.AccessorList.Accessors[0] : propertyStatement.AccessorList.Accessors[1]; var privateprotectedModifier = SyntaxFactory.Token(fixType == FixType.PrivateFix ? SyntaxKind.PrivateKeyword : SyntaxKind.ProtectedKeyword) .WithAdditionalAnnotations(Formatter.Annotation); var modifiers = setAcessor.Modifiers.Add(privateprotectedModifier); setAcessor = setAcessor.WithModifiers(modifiers); var newProperty = SyntaxFactory.PropertyDeclaration(propertyStatement.Type, propertyStatement.Identifier) .WithModifiers(propertyStatement.Modifiers) .WithAccessorList(SyntaxFactory.AccessorList(SyntaxFactory.List<AccessorDeclarationSyntax>(new AccessorDeclarationSyntax[] { getAcessor, setAcessor }))) .WithLeadingTrivia(propertyStatement.GetLeadingTrivia()).WithTrailingTrivia(propertyStatement.GetTrailingTrivia()) .WithAdditionalAnnotations(Formatter.Annotation); var newRoot = root.ReplaceNode(propertyStatement, newProperty); 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 oldSemanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var node = syntaxRoot.FindNode(diagnostic.Location.SourceSpan, getInnermostNodeForTie: true) as CastExpressionSyntax; if (node == null) { return document; } var replacementNode = GenerateReplacementNode(node); var newSyntaxRoot = syntaxRoot.ReplaceNode(node, replacementNode); var newDocument = document.WithSyntaxRoot(newSyntaxRoot); var newSemanticModel = await newDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var newNode = newSemanticModel.SyntaxTree.GetRoot().FindNode( span: new TextSpan(start: node.FullSpan.Start, length: replacementNode.FullSpan.Length), getInnermostNodeForTie: true); var oldConstantValue = oldSemanticModel.GetConstantValue(node).Value; var newConstantValueOption = newSemanticModel.GetConstantValue(newNode, cancellationToken); if (newConstantValueOption.HasValue && oldConstantValue.Equals(newConstantValueOption.Value)) { return newDocument; } else { var newNodeBasedOnValue = GenerateReplacementNodeBasedOnValue(node, oldConstantValue); newSyntaxRoot = syntaxRoot.ReplaceNode(node, newNodeBasedOnValue); return document.WithSyntaxRoot(newSyntaxRoot); } }
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 async Task<Document> AddConstructorsAsync(Document document, IEnumerable<Diagnostic> diagnostics, SyntaxNode root, CancellationToken cancellationToken) { var editor = await DocumentEditor.CreateAsync(document, cancellationToken).ConfigureAwait(false); var generator = editor.Generator; var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var diagnosticSpan = diagnostics.First().Location.SourceSpan; // All the diagnostics are reported at the same location -- the name of the declared class -- so it doesn't matter which one we pick var node = root.FindNode(diagnosticSpan); var targetNode = editor.Generator.GetDeclaration(node, DeclarationKind.Class); var typeSymbol = model.GetDeclaredSymbol(targetNode) as INamedTypeSymbol; foreach (var diagnostic in diagnostics) { var missingCtorSignature = (ImplementStandardExceptionConstructorsAnalyzer.MissingCtorSignature)Enum.Parse(typeof(ImplementStandardExceptionConstructorsAnalyzer.MissingCtorSignature), diagnostic.Properties["Signature"]); switch (missingCtorSignature) { case ImplementStandardExceptionConstructorsAnalyzer.MissingCtorSignature.CtorWithNoParameter: // Add missing CtorWithNoParameter var newConstructorNode1 = generator.ConstructorDeclaration(typeSymbol.Name, accessibility: Accessibility.Public); editor.AddMember(targetNode, newConstructorNode1); break; case ImplementStandardExceptionConstructorsAnalyzer.MissingCtorSignature.CtorWithStringParameter: // Add missing CtorWithStringParameter var newConstructorNode2 = generator.ConstructorDeclaration( containingTypeName: typeSymbol.Name, parameters: new[] { generator.ParameterDeclaration("message", generator.TypeExpression(WellKnownTypes.String(editor.SemanticModel.Compilation))) }, accessibility: Accessibility.Public, baseConstructorArguments: new[] { generator.Argument(generator.IdentifierName("message")) }); editor.AddMember(targetNode, newConstructorNode2); break; case ImplementStandardExceptionConstructorsAnalyzer.MissingCtorSignature.CtorWithStringAndExceptionParameters: // Add missing CtorWithStringAndExceptionParameters var newConstructorNode3 = generator.ConstructorDeclaration( containingTypeName: typeSymbol.Name, parameters: new[] { generator.ParameterDeclaration("message", generator.TypeExpression(WellKnownTypes.String(editor.SemanticModel.Compilation))), generator.ParameterDeclaration("innerException", generator.TypeExpression(WellKnownTypes.Exception(editor.SemanticModel.Compilation))) }, accessibility: Accessibility.Public, baseConstructorArguments: new[] { generator.Argument(generator.IdentifierName("message")), generator.Argument(generator.IdentifierName("innerException")) }); editor.AddMember(targetNode, newConstructorNode3); break; } } return editor.GetChangedDocument(); }
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 fieldSymbol = (IFieldSymbol)semanticModel.GetSymbolInfo(returnIdentifier).Symbol; var variableDeclarator = (VariableDeclaratorSyntax)fieldSymbol.DeclaringSyntaxReferences.First().GetSyntax(); var fieldDeclaration = variableDeclarator.FirstAncestorOfType<FieldDeclarationSyntax>(); var propertySymbol = semanticModel.GetDeclaredSymbol(property); var newRoot = root.TrackNodes(returnIdentifier, fieldDeclaration, property, variableDeclarator); //cycle var newDocument = document.WithSyntaxRoot(newRoot); newRoot = await newDocument.GetSyntaxRootAsync(cancellationToken); var newProperty = CreateAutoProperty(property, variableDeclarator, fieldSymbol, propertySymbol); Solution newSolution; if (IsExplicityImplementation(propertySymbol)) { semanticModel = await newDocument.GetSemanticModelAsync(cancellationToken); returnIdentifier = newRoot.GetCurrentNode(returnIdentifier); fieldSymbol = (IFieldSymbol)semanticModel.GetSymbolInfo(returnIdentifier).Symbol; newSolution = await RenameSymbolAndKeepExplicitPropertiesBoundAsync(newDocument.Project.Solution, property.Identifier.ValueText, fieldSymbol, propertySymbol, cancellationToken); newDocument = newSolution.GetDocument(newDocument.Id); newRoot = await newDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); newRoot = newRoot.ReplaceNode(newRoot.GetCurrentNode(property), newProperty); newSolution = newSolution.WithDocumentSyntaxRoot(newDocument.Id, newRoot); } else { var currentProperty = newRoot.GetCurrentNode(property); var type = (TypeDeclarationSyntax)currentProperty.Parent; var propertyIndex = type.Members.IndexOf(currentProperty); //Remove the property: this is needed otherwise the rename that happens bellow will not be able to //correctly redirect the references to the field, as the property will conflict with the name. //The conflict is specially troublesome for circular references, such as the one that caused the bug #702. newRoot = newRoot.ReplaceNode(type, type.RemoveNode(currentProperty, SyntaxRemoveOptions.KeepNoTrivia)); //cycle newDocument = newDocument.WithSyntaxRoot(newRoot); newRoot = await newDocument.GetSyntaxRootAsync(cancellationToken); semanticModel = await newDocument.GetSemanticModelAsync(cancellationToken); fieldSymbol = (IFieldSymbol)semanticModel.GetDeclaredSymbol(newRoot.GetCurrentNode(variableDeclarator)); //rename the field: newSolution = await Renamer.RenameSymbolAsync(newDocument.Project.Solution, fieldSymbol, property.Identifier.ValueText, newDocument.Project.Solution.Workspace.Options, cancellationToken).ConfigureAwait(false); //cycle newDocument = newSolution.GetDocument(newDocument.Id); newRoot = await newDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); //add the property back: var currentType = (TypeDeclarationSyntax)newRoot.GetCurrentNode(fieldDeclaration).Parent; var newMembers = currentType.Members.Insert(propertyIndex, newProperty); var newType = WithMembers(currentType, newMembers); newRoot = newRoot.ReplaceNode(currentType, newType); newSolution = newSolution.WithDocumentSyntaxRoot(newDocument.Id, newRoot); } newDocument = newSolution.GetDocument(newDocument.Id); newRoot = await newDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); newRoot = RemoveField(newRoot, variableDeclarator, fieldDeclaration); return newSolution.WithDocumentSyntaxRoot(newDocument.Id, newRoot); }
//--- Class Methods --- private static async Task<Document> AddMissingEnumFields(Document document, SyntaxToken typeDecl, CancellationToken cancellationToken) { var semanticModel = await document.GetSemanticModelAsync(cancellationToken); var node = (SwitchStatementSyntax)typeDecl.Parent; IdentifierNameSyntax switchVariable; var missingMembers = EnumSwitchAnalysis.GetMissingEnumMembers(node, semanticModel, out switchVariable); if(missingMembers.Any()) { // get existing switchSections var existingSections = node.Sections.ToList(); SwitchSectionSyntax defaultSection = null; if(existingSections.Any() && existingSections.Last().DescendantNodes().OfType<DefaultSwitchLabelSyntax>().Any()) { defaultSection = existingSections.Last(); existingSections = existingSections.Take(existingSections.Count - 1).ToList(); } // generate missing case statements var switchVariableTypeInfo = semanticModel.GetTypeInfo(switchVariable); var newCaseStatements = missingMembers.Select(missingMember => SyntaxFactory.CaseSwitchLabel( SyntaxFactory.Token(SyntaxKind.CaseKeyword), SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName(switchVariableTypeInfo.Type.Name), SyntaxFactory.IdentifierName(missingMember.Name) ), SyntaxFactory.Token(SyntaxKind.ColonToken) ) ).Select(caseSection => SyntaxFactory.SwitchSection( SyntaxFactory.List<SwitchLabelSyntax>(new[] { caseSection }), SyntaxFactory.List<StatementSyntax>().Add( SyntaxFactory.ThrowStatement( SyntaxFactory.ObjectCreationExpression( SyntaxFactory.ParseTypeName(nameof(NotImplementedException)), SyntaxFactory.ArgumentList(), null ) ) ) )).ToImmutableArray(); // insert case statements after the last one var tree = await document.GetSyntaxTreeAsync(cancellationToken); var root = (CompilationUnitSyntax)tree.GetRoot(cancellationToken); var switchStatement = SyntaxFactory.SwitchStatement( SyntaxFactory.IdentifierName(switchVariable.Identifier) .WithLeadingTrivia(switchVariable.GetLeadingTrivia()) .WithTrailingTrivia(switchVariable.GetTrailingTrivia()) ).WithSections( new SyntaxList<SwitchSectionSyntax>() .AddRange(existingSections) .AddRange(newCaseStatements) .AddRange(defaultSection == null ? Enumerable.Empty<SwitchSectionSyntax>() : new [] { defaultSection }) ).WithLeadingTrivia(node.GetLeadingTrivia()) .WithTrailingTrivia(node.GetTrailingTrivia()); root = root.ReplaceNode(node, switchStatement); return document.WithSyntaxRoot(root); } return document; }
async Task<Solution> MoveClassIntoNewFileAsync(Document document, ClassStatementSyntax typeDecl, string className, CancellationToken cancellationToken) { // symbol representing the type var semanticModel = await document.GetSemanticModelAsync(cancellationToken); var typeSymbol = semanticModel.GetDeclaredSymbol(typeDecl, cancellationToken); // remove type from current files var currentSyntaxTree = await document.GetSyntaxTreeAsync(); var currentRoot = await currentSyntaxTree.GetRootAsync(); //In VB you have to remove th parent of det declaration node. That is the "ClassBlockSyntax" var replacedRoot = currentRoot.RemoveNode(typeDecl.Parent, SyntaxRemoveOptions.KeepNoTrivia); document = document.WithSyntaxRoot(replacedRoot); // create new tree for a new file // we drag all the imports because we don't know which are needed // and there is no easy way to find out which var currentUsings = currentRoot.DescendantNodesAndSelf().Where(s => s is ImportsStatementSyntax); var currentNs = (NamespaceStatementSyntax)currentRoot.DescendantNodesAndSelf().First(s => s is NamespaceStatementSyntax); SyntaxList<StatementSyntax> c; if(currentNs != null) { //We have to wrap the content of the class in the namespace. var temp = SyntaxFactory.SingletonList( SyntaxFactory.NamespaceBlock( SyntaxFactory.NamespaceStatement(SyntaxFactory.ParseName(currentNs.Name.ToString())), SyntaxFactory.SingletonList(typeDecl.Parent), SyntaxFactory.EndNamespaceStatement() )); c = SyntaxFactory.List(temp.Select(i => ((StatementSyntax)i))); } else { c = SyntaxFactory.SingletonList(typeDecl.Parent); } var newFileTree = SyntaxFactory.CompilationUnit() .WithImports(SyntaxFactory.List(currentUsings.Select(i => ((ImportsStatementSyntax)i)))) .WithMembers(c) .WithoutLeadingTrivia() .NormalizeWhitespace(); var codeText = newFileTree.ToFullString(); //TODO: handle name conflicts var newDocument = document.Project.AddDocument(className, SourceText.From(codeText), document.Folders); newDocument = await RemoveUnusedImportDirectivesAsync(newDocument, cancellationToken); return newDocument.Project.Solution; }
/// <summary> /// The entry point to Gistify's engine. Takes the document and the extent of the selection, /// and outputs the augmented snippet. /// </summary> /// <param name="document"></param> /// <param name="startPosition"></param> /// <param name="endPosition"></param> /// <returns>String with the augmented snippet.</returns> public static string AugmentSelection(Document document, int startPosition, int endPosition) { var tree = document.GetSyntaxTreeAsync().Result; var model = document.GetSemanticModelAsync().Result; var objectInfos = DiscoveryWalker.FindObjects(tree, model, startPosition, endPosition); var augmentedSelection = SyntaxBuilder.AugmentSnippet(objectInfos, tree, startPosition, endPosition); return augmentedSelection; }
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); }
private async Task <InvocationContext> GetInvocation(Microsoft.CodeAnalysis.Document document, int offset) { var sourceText = await document.GetTextAsync(); var position = offset; var tree = await document.GetSyntaxTreeAsync(); var root = await tree.GetRootAsync(); var node = root.FindToken(position).Parent; // Walk up until we find a node that we're interested in. while (node != null) { if (node is InvocationExpressionSyntax invocation && invocation.ArgumentList != null && invocation.ArgumentList.Span.Contains(position)) { var semanticModel = await document.GetSemanticModelAsync(); return(new InvocationContext(semanticModel, position, invocation.Expression, invocation.ArgumentList, invocation.IsInStaticContext())); } if (node is ObjectCreationExpressionSyntax objectCreation && objectCreation.ArgumentList != null && objectCreation.ArgumentList.Span.Contains(position)) { var semanticModel = await document.GetSemanticModelAsync(); return(new InvocationContext(semanticModel, position, objectCreation, objectCreation.ArgumentList, objectCreation.IsInStaticContext())); } if (node is AttributeSyntax attributeSyntax && attributeSyntax.ArgumentList != null && attributeSyntax.ArgumentList.Span.Contains(position)) { var semanticModel = await document.GetSemanticModelAsync(); return(new InvocationContext(semanticModel, position, attributeSyntax, attributeSyntax.ArgumentList, attributeSyntax.IsInStaticContext())); } node = node.Parent; } return(null); }
/// <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); } }
protected override async Task <ISymbol> GetSymbol(Document document, int tokenPosition, CancellationToken cancellationToken) { try { SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken); if (semanticModel == null) { return(null); } var syntaxTree = await semanticModel.SyntaxTree.GetRootAsync(cancellationToken); var token = syntaxTree.FindToken(tokenPosition); if (Settings.Default?.AllowDisasmInvocations_V7 == true && token.Parent?.Parent?.Parent is InvocationExpressionSyntax i) { return(semanticModel.GetSymbolInfo(i, cancellationToken).Symbol); } if (token.Parent is LocalFunctionStatementSyntax lf) { return(semanticModel.GetDeclaredSymbol(lf, cancellationToken)); } if (token.Parent is MethodDeclarationSyntax m) { return(semanticModel.GetDeclaredSymbol(m, cancellationToken)); } if (token.Parent is ClassDeclarationSyntax c) { return(semanticModel.GetDeclaredSymbol(c, cancellationToken)); } if (token.Parent is StructDeclarationSyntax s) { return(semanticModel.GetDeclaredSymbol(s, cancellationToken)); } return(null); } catch { return(null); } }
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)); }
protected override async Task <bool> IsValidSymbol(Document document, int tokenPosition, CancellationToken cancellationToken) { SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken); if (semanticModel == null) { return(false); } var syntaxTree = await semanticModel.SyntaxTree.GetRootAsync(cancellationToken); var token = syntaxTree.FindToken(tokenPosition); if (Settings.Default?.AllowDisasmInvocations_V7 == true && token.Parent?.Parent?.Parent is InvocationExpressionSyntax) { return(true); } if (token.Parent is MethodDeclarationSyntax) { return(true); } if (token.Parent is ClassDeclarationSyntax) { return(true); } if (token.Parent is StructDeclarationSyntax) { return(true); } if (token.Parent is LocalFunctionStatementSyntax) { return(true); } return(false); }
/// <summary> /// Get the existing compiler diagnostics on the inputted document. /// </summary> /// <param name="document">The Document to run the compiler diagnostic analyzers on</param> /// <returns>The compiler diagnostics that were found in the code</returns> private static IEnumerable <Diagnostic> GetCompilerDiagnostics(Document document) { return(document.GetSemanticModelAsync().Result.GetDiagnostics()); }
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); } }