コード例 #1
0
        public static ReachabilityAnalysis Create(Statement statement, AlAstResolver resolver = null, RecursiveDetectorVisitor recursiveDetectorVisitor = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            var cfgBuilder = new ControlFlowGraphBuilder();
            var cfg        = cfgBuilder.BuildControlFlowGraph(statement, resolver, cancellationToken);

            return(Create(cfg, recursiveDetectorVisitor, cancellationToken));
        }
コード例 #2
0
            public Task <IContextAction[]> GetAvailableActionsAsync(EditorRefactoringContext context, CancellationToken cancellationToken)
            {
                ITextEditor editor = context.Editor;
                // grab SelectionStart/SelectionLength while we're still on the main thread
                int selectionStart  = editor.SelectionStart;
                int selectionLength = editor.SelectionLength;

                return(Task.Run(
                           async delegate {
                    try {
                        if (!CreateCodeActionProvider())
                        {
                            return new IContextAction[0];
                        }
                        AlAstResolver resolver = await context.GetAstResolverAsync().ConfigureAwait(false);
                        var refactoringContext = new SDRefactoringContext(context.TextSource, resolver, context.CaretLocation, selectionStart, selectionLength, cancellationToken);
                        return codeActionProvider.GetActions(refactoringContext).Select(Wrap).ToArray();
                    } catch (OperationCanceledException) {
                        throw;                                 // don't catch cancellations
                    } catch (Exception ex) {
                        SD.Log.WarnFormatted("AlContextActionProviderWrapper crashed: {0}", ex);
                        SD.AnalyticsMonitor.TrackException(ex);
                        return new IContextAction[0];
                    }
                }, cancellationToken));
            }
        public DefiniteAssignmentAnalysis(Statement rootStatement, AlAstResolver resolver, CancellationToken cancellationToken)
        {
            if (rootStatement == null)
            {
                throw new ArgumentNullException("rootStatement");
            }
            if (resolver == null)
            {
                throw new ArgumentNullException("resolver");
            }
            this.resolver = resolver;

            visitor.analysis = this;
            DerivedControlFlowGraphBuilder cfgBuilder = new DerivedControlFlowGraphBuilder();

            if (resolver.TypeResolveContext.Compilation.MainAssembly.UnresolvedAssembly is MinimalCorlib)
            {
                cfgBuilder.EvaluateOnlyPrimitiveConstants = true;
            }
            allNodes.AddRange(cfgBuilder.BuildControlFlowGraph(rootStatement, resolver, cancellationToken).Cast <DefiniteAssignmentNode>());
            for (int i = 0; i < allNodes.Count; i++)
            {
                DefiniteAssignmentNode node = allNodes[i];
                node.Index = i;                 // assign numbers to the nodes
                if (node.Type == ControlFlowNodeType.StartNode || node.Type == ControlFlowNodeType.BetweenStatements)
                {
                    // Anonymous methods have separate control flow graphs, but we also need to analyze those.
                    // Iterate backwards so that anonymous methods are inserted in the correct order
                    for (AstNode child = node.NextStatement.LastChild; child != null; child = child.PrevSibling)
                    {
                        InsertAnonymousMethods(i + 1, child, cfgBuilder, cancellationToken);
                    }
                }
                // Now register the node in the dictionaries:
                if (node.Type == ControlFlowNodeType.StartNode || node.Type == ControlFlowNodeType.BetweenStatements)
                {
                    beginNodeDict.Add(node.NextStatement, node);
                }
                if (node.Type == ControlFlowNodeType.BetweenStatements || node.Type == ControlFlowNodeType.EndNode)
                {
                    endNodeDict.Add(node.PreviousStatement, node);
                }
                if (node.Type == ControlFlowNodeType.LoopCondition)
                {
                    conditionNodeDict.Add(node.NextStatement, node);
                }
            }
            // Verify that we created nodes for all statements:
            Debug.Assert(!rootStatement.DescendantsAndSelf.OfType <Statement>().Except(allNodes.Select(n => n.NextStatement)).Any());
            // Verify that we put all nodes into the dictionaries:
            Debug.Assert(rootStatement.DescendantsAndSelf.OfType <Statement>().All(stmt => beginNodeDict.ContainsKey(stmt)));
            Debug.Assert(rootStatement.DescendantsAndSelf.OfType <Statement>().All(stmt => endNodeDict.ContainsKey(stmt)));

            this.analyzedRangeStart = 0;
            this.analyzedRangeEnd   = allNodes.Count - 1;
        }
        public static bool TypeChangeResolvesCorrectly(BaseRefactoringContext ctx, ParameterDeclaration parameter, AstNode rootNode, IType type)
        {
            var resolver = ctx.GetResolverStateBefore(rootNode);

            resolver = resolver.AddVariable(new DefaultParameter(type, parameter.Name));
            var astResolver = new AlAstResolver(resolver, rootNode, ctx.UnresolvedFile);
            var validator   = new TypeChangeValidationNavigator();

            astResolver.ApplyNavigator(validator, ctx.CancellationToken);
            return(!validator.FoundErrors);
        }
