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); } } } }
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)); }
/////////////////////////////////////////////////////////////////////////////////// // // 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; } }
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); } }