private void ClearErrors()
 {
     previousSquiggles.ForEach(tag => squiggleTagger.RemoveTagSpans(t => tag.Span == t.Span));
     previousSquiggles.Clear();
     previousErrors.ForEach(task => errorList.Tasks.Remove(task));
     previousErrors.Clear();
 }
        private void ParseSnapshot(ISnapshotTextContentProvider snapshotContent)
        {
            // queue analysis of the parsed tree at High Pri so the active buffer is quickly re-analyzed
            var snapshot = snapshotContent.Snapshot;

            if (snapshot.TextBuffer.ContentType.IsOfType(PythonCoreConstants.ContentType))
            {
                PythonAst           ast;
                CollectingErrorSink errorSink;
                ParsePythonCode((TextContentProvider)snapshotContent, out ast, out errorSink);
                if (ast != null)
                {
                    IPythonProjectEntry analysis;
                    if (snapshot.TextBuffer.TryGetPythonAnalysis(out analysis))
                    {
                        // only update the AST when we're error free, this way we don't remove
                        // a useful analysis with an incomplete and useless analysis.
                        if (errorSink.Errors.Count == 0)
                        {
                            analysis.UpdateTree(ast, new SnapshotCookie(snapshot));
                            _analysisQueue.Enqueue(analysis, AnalysisPriority.High);
                        }

                        SimpleTagger <ErrorTag> squiggles = _squiggleProvider.GetErrorTagger(snapshot.TextBuffer);
                        squiggles.RemoveTagSpans(x => true);

                        // update squiggles for the live buffer
                        foreach (ErrorResult warning in errorSink.Warnings)
                        {
                            var span  = warning.Span;
                            var tspan = CreateSpan(snapshot, span);
                            squiggles.CreateTagSpan(tspan, new ErrorTag("Warning", warning.Message));
                        }

                        foreach (ErrorResult error in errorSink.Errors)
                        {
                            var span  = error.Span;
                            var tspan = CreateSpan(snapshot, span);
                            squiggles.CreateTagSpan(tspan, new ErrorTag("Error", error.Message));
                        }
                    }
                }
            }
            else if (snapshot.TextBuffer.ContentType.IsOfType("xaml"))
            {
                string path = snapshot.TextBuffer.GetFilePath();
                if (path != null)
                {
                    IProjectEntry    analysis;
                    XamlProjectEntry xamlProject;
                    if (_projectFiles.TryGetValue(path, out analysis) &&
                        (xamlProject = analysis as XamlProjectEntry) != null)
                    {
                        xamlProject.UpdateContent(((TextContentProvider)snapshotContent).GetReader(), new SnapshotCookie(snapshotContent.Snapshot));
                        _analysisQueue.Enqueue(analysis, AnalysisPriority.High);
                    }
                }
            }
        }
Esempio n. 3
0
        public void Parse(TextContentProvider /*!*/ content)
        {
            var            errorSink = new CollectingErrorSink();
            SourceUnitTree ast       = MakeParseTree(content, errorSink);

            ISnapshotTextContentProvider snapshotContent = content as ISnapshotTextContentProvider;

            if (snapshotContent != null)
            {
                // queue analysis of the parsed tree at High Pri so the active buffer is quickly re-analyzed
                var snapshot = snapshotContent.Snapshot;

                var analysis = AnalysisItem.GetAnalysis(snapshot.TextBuffer);

                // only update the AST when we're error free, this way we don't remove
                // a useful analysis with an incomplete and useless analysis.
                if (errorSink.Errors.Count == 0)
                {
                    analysis.UpdateTree(ast, new SnapshotCookie(snapshot));
                    _analysisQueue.Enqueue(analysis, AnalysisPriority.High);
                }

                SimpleTagger <ErrorTag> squiggles = _squiggleProvider.GetErrorTagger(snapshot.TextBuffer);
                squiggles.RemoveTagSpans(x => true);

                // update squiggles for the live buffer
                foreach (ErrorResult warning in errorSink.Warnings)
                {
                    var span  = warning.Span;
                    var tspan = CreateSpan(snapshot, span);
                    squiggles.CreateTagSpan(tspan, new ErrorTag("Warning", warning.Message));
                }

                foreach (ErrorResult error in errorSink.Errors)
                {
                    var span  = error.Span;
                    var tspan = CreateSpan(snapshot, span);
                    squiggles.CreateTagSpan(tspan, new ErrorTag("Error", error.Message));
                }
            }
            else
            {
                FileTextContentProvider fileContent = content as FileTextContentProvider;
                AnalysisItem            analysis;
                if (fileContent != null && _projectFiles.TryGetValue(fileContent.Path, out analysis))
                {
                    analysis.UpdateTree(ast, new FileCookie(fileContent.Path));
                    _analysisQueue.Enqueue(analysis, AnalysisPriority.Normal);
                }
            }
        }
 public Int32 RemoveTagSpans(Predicate <TrackingTagSpan <T> > match)
 {
     return(m_storage.RemoveTagSpans(match));
 }
