diff options
-rw-r--r-- | main/src/addins/VBNetBinding/Project/VBNetParsedDocument.cs | 665 |
1 files changed, 333 insertions, 332 deletions
diff --git a/main/src/addins/VBNetBinding/Project/VBNetParsedDocument.cs b/main/src/addins/VBNetBinding/Project/VBNetParsedDocument.cs index 73cbaca827..921754b73f 100644 --- a/main/src/addins/VBNetBinding/Project/VBNetParsedDocument.cs +++ b/main/src/addins/VBNetBinding/Project/VBNetParsedDocument.cs @@ -1,181 +1,181 @@ -// -// CSharpParsedDocument.cs -// -// Author: -// Mike Krüger <mkrueger@xamarin.com> -// -// Copyright (c) 2015 Xamarin Inc. (http://xamarin.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using MonoDevelop.Ide.TypeSystem; -using Microsoft.CodeAnalysis; -using System.Collections.Generic; -using System.Linq; -using MonoDevelop.Ide.Editor; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using MonoDevelop.Core; -using MonoDevelop.Core.Text; -using MonoDevelop.Ide; - -namespace MonoDevelop.VBNetBinding -{ - class VBNetParsedDocument : ParsedDocument - { - static string[] tagComments; - - internal DocumentId DocumentId { - get; - set; - } - internal SyntaxTree ParsedUnit { - get; - set; - } - - static VBNetParsedDocument () - { - UpdateTags (); - MonoDevelop.Ide.Tasks.CommentTag.SpecialCommentTagsChanged += delegate { - UpdateTags (); - }; - } - - static void UpdateTags () - { - tagComments = MonoDevelop.Ide.Tasks.CommentTag.SpecialCommentTags.Select (t => t.Tag).ToArray (); - } - bool isAdHocProject; - - public VBNetParsedDocument (Ide.TypeSystem.ParseOptions options, string fileName) : base (fileName) - { - isAdHocProject = options.IsAdhocProject; - Flags |= ParsedDocumentFlags.SkipFoldings; - } - - #region implemented abstract members of ParsedDocument - - IReadOnlyList<Comment> comments; - SemaphoreSlim commentLock = new SemaphoreSlim (1, 1); - - public override Task<IReadOnlyList<Comment>> GetCommentsAsync (CancellationToken cancellationToken = default(CancellationToken)) - { - if (comments == null) { - return Task.Run (async delegate { - bool locked = await commentLock.WaitAsync (Timeout.Infinite, cancellationToken).ConfigureAwait (false); - await commentLock.WaitAsync (); - try { - if (comments == null) { - var visitor = new CommentVisitor (cancellationToken); - var unit = await GetParsedSyntaxTreeAsync (cancellationToken); - if (unit != null) { - try { +//
+// CSharpParsedDocument.cs
+//
+// Author:
+// Mike Krüger <mkrueger@xamarin.com>
+//
+// Copyright (c) 2015 Xamarin Inc. (http://xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using MonoDevelop.Ide.TypeSystem;
+using Microsoft.CodeAnalysis;
+using System.Collections.Generic;
+using System.Linq;
+using MonoDevelop.Ide.Editor;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis.VisualBasic;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using MonoDevelop.Core;
+using MonoDevelop.Core.Text;
+using MonoDevelop.Ide;
+
+namespace MonoDevelop.VBNetBinding
+{
+ class VBNetParsedDocument : ParsedDocument
+ {
+ static string[] tagComments;
+
+ internal DocumentId DocumentId {
+ get;
+ set;
+ }
+ internal SyntaxTree ParsedUnit {
+ get;
+ set;
+ }
+
+ static VBNetParsedDocument ()
+ {
+ UpdateTags ();
+ MonoDevelop.Ide.Tasks.CommentTag.SpecialCommentTagsChanged += delegate {
+ UpdateTags ();
+ };
+ }
+
+ static void UpdateTags ()
+ {
+ tagComments = MonoDevelop.Ide.Tasks.CommentTag.SpecialCommentTags.Select (t => t.Tag).ToArray ();
+ }
+ bool isAdHocProject;
+
+ public VBNetParsedDocument (Ide.TypeSystem.ParseOptions options, string fileName) : base (fileName)
+ {
+ isAdHocProject = options.IsAdhocProject;
+ Flags |= ParsedDocumentFlags.SkipFoldings;
+ }
+
+ #region implemented abstract members of ParsedDocument
+
+ IReadOnlyList<Comment> comments;
+ SemaphoreSlim commentLock = new SemaphoreSlim (1, 1);
+
+ public override Task<IReadOnlyList<Comment>> GetCommentsAsync (CancellationToken cancellationToken = default(CancellationToken))
+ {
+ if (comments == null) {
+ return Task.Run (async delegate {
+ bool locked = await commentLock.WaitAsync (Timeout.Infinite, cancellationToken).ConfigureAwait (false);
+ await commentLock.WaitAsync ();
+ try {
+ if (comments == null) {
+ var visitor = new CommentVisitor (cancellationToken);
+ var unit = await GetParsedSyntaxTreeAsync (cancellationToken);
+ if (unit != null) {
+ try {
var syntaxRoot = await unit.GetRootAsync (cancellationToken);
visitor.Visit (syntaxRoot);
} catch (OperationCanceledException) {
- } - } - comments = visitor.Comments; - } - } finally { - if (locked) - commentLock.Release (); - } - return comments; - }); - } - return Task.FromResult (comments); - - async Task<SyntaxTree> GetParsedSyntaxTreeAsync (CancellationToken token) - { - if (ParsedUnit == null && DocumentId != null) { - var document = IdeServices.TypeSystemService.GetCodeAnalysisDocument (DocumentId, token); - ParsedUnit = await document.GetSyntaxTreeAsync (token); - } - return ParsedUnit; - } - } - - - class CommentVisitor : CSharpSyntaxWalker - { - public readonly List<Comment> Comments = new List<Comment> (); - - CancellationToken cancellationToken; - - public CommentVisitor (CancellationToken cancellationToken) : base(SyntaxWalkerDepth.Trivia) - { - this.cancellationToken = cancellationToken; - } - - DocumentRegion GetRegion (SyntaxTrivia trivia) - { - var fullSpan = trivia.FullSpan; + }
+ }
+ comments = visitor.Comments;
+ }
+ } finally {
+ if (locked)
+ commentLock.Release ();
+ }
+ return comments;
+ });
+ }
+ return Task.FromResult (comments);
+
+ async Task<SyntaxTree> GetParsedSyntaxTreeAsync (CancellationToken token)
+ {
+ if (ParsedUnit == null && DocumentId != null) {
+ var document = IdeServices.TypeSystemService.GetCodeAnalysisDocument (DocumentId, token);
+ ParsedUnit = await document.GetSyntaxTreeAsync (token);
+ }
+ return ParsedUnit;
+ }
+ }
+
+
+ class CommentVisitor : CSharpSyntaxWalker
+ {
+ public readonly List<Comment> Comments = new List<Comment> ();
+
+ CancellationToken cancellationToken;
+
+ public CommentVisitor (CancellationToken cancellationToken) : base(SyntaxWalkerDepth.Trivia)
+ {
+ this.cancellationToken = cancellationToken;
+ }
+
+ DocumentRegion GetRegion (SyntaxTrivia trivia)
+ {
+ var fullSpan = trivia.FullSpan;
if (fullSpan.Length > 2) {
- var text = trivia.SyntaxTree.GetText (cancellationToken); - if (text [fullSpan.End - 2] == '\r' && text [fullSpan.End - 1] == '\n') - fullSpan = new Microsoft.CodeAnalysis.Text.TextSpan (fullSpan.Start, fullSpan.Length - 2); - else if (NewLine.IsNewLine (text [fullSpan.End - 1])) - fullSpan = new Microsoft.CodeAnalysis.Text.TextSpan (fullSpan.Start, fullSpan.Length - 1); - } - try { - var lineSpan = trivia.SyntaxTree.GetLineSpan (fullSpan); - return (DocumentRegion)lineSpan; - } catch (Exception) { - return DocumentRegion.Empty; - } - } - - public override void VisitBlock (BlockSyntax node) - { - cancellationToken.ThrowIfCancellationRequested (); - base.VisitBlock (node); - } - - bool StartsLine (SyntaxTrivia trivia) - { - var sourceText = trivia.SyntaxTree.GetText (cancellationToken); - Microsoft.CodeAnalysis.Text.TextLine textLine; - try { - textLine = sourceText.Lines.GetLineFromPosition (trivia.SpanStart); - } catch (ArgumentOutOfRangeException) { - return false; - } - //We need start of trivia.FullSpan and not trivia.SpanStart - //because in case of documentation /// <summary... - //trivia.SpanStart is space after /// and not 1st / - //so with trivia.FullSpan.Start we get index of 1st / - var startSpan = trivia.FullSpan.Start; - for (int i = textLine.Start; i < startSpan; i++) { - char ch = sourceText [i]; - if (!char.IsWhiteSpace (ch)) - return false; - } - return true; - } - - string CropStart (SyntaxTrivia trivia, string crop) + var text = trivia.SyntaxTree.GetText (cancellationToken);
+ if (text [fullSpan.End - 2] == '\r' && text [fullSpan.End - 1] == '\n')
+ fullSpan = new Microsoft.CodeAnalysis.Text.TextSpan (fullSpan.Start, fullSpan.Length - 2);
+ else if (NewLine.IsNewLine (text [fullSpan.End - 1]))
+ fullSpan = new Microsoft.CodeAnalysis.Text.TextSpan (fullSpan.Start, fullSpan.Length - 1);
+ }
+ try {
+ var lineSpan = trivia.SyntaxTree.GetLineSpan (fullSpan);
+ return (DocumentRegion)lineSpan;
+ } catch (Exception) {
+ return DocumentRegion.Empty;
+ }
+ }
+
+ public override void VisitBlock (BlockSyntax node)
+ {
+ cancellationToken.ThrowIfCancellationRequested ();
+ base.VisitBlock (node);
+ }
+
+ bool StartsLine (SyntaxTrivia trivia)
+ {
+ var sourceText = trivia.SyntaxTree.GetText (cancellationToken);
+ Microsoft.CodeAnalysis.Text.TextLine textLine;
+ try {
+ textLine = sourceText.Lines.GetLineFromPosition (trivia.SpanStart);
+ } catch (ArgumentOutOfRangeException) {
+ return false;
+ }
+ //We need start of trivia.FullSpan and not trivia.SpanStart
+ //because in case of documentation /// <summary...
+ //trivia.SpanStart is space after /// and not 1st /
+ //so with trivia.FullSpan.Start we get index of 1st /
+ var startSpan = trivia.FullSpan.Start;
+ for (int i = textLine.Start; i < startSpan; i++) {
+ char ch = sourceText [i];
+ if (!char.IsWhiteSpace (ch))
+ return false;
+ }
+ return true;
+ }
+
+ string CropStart (SyntaxTrivia trivia, string crop)
{
- var sourceText = trivia.SyntaxTree.GetText (cancellationToken); + var sourceText = trivia.SyntaxTree.GetText (cancellationToken);
var span = trivia.Span;
int i = span.Start;
int end = span.End;
@@ -201,173 +201,174 @@ namespace MonoDevelop.VBNetBinding i++;
return sourceText.ToString (new Microsoft.CodeAnalysis.Text.TextSpan (i, end - i));
- } - - public override void VisitTrivia (SyntaxTrivia trivia) - { - cancellationToken.ThrowIfCancellationRequested (); - base.VisitTrivia (trivia); - switch (trivia.Kind ()) { - case SyntaxKind.MultiLineCommentTrivia: - case SyntaxKind.MultiLineDocumentationCommentTrivia: - { - var cmt = new Comment (CropStart (trivia, "/*")); - cmt.CommentStartsLine = StartsLine(trivia); - cmt.CommentType = CommentType.Block; - cmt.OpenTag = "/*"; - cmt.ClosingTag = "*/"; - cmt.Region = GetRegion (trivia); - Comments.Add (cmt); - break; - } - case SyntaxKind.SingleLineCommentTrivia: - { - var cmt = new Comment (CropStart (trivia, "//")); - cmt.CommentStartsLine = StartsLine(trivia); - cmt.CommentType = CommentType.SingleLine; - cmt.OpenTag = "//"; - cmt.Region = GetRegion (trivia); - Comments.Add (cmt); - break; - } - case SyntaxKind.SingleLineDocumentationCommentTrivia: - { - var cmt = new Comment (CropStart (trivia, "///")); - cmt.CommentStartsLine = StartsLine(trivia); - cmt.IsDocumentation = true; - cmt.CommentType = CommentType.Documentation; - cmt.OpenTag = "///"; - cmt.ClosingTag = "///"; - cmt.Region = GetRegion (trivia); - Comments.Add (cmt); - break; - } - - } - - } - } - - // Tags are done via Ide.Tasks.CommentTasksProvider. - public override Task<IReadOnlyList<Tag>> GetTagCommentsAsync (CancellationToken cancellationToken = default(CancellationToken)) - { - return Task.FromResult<IReadOnlyList<Tag>> (null); - } - - sealed class SemanticTagVisitor : CSharpSyntaxWalker - { - public List<Tag> Tags = new List<Tag> (); - CancellationToken cancellationToken; - - public SemanticTagVisitor () : base (SyntaxWalkerDepth.Trivia) - { - } - - public SemanticTagVisitor (CancellationToken cancellationToken) : base (SyntaxWalkerDepth.Trivia) - { - this.cancellationToken = cancellationToken; - } - - public override void VisitBlock (BlockSyntax node) - { - cancellationToken.ThrowIfCancellationRequested (); - base.VisitBlock (node); - } - - public override void VisitTrivia (SyntaxTrivia trivia) - { - cancellationToken.ThrowIfCancellationRequested (); - if (trivia.IsKind (SyntaxKind.SingleLineCommentTrivia) || - trivia.IsKind (SyntaxKind.MultiLineCommentTrivia) || - trivia.IsKind (SyntaxKind.SingleLineDocumentationCommentTrivia)) { - var trimmedContent = trivia.ToString ().TrimStart ('/', ' ', '*'); - foreach (string tag in tagComments) { - if (!trimmedContent.StartsWith (tag, StringComparison.Ordinal)) - continue; - var loc = trivia.GetLocation ().GetLineSpan (); - Tags.Add (new Tag (tag, trimmedContent, new DocumentRegion (loc.StartLinePosition, loc.EndLinePosition))); - break; - } - } - } - - public override void VisitThrowStatement (Microsoft.CodeAnalysis.CSharp.Syntax.ThrowStatementSyntax node) - { - cancellationToken.ThrowIfCancellationRequested (); - base.VisitThrowStatement (node); - var createExpression = node.Expression as ObjectCreationExpressionSyntax; - if (createExpression == null) - return; - var st = createExpression.Type.ToString (); - if (st == "NotImplementedException" || st == "System.NotImplementedException") { - var loc = node.GetLocation ().GetLineSpan (); - if (createExpression.ArgumentList.Arguments.Count > 0) { - Tags.Add (new Tag ("High", GettextCatalog.GetString ("NotImplementedException({0}) thrown.", createExpression.ArgumentList.Arguments.First ().ToString ()), new DocumentRegion (loc.StartLinePosition, loc.EndLinePosition))); - } else { - Tags.Add (new Tag ("High", GettextCatalog.GetString ("NotImplementedException thrown."), new DocumentRegion (loc.StartLinePosition, loc.EndLinePosition))); - } - } - } - } - - static readonly Task<IReadOnlyList<FoldingRegion>> foldings = Task.FromResult((IReadOnlyList<FoldingRegion>)new FoldingRegion[0]); - - public override Task<IReadOnlyList<FoldingRegion>> GetFoldingsAsync (CancellationToken cancellationToken = default (CancellationToken)) => foldings; - - SemaphoreSlim errorLock = new SemaphoreSlim (1, 1); - - static readonly IReadOnlyList<Error> emptyErrors = Array.Empty<Error> (); - public override async Task<IReadOnlyList<Error>> GetErrorsAsync (CancellationToken cancellationToken = default(CancellationToken)) - { - if (Ide.IdeApp.Preferences.EnableSourceAnalysis || DocumentId is null) - return emptyErrors; - - // FIXME: remove this fallback, error squiggles should always be handled via the source analysis mechanism - var document = IdeServices.TypeSystemService.GetCodeAnalysisDocument (DocumentId, cancellationToken); - var model = await document.GetSemanticModelAsync (cancellationToken); - - bool locked = await errorLock.WaitAsync (Timeout.Infinite, cancellationToken).ConfigureAwait (false); - IReadOnlyList<Error> errors; + }
+
+ public override void VisitTrivia (SyntaxTrivia trivia)
+ {
+ cancellationToken.ThrowIfCancellationRequested ();
+ base.VisitTrivia (trivia);
+ switch (trivia.Kind ()) {
+ case SyntaxKind.MultiLineCommentTrivia:
+ case SyntaxKind.MultiLineDocumentationCommentTrivia:
+ {
+ var cmt = new Comment (CropStart (trivia, "/*"));
+ cmt.CommentStartsLine = StartsLine(trivia);
+ cmt.CommentType = CommentType.Block;
+ cmt.OpenTag = "/*";
+ cmt.ClosingTag = "*/";
+ cmt.Region = GetRegion (trivia);
+ Comments.Add (cmt);
+ break;
+ }
+ case SyntaxKind.SingleLineCommentTrivia:
+ {
+ var cmt = new Comment (CropStart (trivia, "//"));
+ cmt.CommentStartsLine = StartsLine(trivia);
+ cmt.CommentType = CommentType.SingleLine;
+ cmt.OpenTag = "//";
+ cmt.Region = GetRegion (trivia);
+ Comments.Add (cmt);
+ break;
+ }
+ case SyntaxKind.SingleLineDocumentationCommentTrivia:
+ {
+ var cmt = new Comment (CropStart (trivia, "///"));
+ cmt.CommentStartsLine = StartsLine(trivia);
+ cmt.IsDocumentation = true;
+ cmt.CommentType = CommentType.Documentation;
+ cmt.OpenTag = "///";
+ cmt.ClosingTag = "///";
+ cmt.Region = GetRegion (trivia);
+ Comments.Add (cmt);
+ break;
+ }
+
+ }
+
+ }
+ }
+
+ // Tags are done via Ide.Tasks.CommentTasksProvider.
+ public override Task<IReadOnlyList<Tag>> GetTagCommentsAsync (CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return Task.FromResult<IReadOnlyList<Tag>> (null);
+ }
+
+ sealed class SemanticTagVisitor : CSharpSyntaxWalker
+ {
+ public List<Tag> Tags = new List<Tag> ();
+ CancellationToken cancellationToken;
+
+ public SemanticTagVisitor () : base (SyntaxWalkerDepth.Trivia)
+ {
+ }
+
+ public SemanticTagVisitor (CancellationToken cancellationToken) : base (SyntaxWalkerDepth.Trivia)
+ {
+ this.cancellationToken = cancellationToken;
+ }
+
+ public override void VisitBlock (BlockSyntax node)
+ {
+ cancellationToken.ThrowIfCancellationRequested ();
+ base.VisitBlock (node);
+ }
+
+ public override void VisitTrivia (SyntaxTrivia trivia)
+ {
+ cancellationToken.ThrowIfCancellationRequested ();
+ if (trivia.IsKind (SyntaxKind.SingleLineCommentTrivia) ||
+ trivia.IsKind (SyntaxKind.MultiLineCommentTrivia) ||
+ trivia.IsKind (SyntaxKind.SingleLineDocumentationCommentTrivia)) {
+ var trimmedContent = trivia.ToString ().TrimStart ('/', ' ', '*');
+ foreach (string tag in tagComments) {
+ if (!trimmedContent.StartsWith (tag, StringComparison.Ordinal))
+ continue;
+ var loc = trivia.GetLocation ().GetLineSpan ();
+ Tags.Add (new Tag (tag, trimmedContent, new DocumentRegion (loc.StartLinePosition, loc.EndLinePosition)));
+ break;
+ }
+ }
+ }
+
+ public override void VisitThrowStatement (Microsoft.CodeAnalysis.CSharp.Syntax.ThrowStatementSyntax node)
+ {
+ cancellationToken.ThrowIfCancellationRequested ();
+ base.VisitThrowStatement (node);
+ var createExpression = node.Expression as ObjectCreationExpressionSyntax;
+ if (createExpression == null)
+ return;
+ var st = createExpression.Type.ToString ();
+ if (st == "NotImplementedException" || st == "System.NotImplementedException") {
+ var loc = node.GetLocation ().GetLineSpan ();
+ if (createExpression.ArgumentList.Arguments.Count > 0) {
+ Tags.Add (new Tag ("High", GettextCatalog.GetString ("NotImplementedException({0}) thrown.", createExpression.ArgumentList.Arguments.First ().ToString ()), new DocumentRegion (loc.StartLinePosition, loc.EndLinePosition)));
+ } else {
+ Tags.Add (new Tag ("High", GettextCatalog.GetString ("NotImplementedException thrown."), new DocumentRegion (loc.StartLinePosition, loc.EndLinePosition)));
+ }
+ }
+ }
+ }
+
+ static readonly Task<IReadOnlyList<FoldingRegion>> foldings = Task.FromResult((IReadOnlyList<FoldingRegion>)new FoldingRegion[0]);
+
+ public override Task<IReadOnlyList<FoldingRegion>> GetFoldingsAsync (CancellationToken cancellationToken = default (CancellationToken)) => foldings;
+
+ SemaphoreSlim errorLock = new SemaphoreSlim (1, 1);
+
+ static readonly IReadOnlyList<Error> emptyErrors = Array.Empty<Error> ();
+ public override async Task<IReadOnlyList<Error>> GetErrorsAsync (CancellationToken cancellationToken = default(CancellationToken))
+ {
+ if (Ide.IdeApp.Preferences.EnableSourceAnalysis || DocumentId is null)
+ return emptyErrors;
+
+ // FIXME: remove this fallback, error squiggles should always be handled via the source analysis mechanism
+ var document = IdeServices.TypeSystemService.GetCodeAnalysisDocument (DocumentId, cancellationToken);
+ var model = await document.GetSemanticModelAsync (cancellationToken);
+
+ bool locked = await errorLock.WaitAsync (Timeout.Infinite, cancellationToken).ConfigureAwait (false);
+ IReadOnlyList<Error> errors;
try {
try {
errors = model
.GetDiagnostics (null, cancellationToken)
.Select ((Diagnostic diag) => new Error (GetErrorType (diag.Severity), diag.Id, diag.GetMessage (), GetRegion (diag)) { Tag = diag })
- .ToList (); + .ToList ();
} catch (OperationCanceledException) {
errors = emptyErrors;
} catch (Exception e) {
LoggingService.LogError ("Error while getting diagnostics.", e);
errors = emptyErrors;
}
- } finally { - if (locked) - errorLock.Release ();
} - - return errors; - } - - static DocumentRegion GetRegion (Diagnostic diagnostic) - { - try { - var lineSpan = diagnostic.Location.GetLineSpan (); - return new DocumentRegion (lineSpan.StartLinePosition, lineSpan.EndLinePosition); - } catch (Exception) { - return DocumentRegion.Empty; - } - } - - static ErrorType GetErrorType (DiagnosticSeverity severity) - { - switch (severity) { - case DiagnosticSeverity.Error: - return ErrorType.Error; - case DiagnosticSeverity.Warning: - return ErrorType.Warning; - } - return ErrorType.Unknown; - } - - #endregion - } -}
\ No newline at end of file + } finally {
+ if (locked)
+ errorLock.Release ();
+ }
+
+ return errors;
+ }
+
+ static DocumentRegion GetRegion (Diagnostic diagnostic)
+ {
+ try {
+ var lineSpan = diagnostic.Location.GetLineSpan ();
+ return new DocumentRegion (lineSpan.StartLinePosition, lineSpan.EndLinePosition);
+ } catch (Exception) {
+ return DocumentRegion.Empty;
+ }
+ }
+
+ static ErrorType GetErrorType (DiagnosticSeverity severity)
+ {
+ switch (severity) {
+ case DiagnosticSeverity.Error:
+ return ErrorType.Error;
+ case DiagnosticSeverity.Warning:
+ return ErrorType.Warning;
+ }
+ return ErrorType.Unknown;
+ }
+
+ #endregion
+ }
+}
|