Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/addins/CSharpBinding/MonoDevelop.CSharp.Parser')
-rw-r--r--main/src/addins/CSharpBinding/MonoDevelop.CSharp.Parser/CSharpFoldingParser.cs22
-rw-r--r--main/src/addins/CSharpBinding/MonoDevelop.CSharp.Parser/CSharpParsedDocument.cs444
-rw-r--r--main/src/addins/CSharpBinding/MonoDevelop.CSharp.Parser/TypeSystemProvider.cs456
3 files changed, 532 insertions, 390 deletions
diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Parser/CSharpFoldingParser.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Parser/CSharpFoldingParser.cs
index f87390b709..776abe4a87 100644
--- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Parser/CSharpFoldingParser.cs
+++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Parser/CSharpFoldingParser.cs
@@ -26,9 +26,7 @@
using System;
using System.Collections.Generic;
using MonoDevelop.Ide.TypeSystem;
-using ICSharpCode.NRefactory;
-using ICSharpCode.NRefactory.TypeSystem;
-using ICSharpCode.NRefactory.CSharp;
+using MonoDevelop.Ide.Editor;
namespace MonoDevelop.CSharp.Parser
{
@@ -94,14 +92,14 @@ namespace MonoDevelop.CSharp.Parser
public unsafe ParsedDocument Parse (string fileName, string content)
{
- var regionStack = new Stack<Tuple<string, TextLocation>> ();
+ var regionStack = new Stack<Tuple<string, DocumentLocation>> ();
var result = new DefaultParsedDocument (fileName);
bool inSingleComment = false, inMultiLineComment = false;
bool inString = false, inVerbatimString = false;
bool inChar = false;
bool inLineStart = true, hasStartedAtLine = false;
int line = 1, column = 1;
- var startLoc = TextLocation.Empty;
+ var startLoc = DocumentLocation.Empty;
fixed (char* startPtr = content) {
char* endPtr = startPtr + content.Length;
@@ -116,7 +114,7 @@ namespace MonoDevelop.CSharp.Parser
ptr++;
if (StartsIdentifier (ptr, endPtr, "region")) {
- var regionLocation = new TextLocation (line, column);
+ var regionLocation = new DocumentLocation (line, column);
column++;
ptr += "region".Length;
column += "region".Length;
@@ -131,7 +129,7 @@ namespace MonoDevelop.CSharp.Parser
var beginRegion = regionStack.Pop ();
result.Add (new FoldingRegion (
beginRegion.Item1,
- new DomRegion (beginRegion.Item2.Line, beginRegion.Item2.Column, line, column),
+ new DocumentRegion (beginRegion.Item2.Line, beginRegion.Item2.Column, line, column),
FoldType.UserRegion,
true));
}
@@ -150,14 +148,14 @@ namespace MonoDevelop.CSharp.Parser
if (nextCh == '/') {
hasStartedAtLine = inLineStart;
beginPtr = ptr + 2;
- startLoc = new TextLocation (line, column);
+ startLoc = new DocumentLocation (line, column);
ptr++;
column++;
inSingleComment = true;
} else if (nextCh == '*') {
hasStartedAtLine = inLineStart;
beginPtr = ptr + 2;
- startLoc = new TextLocation (line, column);
+ startLoc = new DocumentLocation (line, column);
ptr++;
column++;
inMultiLineComment = true;
@@ -175,7 +173,7 @@ namespace MonoDevelop.CSharp.Parser
column += 2;
inMultiLineComment = false;
result.Add (new MonoDevelop.Ide.TypeSystem.Comment () {
- Region = new DomRegion (startLoc, new TextLocation (line, column)),
+ Region = new DocumentRegion (startLoc, new DocumentLocation (line, column)),
OpenTag = "/*",
CommentType = MonoDevelop.Ide.TypeSystem.CommentType.Block,
Text = content.Substring ((int)(beginPtr - startPtr), (int)(ptr - beginPtr)),
@@ -202,7 +200,7 @@ namespace MonoDevelop.CSharp.Parser
beginPtr++;
result.Add (new MonoDevelop.Ide.TypeSystem.Comment () {
- Region = new DomRegion (startLoc, new TextLocation (line, column)),
+ Region = new DocumentRegion (startLoc, new DocumentLocation (line, column)),
CommentType = MonoDevelop.Ide.TypeSystem.CommentType.SingleLine,
OpenTag = "//",
Text = content.Substring ((int)(beginPtr - startPtr), (int)(ptr - beginPtr)),
@@ -254,7 +252,7 @@ namespace MonoDevelop.CSharp.Parser
ptr++;
}
}
- foreach (var fold in result.Comments.ToFolds ()) {
+ foreach (var fold in result.GetCommentsAsync().Result.ToFolds ()) {
result.Add (fold);
}
return result;
diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Parser/CSharpParsedDocument.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Parser/CSharpParsedDocument.cs
new file mode 100644
index 0000000000..db4c99f3c8
--- /dev/null
+++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Parser/CSharpParsedDocument.cs
@@ -0,0 +1,444 @@
+//
+// 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;
+
+namespace MonoDevelop.CSharp.Parser
+{
+ class CSharpParsedDocument : ParsedDocument
+ {
+ internal SyntaxTree Unit {
+ get;
+ set;
+ }
+
+ public CSharpParsedDocument (string fileName) : base (fileName)
+ {
+ }
+
+
+ #region implemented abstract members of ParsedDocument
+
+
+ WeakReference<IReadOnlyList<Comment>> weakComments;
+
+ public override Task<IReadOnlyList<Comment>> GetCommentsAsync (CancellationToken cancellationToken = default(CancellationToken))
+ {
+ IReadOnlyList<Comment> result;
+ if (weakComments == null || !weakComments.TryGetTarget (out result)) {
+ var visitor = new CommentVisitor (cancellationToken);
+ if (Unit != null)
+ visitor.Visit (Unit.GetRoot (cancellationToken));
+ result = visitor.Comments;
+
+ var newRef = new WeakReference<IReadOnlyList<Comment>> (result);
+ var oldRef = weakComments;
+ while (Interlocked.CompareExchange (ref weakComments, newRef, oldRef) == oldRef) {
+ }
+ }
+ return Task.FromResult (result);
+ }
+
+
+ class CommentVisitor : CSharpSyntaxWalker
+ {
+ public readonly List<Comment> Comments = new List<Comment> ();
+
+ CancellationToken cancellationToken;
+
+ public CommentVisitor (CancellationToken cancellationToken) : base(SyntaxWalkerDepth.Trivia)
+ {
+ this.cancellationToken = cancellationToken;
+ }
+
+ static DocumentRegion GetRegion (SyntaxTrivia trivia)
+ {
+ var fullSpan = trivia.FullSpan;
+ var text = trivia.ToString ();
+ if (text.Length > 2) {
+ if (text [text.Length - 2] == '\r' && text [text.Length - 1] == '\n')
+ fullSpan = new Microsoft.CodeAnalysis.Text.TextSpan (fullSpan.Start, fullSpan.Length - 2);
+ else if (ICSharpCode.NRefactory6.NewLine.IsNewLine (text [text.Length - 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;
+ }
+
+ static string CropStart (string text, string crop)
+ {
+ text = text.Trim ();
+ if (text.StartsWith (crop))
+ return text.Substring (crop.Length).TrimStart ();
+ return text;
+ }
+
+ public override void VisitTrivia (SyntaxTrivia trivia)
+ {
+ base.VisitTrivia (trivia);
+ switch (trivia.Kind ()) {
+ case SyntaxKind.MultiLineCommentTrivia:
+ case SyntaxKind.MultiLineDocumentationCommentTrivia:
+ {
+ var cmt = new Comment (CropStart (trivia.ToString (), "/*"));
+ 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.ToString (), "//"));
+ 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.ToString (), "///"));
+ cmt.CommentStartsLine = StartsLine(trivia);
+ cmt.IsDocumentation = true;
+ cmt.CommentType = CommentType.Documentation;
+ cmt.OpenTag = "///";
+ cmt.ClosingTag = "*/";
+ cmt.Region = GetRegion (trivia);
+ Comments.Add (cmt);
+ break;
+ }
+
+ }
+
+ }
+ }
+
+ WeakReference<IReadOnlyList<Tag>> weakTags;
+
+ public override Task<IReadOnlyList<Tag>> GetTagCommentsAsync (CancellationToken cancellationToken = default(CancellationToken))
+ {
+ IReadOnlyList<Tag> result;
+ if (weakTags == null || !weakTags.TryGetTarget (out result)) {
+ var visitor = new SemanticTagVisitor (cancellationToken);
+ if (Unit != null) {
+ try {
+ visitor.Visit (Unit.GetRoot (cancellationToken));
+ } catch {
+ }
+ }
+ result = visitor.Tags;
+
+ var newRef = new WeakReference<IReadOnlyList<Tag>> (result);
+ var oldRef = weakTags;
+ while (Interlocked.CompareExchange (ref weakTags, newRef, oldRef) == oldRef) {
+ }
+ }
+ return Task.FromResult (result);
+ }
+
+ sealed class SemanticTagVisitor : CSharpSyntaxWalker
+ {
+ string[] tagComments;
+ public List<Tag> Tags = new List<Tag> ();
+ CancellationToken cancellationToken;
+
+ public SemanticTagVisitor () : base (SyntaxWalkerDepth.Trivia)
+ {
+ tagComments = MonoDevelop.Ide.Tasks.CommentTag.SpecialCommentTags.Select (t => t.Tag).ToArray ();
+
+ }
+
+ public SemanticTagVisitor (CancellationToken cancellationToken)
+ {
+ 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)) {
+ foreach (string tag in tagComments) {
+ var trimmedContent = trivia.ToString ().TrimStart ('/', ' ', '*');
+ if (!trimmedContent.StartsWith (tag))
+ 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)));
+ }
+ }
+ }
+ }
+
+ WeakReference<IReadOnlyList<FoldingRegion>> weakFoldings;
+
+ public override Task<IReadOnlyList<FoldingRegion>> GetFoldingsAsync (CancellationToken cancellationToken = default(CancellationToken))
+ {
+ IReadOnlyList<FoldingRegion> result;
+ if (weakFoldings == null || !weakFoldings.TryGetTarget (out result)) {
+
+ result = GenerateFoldings (cancellationToken).ToList ();
+
+ var newRef = new WeakReference<IReadOnlyList<FoldingRegion>> (result);
+ var oldRef = weakFoldings;
+ while (Interlocked.CompareExchange (ref weakFoldings, newRef, oldRef) == oldRef) {
+ }
+ }
+
+ return Task.FromResult (result);
+ }
+
+ IEnumerable<FoldingRegion> GenerateFoldings (CancellationToken cancellationToken)
+ {
+ foreach (var fold in GetCommentsAsync().Result.ToFolds ())
+ yield return fold;
+
+ var visitor = new FoldingVisitor (cancellationToken);
+ if (Unit != null) {
+ try {
+ visitor.Visit (Unit.GetRoot (cancellationToken));
+ } catch (Exception) { }
+ }
+ foreach (var fold in visitor.Foldings)
+ yield return fold;
+ }
+
+ class FoldingVisitor : CSharpSyntaxWalker
+ {
+ public readonly List<FoldingRegion> Foldings = new List<FoldingRegion> ();
+ CancellationToken cancellationToken;
+
+ public FoldingVisitor (CancellationToken cancellationToken)
+ {
+ this.cancellationToken = cancellationToken;
+ }
+
+ void AddUsings (SyntaxNode parent)
+ {
+ SyntaxNode firstChild = null, lastChild = null;
+ foreach (var child in parent.ChildNodes ()) {
+ if (child is UsingDirectiveSyntax) {
+ if (firstChild == null) {
+ firstChild = child;
+ }
+ lastChild = child;
+ continue;
+ }
+ if (firstChild != null)
+ break;
+ }
+
+ if (firstChild != null && firstChild != lastChild) {
+ var first = firstChild.GetLocation ().GetLineSpan ();
+ var last = lastChild.GetLocation ().GetLineSpan ();
+
+ Foldings.Add (new FoldingRegion (new DocumentRegion (first.StartLinePosition, last.EndLinePosition), FoldType.Undefined));
+ }
+ }
+
+ public override void VisitCompilationUnit (Microsoft.CodeAnalysis.CSharp.Syntax.CompilationUnitSyntax node)
+ {
+ AddUsings (node);
+ base.VisitCompilationUnit (node);
+ }
+
+ void AddFolding (SyntaxToken openBrace, SyntaxToken closeBrace)
+ {
+ openBrace = openBrace.GetPreviousToken (false, false, true, true);
+
+ try {
+ var first = openBrace.GetLocation ().GetLineSpan ();
+ var last = closeBrace.GetLocation ().GetLineSpan ();
+
+ if (first.EndLinePosition.Line != last.EndLinePosition.Line)
+ Foldings.Add (new FoldingRegion (new DocumentRegion (first.EndLinePosition, last.EndLinePosition), FoldType.Undefined));
+ } catch (ArgumentOutOfRangeException) {}
+ }
+
+ public override void VisitNamespaceDeclaration (Microsoft.CodeAnalysis.CSharp.Syntax.NamespaceDeclarationSyntax node)
+ {
+ AddUsings (node);
+ AddFolding (node.OpenBraceToken, node.CloseBraceToken);
+ base.VisitNamespaceDeclaration (node);
+ }
+
+ public override void VisitClassDeclaration (Microsoft.CodeAnalysis.CSharp.Syntax.ClassDeclarationSyntax node)
+ {
+ AddFolding (node.OpenBraceToken, node.CloseBraceToken);
+ base.VisitClassDeclaration (node);
+ }
+
+ public override void VisitStructDeclaration (Microsoft.CodeAnalysis.CSharp.Syntax.StructDeclarationSyntax node)
+ {
+ AddFolding (node.OpenBraceToken, node.CloseBraceToken);
+ base.VisitStructDeclaration (node);
+ }
+
+ public override void VisitInterfaceDeclaration (Microsoft.CodeAnalysis.CSharp.Syntax.InterfaceDeclarationSyntax node)
+ {
+ AddFolding (node.OpenBraceToken, node.CloseBraceToken);
+ base.VisitInterfaceDeclaration (node);
+ }
+
+ public override void VisitEnumDeclaration (Microsoft.CodeAnalysis.CSharp.Syntax.EnumDeclarationSyntax node)
+ {
+ AddFolding (node.OpenBraceToken, node.CloseBraceToken);
+ base.VisitEnumDeclaration (node);
+ }
+
+ public override void VisitBlock (Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax node)
+ {
+ cancellationToken.ThrowIfCancellationRequested ();
+ AddFolding (node.OpenBraceToken, node.CloseBraceToken);
+ base.VisitBlock (node);
+ }
+ }
+
+ static readonly IReadOnlyList<Error> emptyErrors = new Error[0];
+ WeakReference<IReadOnlyList<Error>> weakErrors;
+
+ public override Task<IReadOnlyList<Error>> GetErrorsAsync (CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var model = GetAst<SemanticModel> ();
+ if (model == null)
+ return Task.FromResult (emptyErrors);
+
+ IReadOnlyList<Error> result;
+ if (weakErrors == null || !weakErrors.TryGetTarget (out result)) {
+ try {
+ result = model
+ .GetDiagnostics (null, cancellationToken)
+ .Where (diag => diag.Severity == DiagnosticSeverity.Error || diag.Severity == DiagnosticSeverity.Warning)
+ .Select ((Diagnostic diag) => new Error (GetErrorType (diag.Severity), diag.Id, diag.GetMessage (), GetRegion (diag)) { Tag = diag })
+ .ToList ();
+ var newRef = new WeakReference<IReadOnlyList<Error>> (result);
+ var oldRef = weakErrors;
+ while (Interlocked.CompareExchange (ref weakErrors, newRef, oldRef) == oldRef) {
+ }
+ } catch (OperationCanceledException) {
+ return Task.FromResult (emptyErrors);
+ } catch (Exception e) {
+ LoggingService.LogError ("Error while getting diagnostics.", e);
+ return Task.FromResult (emptyErrors);
+ }
+ }
+ return Task.FromResult (result);
+ }
+
+ 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
diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Parser/TypeSystemProvider.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Parser/TypeSystemProvider.cs
index 498d98544f..037656f295 100644
--- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Parser/TypeSystemProvider.cs
+++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Parser/TypeSystemProvider.cs
@@ -25,375 +25,90 @@
// THE SOFTWARE.
using System;
using MonoDevelop.Ide.TypeSystem;
-using ICSharpCode.NRefactory.CSharp;
-using ICSharpCode.NRefactory.TypeSystem;
using System.Collections.Generic;
using MonoDevelop.Projects;
using MonoDevelop.CSharp.Project;
-using MonoDevelop.Ide.Tasks;
using Mono.CSharp;
using System.Linq;
-using ICSharpCode.NRefactory;
-using MonoDevelop.CSharp.Refactoring.CodeActions;
using MonoDevelop.Core;
-using ICSharpCode.NRefactory.CSharp.Resolver;
+using MonoDevelop.Ide.Editor;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.Text;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using MonoDevelop.Core.Text;
+using System.Threading.Tasks;
namespace MonoDevelop.CSharp.Parser
{
- public class TypeSystemParser : MonoDevelop.Ide.TypeSystem.TypeSystemParser
+ sealed class TypeSystemParser : MonoDevelop.Ide.TypeSystem.TypeSystemParser
{
- public override ParsedDocument Parse (bool storeAst, string fileName, System.IO.TextReader content, MonoDevelop.Projects.Project project = null)
+ static readonly List<Error> emptyList = new List<Error> ();
+ public override System.Threading.Tasks.Task<ParsedDocument> Parse (MonoDevelop.Ide.TypeSystem.ParseOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken))
{
- var parser = new ICSharpCode.NRefactory.CSharp.CSharpParser (GetCompilerArguments (project));
- parser.GenerateTypeSystemMode = !storeAst;
- var result = new ParsedDocumentDecorator ();
+ var fileName = options.FileName;
+ var project = options.Project;
+ var result = new CSharpParsedDocument (fileName);
if (project != null) {
+
var projectFile = project.Files.GetFile (fileName);
if (projectFile != null && !TypeSystemParserNode.IsCompileBuildAction (projectFile.BuildAction))
result.Flags |= ParsedDocumentFlags.NonSerializable;
}
- var tagComments = CommentTag.SpecialCommentTags.Select (t => t.Tag).ToArray ();
-
- parser.CompilationUnitCallback = delegate (CompilerCompilationUnit top) {
- foreach (var special in top.SpecialsBag.Specials) {
- var comment = special as SpecialsBag.Comment;
- if (comment != null) {
- VisitComment (result, comment, tagComments);
- } else {
- if (storeAst) {
- var ppd = special as SpecialsBag.PreProcessorDirective;
- if (ppd != null)
- VisitPreprocessorDirective (result, ppd);
- }
- }
- }
- };
-
- var unit = parser.Parse (content, fileName);
- unit.Freeze ();
- var pf = unit.ToTypeSystem ();
- try {
- pf.LastWriteTime = System.IO.File.GetLastWriteTimeUtc (fileName);
- } catch (Exception) {
- pf.LastWriteTime = DateTime.UtcNow;
- }
-
- result.LastWriteTimeUtc = pf.LastWriteTime.Value;
- result.ParsedFile = pf;
- result.Add (GetSemanticTags (unit));
-
- result.CreateRefactoringContext = delegate (MonoDevelop.Ide.Gui.Document doc, System.Threading.CancellationToken token) {
- var task = MDRefactoringContext.Create (doc, doc.Editor.Caret.Location, token);
- try {
- task.Wait (5000, token);
- } catch (AggregateException ae) {
- ae.Flatten ().Handle (aex => aex is OperationCanceledException);
- return null;
- } catch (OperationCanceledException) {
- return null;
- }
- if (!task.IsCompleted)
- return null;
- return task.Result;
- };
- result.CreateRefactoringContextWithEditor = (data, resolver, token) => new MDRefactoringContext ((DotNetProject)project, data, result, (CSharpAstResolver)resolver, TextLocation.Empty, token);
+ var compilerArguments = GetCompilerArguments (project);
+ SyntaxTree unit = null;
- if (storeAst) {
- result.Ast = unit;
- result.Add (GenerateFoldings (unit, result));
- }
- return result;
- }
-
- IEnumerable<FoldingRegion> GenerateFoldings (SyntaxTree unit, ParsedDocument doc)
- {
- foreach (var fold in doc.ConditionalRegions.ToFolds ())
- yield return fold;
-
- foreach (var fold in doc.Comments.ToFolds ())
- yield return fold;
-
- var visitor = new FoldingVisitor ();
- unit.AcceptVisitor (visitor, null);
- foreach (var fold in visitor.Foldings)
- yield return fold;
- }
-
- class FoldingVisitor : DepthFirstAstVisitor<object, object>
- {
- public readonly List<FoldingRegion> Foldings = new List<FoldingRegion> ();
-
- void AddUsings (AstNode parent)
- {
- var firstChild = parent.Children.FirstOrDefault (child => child is UsingDeclaration || child is UsingAliasDeclaration);
- var node = firstChild;
- while (node != null) {
- var next = node.GetNextNode ();
- if (next is UsingDeclaration || next is UsingAliasDeclaration) {
- node = next;
- } else {
- break;
+ if (project != null) {
+ var curDoc = options.RoslynDocument;
+ if (curDoc == null) {
+ var curProject = TypeSystemService.GetCodeAnalysisProject (project);
+ if (curProject != null) {
+ var documentId = TypeSystemService.GetDocumentId (project, fileName);
+ if (documentId != null)
+ curDoc = curProject.GetDocument (documentId);
}
}
- if (firstChild != node) {
- Foldings.Add (new FoldingRegion (new DomRegion (firstChild.StartLocation, node.EndLocation), FoldType.Undefined));
- }
- }
- public override object VisitSyntaxTree (SyntaxTree unit, object data)
- {
- AddUsings (unit);
- return base.VisitSyntaxTree (unit, data);
- }
-
- static TextLocation CorrectEnd (AstNode token)
- {
- return new TextLocation (token.EndLocation.Line, token.EndLocation.Column + 1);
- }
-
- static bool LastToken(AstNode arg)
- {
- return !(arg.Role == Roles.NewLine || arg.Role == Roles.Whitespace || arg.Role == Roles.Comment);
- }
-
- public override object VisitNamespaceDeclaration (NamespaceDeclaration namespaceDeclaration, object data)
- {
- AddUsings (namespaceDeclaration);
- if (!namespaceDeclaration.RBraceToken.IsNull && namespaceDeclaration.LBraceToken.StartLocation.Line != namespaceDeclaration.RBraceToken.StartLocation.Line)
- Foldings.Add (new FoldingRegion (new DomRegion (namespaceDeclaration.LBraceToken.GetPrevNode (LastToken).EndLocation, CorrectEnd (namespaceDeclaration.RBraceToken)), FoldType.Undefined));
- return base.VisitNamespaceDeclaration (namespaceDeclaration, data);
- }
-
- public override object VisitTypeDeclaration (TypeDeclaration typeDeclaration, object data)
- {
- if (!typeDeclaration.RBraceToken.IsNull && typeDeclaration.LBraceToken.StartLocation.Line != typeDeclaration.RBraceToken.StartLocation.Line)
- Foldings.Add (new FoldingRegion (new DomRegion (typeDeclaration.LBraceToken.GetPrevNode (LastToken).EndLocation, CorrectEnd (typeDeclaration.RBraceToken)), FoldType.Type));
- return base.VisitTypeDeclaration (typeDeclaration, data);
- }
-
- public override object VisitMethodDeclaration (MethodDeclaration methodDeclaration, object data)
- {
- if (!methodDeclaration.Body.IsNull && methodDeclaration.Body.LBraceToken.StartLocation.Line != methodDeclaration.Body.RBraceToken.StartLocation.Line)
- Foldings.Add (new FoldingRegion (new DomRegion (methodDeclaration.Body.LBraceToken.GetPrevNode (LastToken).EndLocation, CorrectEnd (methodDeclaration.Body.RBraceToken)), FoldType.Member));
- return base.VisitMethodDeclaration (methodDeclaration, data);
- }
-
- public override object VisitConstructorDeclaration (ConstructorDeclaration constructorDeclaration, object data)
- {
- if (!constructorDeclaration.Body.IsNull && constructorDeclaration.Body.LBraceToken.StartLocation.Line != constructorDeclaration.Body.RBraceToken.StartLocation.Line)
- Foldings.Add (new FoldingRegion (new DomRegion (constructorDeclaration.Body.LBraceToken.GetPrevNode (LastToken).EndLocation, CorrectEnd (constructorDeclaration.Body.RBraceToken)), FoldType.Member));
- return base.VisitConstructorDeclaration (constructorDeclaration, data);
- }
-
- public override object VisitDestructorDeclaration (DestructorDeclaration destructorDeclaration, object data)
- {
- if (!destructorDeclaration.Body.IsNull && destructorDeclaration.Body.LBraceToken.StartLocation.Line != destructorDeclaration.Body.RBraceToken.StartLocation.Line)
- Foldings.Add (new FoldingRegion (new DomRegion (destructorDeclaration.Body.LBraceToken.GetPrevNode (LastToken).EndLocation, CorrectEnd (destructorDeclaration.Body.RBraceToken)), FoldType.Member));
- return base.VisitDestructorDeclaration (destructorDeclaration, data);
- }
-
- public override object VisitOperatorDeclaration (OperatorDeclaration operatorDeclaration, object data)
- {
- if (!operatorDeclaration.Body.IsNull && operatorDeclaration.Body.LBraceToken.StartLocation.Line != operatorDeclaration.Body.RBraceToken.StartLocation.Line)
- Foldings.Add (new FoldingRegion (new DomRegion (operatorDeclaration.Body.LBraceToken.GetPrevNode (LastToken).EndLocation, CorrectEnd (operatorDeclaration.Body.RBraceToken)), FoldType.Member));
- return base.VisitOperatorDeclaration (operatorDeclaration, data);
- }
-
- public override object VisitPropertyDeclaration (PropertyDeclaration propertyDeclaration, object data)
- {
- if (!propertyDeclaration.LBraceToken.IsNull && propertyDeclaration.LBraceToken.StartLocation.Line != propertyDeclaration.RBraceToken.StartLocation.Line)
- Foldings.Add (new FoldingRegion (new DomRegion (propertyDeclaration.LBraceToken.GetPrevNode (LastToken).EndLocation, CorrectEnd (propertyDeclaration.RBraceToken)), FoldType.Member));
- return base.VisitPropertyDeclaration (propertyDeclaration, data);
- }
-
- public override object VisitIndexerDeclaration (IndexerDeclaration indexerDeclaration, object data)
- {
- if (!indexerDeclaration.LBraceToken.IsNull && indexerDeclaration.LBraceToken.StartLocation.Line != indexerDeclaration.RBraceToken.StartLocation.Line)
- Foldings.Add (new FoldingRegion (new DomRegion (indexerDeclaration.LBraceToken.GetPrevNode (LastToken).EndLocation, CorrectEnd (indexerDeclaration.RBraceToken)), FoldType.Member));
- return base.VisitIndexerDeclaration (indexerDeclaration, data);
- }
-
- public override object VisitCustomEventDeclaration (CustomEventDeclaration eventDeclaration, object data)
- {
- if (!eventDeclaration.LBraceToken.IsNull && eventDeclaration.LBraceToken.StartLocation.Line != eventDeclaration.RBraceToken.StartLocation.Line)
- Foldings.Add (new FoldingRegion (new DomRegion (eventDeclaration.LBraceToken.GetPrevNode (LastToken).EndLocation, CorrectEnd (eventDeclaration.RBraceToken)), FoldType.Member));
- return base.VisitCustomEventDeclaration (eventDeclaration, data);
- }
-
- public override object VisitSwitchStatement (SwitchStatement switchStatement, object data)
- {
- if (!switchStatement.RBraceToken.IsNull && switchStatement.LBraceToken.StartLocation.Line != switchStatement.RBraceToken.StartLocation.Line)
- Foldings.Add (new FoldingRegion (new DomRegion (switchStatement.LBraceToken.GetPrevNode (LastToken).EndLocation, CorrectEnd (switchStatement.RBraceToken)), FoldType.Member));
- return base.VisitSwitchStatement (switchStatement, data);
- }
-
- public override object VisitBlockStatement (BlockStatement blockStatement, object data)
- {
- if (!(blockStatement.Parent is EntityDeclaration) && blockStatement.EndLocation.Line - blockStatement.StartLocation.Line > 2) {
- Foldings.Add (new FoldingRegion (new DomRegion (blockStatement.GetPrevNode (LastToken).EndLocation, CorrectEnd (blockStatement.RBraceToken)), FoldType.Undefined));
- }
-
- return base.VisitBlockStatement (blockStatement, data);
- }
- }
-
- static IEnumerable<Tag> GetSemanticTags (SyntaxTree unit)
- {
- var visitor = new SemanticTagVisitor ();
- unit.AcceptVisitor (visitor);
- foreach (var fold in visitor.Tags)
- yield return fold;
- }
-
- public class SemanticTagVisitor : DepthFirstAstVisitor
- {
- public List<Tag> Tags = new List<Tag> ();
-
- public override void VisitThrowStatement (ThrowStatement throwStatement)
- {
- var createExpression = throwStatement.Expression as ObjectCreateExpression;
- if (createExpression == null)
- return;
- var st = createExpression.Type as SimpleType;
- var mt = createExpression.Type as MemberType;
- if (st != null && st.Identifier == "NotImplementedException" ||
- mt != null && mt.MemberName == "NotImplementedException" && mt.Target.ToString () == "System") {
-
- if (createExpression.Arguments.Any ()) {
- Tags.Add (new Tag ("High", GettextCatalog.GetString ("NotImplementedException({0}) thrown.", createExpression.Arguments.First ().ToString ()), new DomRegion (throwStatement.StartLocation, throwStatement.EndLocation)));
- } else {
- Tags.Add (new Tag ("High", GettextCatalog.GetString ("NotImplementedException thrown."), new DomRegion (throwStatement.StartLocation, throwStatement.EndLocation)));
+ if (curDoc != null) {
+ try {
+ var model = curDoc.GetSemanticModelAsync (cancellationToken).Result;
+ unit = model.SyntaxTree;
+ result.Ast = model;
+ } catch (AggregateException ae) {
+ ae.Flatten ().Handle (x => x is OperationCanceledException);
+ return Task.FromResult ((ParsedDocument)result);
+ } catch (OperationCanceledException) {
+ return Task.FromResult ((ParsedDocument)result);
+ } catch (Exception e) {
+ LoggingService.LogError ("Error while getting the semantic model for " + fileName, e);
}
}
}
- }
- void VisitMcsUnit ()
- {
- }
-
- void VisitComment (ParsedDocument result, SpecialsBag.Comment comment, string[] tagComments)
- {
- var cmt = new MonoDevelop.Ide.TypeSystem.Comment (comment.Content);
- cmt.CommentStartsLine = comment.StartsLine;
- switch (comment.CommentType) {
- case SpecialsBag.CommentType.Multi:
- cmt.CommentType = MonoDevelop.Ide.TypeSystem.CommentType.Block;
- cmt.OpenTag = "/*";
- cmt.ClosingTag = "*/";
- break;
- case SpecialsBag.CommentType.Single:
- cmt.CommentType = MonoDevelop.Ide.TypeSystem.CommentType.SingleLine;
- cmt.OpenTag = "//";
- break;
- case SpecialsBag.CommentType.Documentation:
- cmt.CommentType = MonoDevelop.Ide.TypeSystem.CommentType.Documentation;
- cmt.IsDocumentation = true;
- cmt.OpenTag = "///";
- break;
- }
- cmt.Region = new DomRegion (comment.Line, comment.Col, comment.EndLine, comment.EndCol);
- result.Comments.Add (cmt);
- var trimmedContent = comment.Content.TrimStart ();
- foreach (string tag in tagComments) {
- if (!trimmedContent.StartsWith (tag))
- continue;
- result.Add (new Tag (tag, comment.Content, cmt.Region));
- }
- }
-
- Stack<SpecialsBag.PreProcessorDirective> regions = new Stack<SpecialsBag.PreProcessorDirective> ();
- Stack<SpecialsBag.PreProcessorDirective> ifBlocks = new Stack<SpecialsBag.PreProcessorDirective> ();
- List<SpecialsBag.PreProcessorDirective> elifBlocks = new List<SpecialsBag.PreProcessorDirective> ();
- SpecialsBag.PreProcessorDirective elseBlock = null;
-
- Stack<ConditionalRegion> conditionalRegions = new Stack<ConditionalRegion> ();
- ConditionalRegion ConditionalRegion {
- get {
- return conditionalRegions.Count > 0 ? conditionalRegions.Peek () : null;
- }
- }
+ if (unit == null) {
+ unit = CSharpSyntaxTree.ParseText (SourceText.From (options.Content.Text), compilerArguments, fileName);
+ }
- void CloseConditionBlock (TextLocation loc)
- {
- if (ConditionalRegion == null || ConditionalRegion.ConditionBlocks.Count == 0 || !ConditionalRegion.ConditionBlocks[ConditionalRegion.ConditionBlocks.Count - 1].End.IsEmpty)
- return;
- ConditionalRegion.ConditionBlocks[ConditionalRegion.ConditionBlocks.Count - 1].End = loc;
- }
+ result.Unit = unit;
- void AddCurRegion (ParsedDocument result, int line, int col)
- {
- if (ConditionalRegion == null)
- return;
- ConditionalRegion.End = new TextLocation (line, col);
- result.Add (ConditionalRegion);
- conditionalRegions.Pop ();
- }
-
- void VisitPreprocessorDirective (ParsedDocument result, SpecialsBag.PreProcessorDirective directive)
- {
- TextLocation loc = new TextLocation (directive.Line, directive.Col);
- switch (directive.Cmd) {
- case Tokenizer.PreprocessorDirective.If:
- conditionalRegions.Push (new ConditionalRegion (directive.Arg));
- ifBlocks.Push (directive);
- ConditionalRegion.Start = loc;
- break;
- case Tokenizer.PreprocessorDirective.Elif:
- CloseConditionBlock (new TextLocation (directive.EndLine, directive.EndCol));
- if (ConditionalRegion != null)
- ConditionalRegion.ConditionBlocks.Add (new ConditionBlock (directive.Arg, loc));
- break;
- case Tokenizer.PreprocessorDirective.Else:
- CloseConditionBlock (new TextLocation (directive.EndLine, directive.EndCol));
- if (ConditionalRegion != null)
- ConditionalRegion.ElseBlock = new DomRegion (loc, TextLocation.Empty);
- break;
- case Tokenizer.PreprocessorDirective.Endif:
- TextLocation endLoc = new TextLocation (directive.EndLine, directive.EndCol);
- CloseConditionBlock (endLoc);
- if (ConditionalRegion != null && !ConditionalRegion.ElseBlock.Begin.IsEmpty)
- ConditionalRegion.ElseBlock = new DomRegion (ConditionalRegion.ElseBlock.Begin, endLoc);
- AddCurRegion (result, directive.EndLine, directive.EndCol);
- if (ifBlocks.Count > 0) {
- var ifBlock = ifBlocks.Pop ();
- var ifRegion = new DomRegion (ifBlock.Line, ifBlock.Col, directive.EndLine, directive.EndCol);
- result.Add (new FoldingRegion ("#if " + ifBlock.Arg.Trim (), ifRegion, FoldType.UserRegion, false));
- foreach (var d in elifBlocks) {
- var elIlfRegion = new DomRegion (d.Line, d.Col, directive.EndLine, directive.EndCol);
- result.Add (new FoldingRegion ("#elif " + ifBlock.Arg.Trim (), elIlfRegion, FoldType.UserRegion, false));
- }
- if (elseBlock != null) {
- var elseBlockRegion = new DomRegion (elseBlock.Line, elseBlock.Col, elseBlock.Line, elseBlock.Col);
- result.Add (new FoldingRegion ("#else", elseBlockRegion, FoldType.UserRegion, false));
- }
- }
- elseBlock = null;
- break;
- case Tokenizer.PreprocessorDirective.Define:
- result.Add (new PreProcessorDefine (directive.Arg, loc));
- break;
- case Tokenizer.PreprocessorDirective.Region:
- regions.Push (directive);
- break;
- case Tokenizer.PreprocessorDirective.Endregion:
- if (regions.Count > 0) {
- var start = regions.Pop ();
- DomRegion dr = new DomRegion (start.Line, start.Col, directive.EndLine, directive.EndCol);
- result.Add (new FoldingRegion (start.Arg, dr, FoldType.UserRegion, true));
- }
- break;
+ DateTime time;
+ try {
+ time = System.IO.File.GetLastWriteTimeUtc (fileName);
+ } catch (Exception) {
+ time = DateTime.UtcNow;
}
+ result.LastWriteTimeUtc = time;
+ return Task.FromResult ((ParsedDocument)result);
}
- public static ICSharpCode.NRefactory.CSharp.CompilerSettings GetCompilerArguments (MonoDevelop.Projects.Project project)
+ public static CSharpParseOptions GetCompilerArguments (MonoDevelop.Projects.Project project)
{
- var compilerArguments = new ICSharpCode.NRefactory.CSharp.CompilerSettings ();
+ var compilerArguments = new CSharpParseOptions ();
// compilerArguments.TabSize = 1;
if (project == null || MonoDevelop.Ide.IdeApp.Workspace == null) {
- compilerArguments.AllowUnsafeBlocks = true;
+ // compilerArguments.AllowUnsafeBlocks = true;
return compilerArguments;
}
@@ -401,69 +116,54 @@ namespace MonoDevelop.CSharp.Parser
if (configuration == null)
return compilerArguments;
- foreach (var sym in configuration.GetDefineSymbols ())
- compilerArguments.ConditionalSymbols.Add (sym);
+ compilerArguments = compilerArguments.WithPreprocessorSymbols (configuration.GetDefineSymbols ());
var par = configuration.CompilationParameters as CSharpCompilerParameters;
if (par == null)
return compilerArguments;
-
- compilerArguments.AllowUnsafeBlocks = par.UnsafeCode;
- compilerArguments.LanguageVersion = ConvertLanguageVersion (par.LangVersion);
- compilerArguments.CheckForOverflow = par.GenerateOverflowChecks;
- compilerArguments.WarningLevel = par.WarningLevel;
- compilerArguments.TreatWarningsAsErrors = par.TreatWarningsAsErrors;
- if (!string.IsNullOrEmpty (par.NoWarnings)) {
- foreach (var warning in par.NoWarnings.Split (';', ',', ' ', '\t')) {
- int w;
- try {
- w = int.Parse (warning);
- } catch (Exception) {
- continue;
- }
- compilerArguments.DisabledWarnings.Add (w);
- }
- }
+
+
+ // compilerArguments.AllowUnsafeBlocks = par.UnsafeCode;
+ compilerArguments = compilerArguments.WithLanguageVersion (ConvertLanguageVersion (par.LangVersion));
+// compilerArguments.CheckForOverflow = par.GenerateOverflowChecks;
+
+// compilerArguments.WarningLevel = par.WarningLevel;
+// compilerArguments.TreatWarningsAsErrors = par.TreatWarningsAsErrors;
+// if (!string.IsNullOrEmpty (par.NoWarnings)) {
+// foreach (var warning in par.NoWarnings.Split (';', ',', ' ', '\t')) {
+// int w;
+// try {
+// w = int.Parse (warning);
+// } catch (Exception) {
+// continue;
+// }
+// compilerArguments.DisabledWarnings.Add (w);
+// }
+// }
return compilerArguments;
}
- internal static Version ConvertLanguageVersion (LangVersion ver)
+ internal static Microsoft.CodeAnalysis.CSharp.LanguageVersion ConvertLanguageVersion (LangVersion ver)
{
switch (ver) {
case LangVersion.ISO_1:
- return new Version (1, 0, 0, 0);
+ return Microsoft.CodeAnalysis.CSharp.LanguageVersion.CSharp1;
case LangVersion.ISO_2:
- return new Version (2, 0, 0, 0);
+ return Microsoft.CodeAnalysis.CSharp.LanguageVersion.CSharp2;
case LangVersion.Version3:
- return new Version (3, 0, 0, 0);
+ return Microsoft.CodeAnalysis.CSharp.LanguageVersion.CSharp3;
case LangVersion.Version4:
- return new Version (4, 0, 0, 0);
+ return Microsoft.CodeAnalysis.CSharp.LanguageVersion.CSharp4;
case LangVersion.Version5:
- return new Version (5, 0, 0, 0);
+ return Microsoft.CodeAnalysis.CSharp.LanguageVersion.CSharp5;
case LangVersion.Version6:
- return new Version (6, 0, 0, 0);
+ return Microsoft.CodeAnalysis.CSharp.LanguageVersion.CSharp6;
case LangVersion.Default:
break;
}
- return new Version (6, 0, 0, 0);;
+ return Microsoft.CodeAnalysis.CSharp.LanguageVersion.CSharp6;
}
}
-
- static class FoldingUtils
- {
- public static IEnumerable<FoldingRegion> ToFolds (this IEnumerable<ConditionalRegion> conditionalRegions)
- {
- foreach (ConditionalRegion region in conditionalRegions) {
- yield return new FoldingRegion ("#if " + region.Flag, region.Region, FoldType.ConditionalDefine);
- foreach (ConditionBlock block in region.ConditionBlocks) {
- yield return new FoldingRegion ("#elif " + block.Flag, block.Region,
- FoldType.ConditionalDefine);
- }
- if (!region.ElseBlock.IsEmpty)
- yield return new FoldingRegion ("#else", region.ElseBlock, FoldType.ConditionalDefine);
- }
- }
- }
}