Esempio n. 5
0
        ///////////////////////////////////////////////////////////////////////////////////
        //
        // Validate the mardown directive syntax according to the ruleset definitions
        //
        // Copyright (c) 2014 Microsoft Corporation.
        // Author: Junyi Yi ([email protected]) - Initial version
        //
        ///////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Validate the whole document according to the specified ruleset.
        /// </summary>
        /// <param name="snapshot">The whole document snapshot.</param>
        /// <param name="errorTagger">The tagger used to generate error squiggles.</param>
        /// <param name="ruleset">The specified ruleset.</param>
        public static void ValidateDirectiveSyntax(ITextSnapshot snapshot, DirectiveRuleset ruleset, SimpleTagger<ErrorTag> errorTagger)
        {
            // Remove all current error squiggles
            errorTagger.RemoveTagSpans(errorTagSpan => true);

            // Get the full document text and clear all HTML tags
            string text = snapshot.GetText();
            text = MarkdownParser.DestroyHtmlTags(text);

            // Three cases:
            // 0123456789              01234567 8              01234567  8
            // [  WA ab ]              [  WA ab \n             [  WA ab EOT
            // |        |-endIndex=9   |        |-endIndex=8   |         |-endIndex=8
            // |-startIndex=0          |-startIndex=0          |-startIndex=0

            // Greedily search for the pair of '[...]' (supports nested pair '[... [...] ...]')
            // Here 'Greedily' means if we have a string '[...[...]', it would also treat the latter '[...]' as the pair
            for (int startIndex = text.IndexOf('['); startIndex >= 0; startIndex = text.IndexOf('[', startIndex))
            {
                int endIndex = MarkdownParser.FindCorrespondingEndBracket(text, startIndex + 1);

                // Get the directive content string
                ITrackingSpan overallDirective = snapshot.CreateTrackingSpan(startIndex + 1, endIndex - startIndex - 1, SpanTrackingMode.EdgeInclusive);
                string directive = overallDirective.GetText(snapshot);
                var directiveMatches = Regex.Matches(directive, string.Concat(@"^\s*(", ValidationUtilities.DirectiveNameRegularPattern, @")(.*)$"));
                if (directiveMatches.Count != 1 || !directiveMatches[0].Success || directiveMatches[0].Groups.Count != 3 || directiveMatches[0].Value != directive)
                {
                    startIndex++;
                    continue;
                }
                string directiveName = directiveMatches[0].Groups[1].Value;
                string directiveContent = directiveMatches[0].Groups[2].Value;

                var rule = ruleset.TryGetDirectiveRule(directiveName);
                if (rule != null)
                {
                    // Get the preceding and following directive string of the same line
                    ITextSnapshotLine line = snapshot.GetLineFromPosition(startIndex);
                    string precedingText = snapshot.GetText(line.Start, startIndex - line.Start);
                    string followingText = endIndex < line.End ? snapshot.GetText(endIndex + 1, line.End - endIndex - 1) : string.Empty;

                    // If we found a exactly-matched rule, just validate it
                    string message = rule.Validate(directiveContent, precedingText, followingText);
                    if (message != null)
                    {
                        ITrackingSpan squiggleSpan = overallDirective;
                        if (rule.SquiggleWholeLine)
                        {
                            squiggleSpan = snapshot.CreateTrackingSpan(line.Start, line.Length, SpanTrackingMode.EdgeInclusive);
                        }
                        errorTagger.CreateTagSpan(squiggleSpan, new ErrorTag(PredefinedErrorTypeNames.SyntaxError, message));
                    }

                    // If we miss the closing bracket, give out the prompt message
                    if (endIndex >= text.Length || text[endIndex] != ']')
                    {
                        errorTagger.CreateTagSpan(snapshot.CreateTrackingSpan(line.End, 0, SpanTrackingMode.EdgePositive), new ErrorTag(PredefinedErrorTypeNames.CompilerError, "Missing the closing bracket"));
                    }
                }
                else
                {
                    // Otherwise we may take a look at the suspects
                    var suspects = ruleset.GetSuspects(directive);
                    if (suspects.Count() > 0)
                    {
                        StringBuilder suspectPrompt = new StringBuilder();
                        suspectPrompt.AppendLine("Are you trying to enter one of the following directives?");
                        foreach (var suspect in suspects)
                        {
                            suspectPrompt.AppendLine(string.Format("    \u2022 {0} - {1}", suspect.ParentRule.DirectiveName, suspect.SuggestionMessage));
                        }
                        errorTagger.CreateTagSpan(overallDirective, new ErrorTag(PredefinedErrorTypeNames.Warning, suspectPrompt.ToString().TrimEnd()));
                    }
                }

                startIndex = endIndex;
            }
        }