コード例 #5
0
 public IList <ControlFlowNode> BuildControlFlowGraph(Statement statement, AlAstResolver resolver, CancellationToken cancellationToken = default(CancellationToken))
 {
     if (statement == null)
     {
         throw new ArgumentNullException("statement");
     }
     if (resolver == null)
     {
         throw new ArgumentNullException("resolver");
     }
     return(BuildControlFlowGraph(statement, resolver.Resolve, resolver.TypeResolveContext, cancellationToken));
 }
コード例 #6
0
 public SDRefactoringContext(ITextSource textSource, AlAstResolver resolver, TextLocation location, int selectionStart, int selectionLength, CancellationToken cancellationToken)
     : base(resolver, cancellationToken)
 {
     this.resolver        = resolver;
     this.textSource      = textSource;
     this.document        = textSource as IDocument;
     this.selectionStart  = selectionStart;
     this.selectionLength = selectionLength;
     this.location        = location;
     this.editorOptions   = SD.EditorControlService.GlobalOptions.ToEditorOptions();
     InitializeServices();
 }
コード例 #7
0
 public SDRefactoringContext(ITextEditor editor, AlAstResolver resolver, TextLocation location, CancellationToken cancellationToken = default(CancellationToken))
     : base(resolver, cancellationToken)
 {
     this.resolver        = resolver;
     this.editor          = editor;
     this.textSource      = editor.Document;
     this.document        = editor.Document;
     this.selectionStart  = editor.SelectionStart;
     this.selectionLength = editor.SelectionLength;
     this.location        = location;
     this.editorOptions   = editor.ToEditorOptions();
     InitializeServices();
 }
コード例 #8
0
 void VisitVisibleNodes(AstNode node, IResolveVisitorNavigator currentNavigator, AlAstResolver resolver, int start, int end)
 {
     if (!AlAstResolver.IsUnresolvableNode(node))
     {
         currentNavigator.Resolved(node, resolver.Resolve(node));
     }
     for (var child = node.FirstChild; child != null; child = child.NextSibling)
     {
         if (child.StartLocation.Line <= end && child.EndLocation.Line >= start)
         {
             VisitVisibleNodes(child, currentNavigator, resolver, start, end);
         }
     }
 }
コード例 #9
0
        public AlAstResolver GetResolver(ICompilation compilation)
        {
            // Cache the resolver within the compilation.
            // (caching in the parse information could prevent the compilation from being garbage-collected)

            // Also, don't cache AlAstResolvers for every file - doing so would require too much memory,
            // and we usually only need to access the same file several times.
            // So we use a static key to get the resolver, and verify that it belongs to this parse information.
            var resolver = compilation.CacheManager.GetShared(ResolverCacheKey) as AlAstResolver;

            if (resolver == null || resolver.RootNode != syntaxTree || resolver.UnresolvedFile != UnresolvedFile)
            {
                resolver = new AlAstResolver(compilation, syntaxTree, UnresolvedFile);
                compilation.CacheManager.SetShared(ResolverCacheKey, resolver);
            }
            return(resolver);
        }
