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;
 }
示例#4
0
    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;
        }
示例#11
0
        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);
        }
示例#13
0
        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;
            }

        }
示例#14
0
        /// <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;
        }
示例#17
0
        /// <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;
		}
示例#21
0
        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);
		}
示例#23
0
        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));
        }
示例#25
0
        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;

        }
示例#33
0
 /// <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;
 }
示例#34
0
        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);
        }
示例#36
0
        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);
        }
示例#39
0
        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);
            }
        }
示例#40
0
        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);
            }
        }
示例#41
0
        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));
        }
示例#42
0
        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);
        }
示例#43
0
 /// <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());
 }
示例#44
0
        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);
            }
        }
示例#45
0
        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);
        }
示例#46
0
        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);
                }
            }
        }
示例#47
0
        /// <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);
            }
        }
示例#48
0
        /// <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);
            }
        }