Esempio n. 6
0
        public void ParseBuffers(BufferParser bufferParser, Severity indentationSeverity, params ITextSnapshot[] snapshots)
        {
            IProjectEntry analysis;

            lock (_openFiles) {
                if (!_openFiles.TryGetValue(bufferParser, out analysis))
                {
                    return;
                }
            }

            IPythonProjectEntry pyProjEntry = analysis as IPythonProjectEntry;
            List <PythonAst>    asts        = new List <PythonAst>();
            bool hasErrors = false;

            foreach (var snapshot in snapshots)
            {
                var snapshotContent = new SnapshotSpanSourceCodeReader(new SnapshotSpan(snapshot, new Span(0, snapshot.Length)));

                if (pyProjEntry != null && snapshot.TextBuffer.ContentType.IsOfType(PythonCoreConstants.ContentType))
                {
                    if (!snapshot.IsReplBufferWithCommand())
                    {
                        PythonAst           ast;
                        CollectingErrorSink errorSink;

                        ParsePythonCode(snapshotContent, indentationSeverity, out ast, out errorSink);
                        if (ast != null)
                        {
                            asts.Add(ast);

                            if (errorSink.Errors.Count != 0)
                            {
                                hasErrors = true;
                            }

                            // update squiggles for the buffer
                            var buffer = snapshot.TextBuffer;
                            SimpleTagger <ErrorTag> squiggles = _errorProvider.GetErrorTagger(snapshot.TextBuffer);
                            squiggles.RemoveTagSpans(x => true);

                            TaskProvider provider = GetTaskListProviderForProject(bufferParser._currentProjEntry);

                            AddWarnings(snapshot, errorSink, squiggles, provider);

                            AddErrors(snapshot, errorSink, squiggles, provider);

                            UpdateErrorList(errorSink, buffer.GetFilePath(), provider);
                        }
                    }
                }
                else
                {
                    // other file such as XAML
                    IExternalProjectEntry externalEntry;
                    if ((externalEntry = (analysis as IExternalProjectEntry)) != null)
                    {
                        externalEntry.ParseContent(snapshotContent, new SnapshotCookie(snapshotContent.Snapshot));
                        _analysisQueue.Enqueue(analysis, AnalysisPriority.High);
                    }
                }
            }

            if ((!hasErrors && asts.Count > 0) || asts.Count > 1)
            {
                // only update the AST when we're error free, this way we don't remove
                // a useful analysis with an incomplete and useless analysis.
                // If we have more than one AST we're in the REPL - we'll update the
                // AST in that case as errors won't go away.

                PythonAst finalAst;
                if (asts.Count == 1)
                {
                    finalAst = asts[0];
                }
                else
                {
                    // multiple ASTs, merge them together
                    List <Statement> bodies = new List <Statement>();
                    foreach (var ast in asts)
                    {
                        bodies.Add(ast.Body);
                    }
                    finalAst = new PythonAst(new SuiteStatement(bodies.ToArray()), new int[0]);
                }

                pyProjEntry.UpdateTree(finalAst, new SnapshotCookie(snapshots[0])); // SnapshotCookie is ot entirely right, we should merge the snapshots
                _analysisQueue.Enqueue(analysis, AnalysisPriority.High);
            }
        }