コード例 #10
0
		public ICodeContext ResolveContext(ParseInformation parseInfo, TextLocation location, ICompilation compilation, CancellationToken cancellationToken)
		{
			var csParseInfo = parseInfo as AlFullParseInformation;
			if (csParseInfo == null)
				throw new ArgumentException("Parse info does not have SyntaxTree");
			
			AlUnresolvedFile unresolvedFile = csParseInfo.UnresolvedFile;
			var projectContents = compilation.Assemblies.Select(asm => asm.UnresolvedAssembly).OfType<IProjectContent>().ToList();
			if (projectContents.All(pc => pc.GetFile(unresolvedFile.FileName) != unresolvedFile))
				unresolvedFile = null;
			var syntaxTree = csParseInfo.SyntaxTree;
			var node = syntaxTree.GetNodeAt(location);
			if (node == null)
				return null; // null result is allowed; the parser service will substitute a dummy context
			var resolver = new AlAstResolver(compilation, syntaxTree, unresolvedFile);
			return resolver.GetResolverStateBefore(node);
		}
コード例 #11
0
        public static SDRefactoringContext Create(FileName fileName, ITextSource textSource, TextLocation location = default(TextLocation), CancellationToken cancellationToken = default(CancellationToken))
        {
            var           parseInfo   = SD.ParserService.Parse(fileName, textSource, cancellationToken: cancellationToken) as AlFullParseInformation;
            var           compilation = SD.ParserService.GetCompilationForFile(fileName);
            AlAstResolver resolver;

            if (parseInfo != null)
            {
                resolver = parseInfo.GetResolver(compilation);
            }
            else
            {
                // create dummy refactoring context
                resolver = new AlAstResolver(compilation, new SyntaxTree());
            }
            var context = new SDRefactoringContext(textSource, resolver, location, 0, 0, cancellationToken);

            return(context);
        }
コード例 #12
0
        public static SDRefactoringContext Create(ITextEditor editor, CancellationToken cancellationToken)
        {
            var           parseInfo   = SD.ParserService.Parse(editor.FileName, editor.Document, cancellationToken: cancellationToken) as AlFullParseInformation;
            var           compilation = SD.ParserService.GetCompilationForFile(editor.FileName);
            AlAstResolver resolver;

            if (parseInfo != null)
            {
                resolver = parseInfo.GetResolver(compilation);
            }
            else
            {
                // create dummy refactoring context
                resolver = new AlAstResolver(compilation, new SyntaxTree());
            }
            var context = new SDRefactoringContext(editor, resolver, editor.Caret.Location, cancellationToken);

            return(context);
        }
コード例 #13
0
		public ResolveResult ResolveSnippet(ParseInformation parseInfo, TextLocation location, string codeSnippet, ICompilation compilation, CancellationToken cancellationToken)
		{
			var csParseInfo = parseInfo as AlFullParseInformation;
			if (csParseInfo == null)
				throw new ArgumentException("Parse info does not have SyntaxTree");
			AlAstResolver contextResolver = new AlAstResolver(compilation, csParseInfo.SyntaxTree, csParseInfo.UnresolvedFile);
			var node = csParseInfo.SyntaxTree.GetNodeAt(location);
			AlResolver context;
			if (node != null)
				context = contextResolver.GetResolverStateAfter(node, cancellationToken);
			else
				context = new AlResolver(compilation);
			AlParser parser = new AlParser();
			var expr = parser.ParseExpression(codeSnippet);
			if (parser.HasErrors)
				return new ErrorResolveResult(SpecialType.UnknownType, PrintErrorsAsString(parser.Errors), TextLocation.Empty);
			AlAstResolver snippetResolver = new AlAstResolver(context, expr);
			return snippetResolver.Resolve(expr, cancellationToken);
		}
コード例 #14
0
        void FindCurrentReferences(int start, int end)
        {
            ICompilation           compilation = SD.ParserService.GetCompilationForFile(editor.FileName);
            AlFullParseInformation parseInfo   = SD.ParserService.GetCachedParseInformation(editor.FileName) as AlFullParseInformation;

            if (currentSymbolReference == null || parseInfo == null)
            {
                return;
            }

            IResolveVisitorNavigator currentNavigator = InitNavigator(compilation);
            AlAstResolver            resolver         = parseInfo.GetResolver(compilation);

            if (currentNavigator == null || resolver == null)
            {
                return;
            }

            VisitVisibleNodes(parseInfo.SyntaxTree, currentNavigator, resolver, start, end);
        }
コード例 #15
0
 public ExpressionResolveResult(ResolveResult item1, AlResolver item2, AlAstResolver item3)
 {
     this.Result      = item1;
     this.Resolver    = item2;
     this.AstResolver = item3;
 }
コード例 #16
0
        void RenameReferencesInFile(SymbolRenameArgs args, IList <IFindReferenceSearchScope> searchScopeList, FileName fileName, Action <PatchedFile> callback, Action <Error> errorCallback, bool isNameValid, CancellationToken cancellationToken)
        {
            ITextSource textSource = args.ParseableFileContentFinder.Create(fileName);

            if (textSource == null)
            {
                return;
            }
            if (searchScopeList != null)
            {
                if (!searchScopeList.DistinctBy(scope => scope.SearchTerm ?? String.Empty).Any(
                        scope => (scope.SearchTerm == null) || (textSource.IndexOf(scope.SearchTerm, 0, textSource.TextLength, StringComparison.Ordinal) >= 0)))
                {
                    return;
                }
            }

            var parseInfo = SD.ParserService.Parse(fileName, textSource) as AlFullParseInformation;

            if (parseInfo == null)
            {
                return;
            }
            ReadOnlyDocument         document    = null;
            IHighlighter             highlighter = null;
            List <RenameResultMatch> results     = new List <RenameResultMatch>();

            // Grab the unresolved file matching the compilation version
            // (this may differ from the version created by re-parsing the project)
            AlUnresolvedFile unresolvedFile = null;
            IProjectContent  pc             = compilation.MainAssembly.UnresolvedAssembly as IProjectContent;

            if (pc != null)
            {
                unresolvedFile = pc.GetFile(fileName) as AlUnresolvedFile;
            }

            AlAstResolver resolver = new AlAstResolver(compilation, parseInfo.SyntaxTree, unresolvedFile);

            fr.RenameReferencesInFile(
                searchScopeList, args.NewName, resolver,
                delegate(RenameCallbackArguments callbackArgs) {
                var node       = callbackArgs.NodeToReplace;
                string newCode = callbackArgs.NewNode.ToString();
                if (document == null)
                {
                    document = new ReadOnlyDocument(textSource, fileName);

                    if (args.ProvideHighlightedLine)
                    {
                        highlighter = SD.EditorControlService.CreateHighlighter(document);
                        highlighter.BeginHighlighting();
                    }
                }
                var startLocation = node.StartLocation;
                var endLocation   = node.EndLocation;
                int offset        = document.GetOffset(startLocation);
                int length        = document.GetOffset(endLocation) - offset;
                if (args.ProvideHighlightedLine)
                {
                    var builder          = SearchResultsPad.CreateInlineBuilder(node.StartLocation, node.EndLocation, document, highlighter);
                    var defaultTextColor = highlighter != null ? highlighter.DefaultTextColor : null;
                    results.Add(new RenameResultMatch(fileName, startLocation, endLocation, offset, length, newCode, builder, defaultTextColor));
                }
                else
                {
                    results.Add(new RenameResultMatch(fileName, startLocation, endLocation, offset, length, newCode));
                }
            },
                errorCallback, cancellationToken);
            if (highlighter != null)
            {
                highlighter.Dispose();
            }
            if (results.Count > 0)
            {
                if (!isNameValid)
                {
                    errorCallback(new Error(ErrorType.Error, string.Format("The name '{0}' is not valid in the current context!", args.NewName),
                                            new DomRegion(fileName, results[0].StartLocation)));
                    return;
                }
                IDocument changedDocument             = new TextDocument(document);
                var       oldVersion                  = changedDocument.Version;
                List <SearchResultMatch> fixedResults = new List <SearchResultMatch>();
                int lastStartOffset = changedDocument.TextLength + 1;
                foreach (var result in results.OrderByDescending(m => m.StartOffset))
                {
                    if (result.EndOffset <= lastStartOffset)
                    {
                        changedDocument.Replace(result.StartOffset, result.Length, result.NewCode);
                        fixedResults.Add(result);
                        lastStartOffset = result.StartOffset;
                    }
                }
                callback(new PatchedFile(fileName, fixedResults, oldVersion, changedDocument.Version));
            }
        }