Browse Source

Add folding for Html in .cshtml Razor files.

pull/18/head
Matt Ward 14 years ago
parent
commit
426410f6a6
  1. 4
      src/AddIns/BackendBindings/AspNet.Mvc/Project/AspNet.Mvc.addin
  2. 15
      src/AddIns/BackendBindings/AspNet.Mvc/Project/AspNet.Mvc.csproj
  3. 17
      src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/CSharpRazorLanguageBinding.cs
  4. 17
      src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/CharacterReader.cs
  5. 77
      src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/HtmlFoldParser.cs
  6. 48
      src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/HtmlLanguageBinding.cs
  7. 117
      src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/HtmlReader.cs
  8. 2
      src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/IFoldGeneratorFactory.cs
  9. 12
      src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/IHtmlReaderFactory.cs
  10. 23
      src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/RazorFoldGeneratorFactory.cs
  11. 22
      src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/RazorHtmlFoldParser.cs
  12. 29
      src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/RazorHtmlReader.cs
  13. 19
      src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/RazorHtmlReaderFactory.cs
  14. 55
      src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/RazorHtmlSpans.cs
  15. 22
      src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/RazorMarkupCharacterReader.cs
  16. 95
      src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/SimpleWebFormsHtmlReader.cs
  17. 2
      src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/WebFormsFoldGeneratorFactory.cs
  18. 56
      src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/WebFormsHtmlFoldParser.cs
  19. 15
      src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/WebFormsHtmlReaderFactory.cs
  20. 38
      src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/WebFormsLanguageBinding.cs
  21. 4
      src/AddIns/BackendBindings/AspNet.Mvc/Test/AspNet.Mvc.Tests.csproj
  22. 30
      src/AddIns/BackendBindings/AspNet.Mvc/Test/Src/Folding/CharacterReaderTests.cs
  23. 76
      src/AddIns/BackendBindings/AspNet.Mvc/Test/Src/Folding/RazorHtmlFoldParserTests.cs
  24. 38
      src/AddIns/BackendBindings/AspNet.Mvc/Test/Src/Folding/RazorHtmlReaderTests.cs
  25. 63
      src/AddIns/BackendBindings/AspNet.Mvc/Test/Src/Folding/RazorMarkupCharacterReaderTests.cs
  26. 4
      src/AddIns/BackendBindings/AspNet.Mvc/Test/Src/Folding/WebFormsLanguageBindingTests.cs

4
src/AddIns/BackendBindings/AspNet.Mvc/Project/AspNet.Mvc.addin

@ -91,5 +91,9 @@ @@ -91,5 +91,9 @@
id="WebForms"
class="ICSharpCode.AspNet.Mvc.Folding.WebFormsLanguageBinding"
extensions=".aspx;.ascx;.master;.html;.htm" />
<LanguageBinding
id="CSharp.Razor"
class="ICSharpCode.AspNet.Mvc.Folding.CSharpRazorLanguageBinding"
extensions=".cshtml" />
</Path>
</AddIn>

15
src/AddIns/BackendBindings/AspNet.Mvc/Project/AspNet.Mvc.csproj

@ -36,6 +36,7 @@ @@ -36,6 +36,7 @@
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="System" />
<Reference Include="System.Web.Razor" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
@ -116,14 +117,25 @@ @@ -116,14 +117,25 @@
<Compile Include="Src\DelegateCommand.cs" />
<Compile Include="Src\FileSystem.cs" />
<Compile Include="Src\Folding\CharacterReader.cs" />
<Compile Include="Src\Folding\HtmlFoldParser.cs" />
<Compile Include="Src\Folding\RazorFoldGeneratorFactory.cs" />
<Compile Include="Src\Folding\RazorHtmlFoldParser.cs" />
<Compile Include="Src\Folding\CSharpRazorLanguageBinding.cs" />
<Compile Include="Src\Folding\FoldGenerationTimer.cs" />
<Compile Include="Src\Folding\HtmlElementFold.cs" />
<Compile Include="Src\Folding\HtmlLanguageBinding.cs" />
<Compile Include="Src\Folding\HtmlReader.cs" />
<Compile Include="Src\Folding\IFoldGenerationTimer.cs" />
<Compile Include="Src\Folding\IFoldParser.cs" />
<Compile Include="Src\Folding\IHtmlReaderFactory.cs" />
<Compile Include="Src\Folding\ITextEditorWithParseInformationFolding.cs" />
<Compile Include="Src\Folding\ITextEditorWithParseInformationFoldingFactory.cs" />
<Compile Include="Src\Folding\IFoldGenerator.cs" />
<Compile Include="Src\Folding\IWebFormsFoldGeneratorFactory.cs" />
<Compile Include="Src\Folding\IFoldGeneratorFactory.cs" />
<Compile Include="Src\Folding\RazorHtmlReader.cs" />
<Compile Include="Src\Folding\RazorHtmlReaderFactory.cs" />
<Compile Include="Src\Folding\RazorHtmlSpans.cs" />
<Compile Include="Src\Folding\RazorMarkupCharacterReader.cs" />
<Compile Include="Src\Folding\ScheduledFoldGenerator.cs" />
<Compile Include="Src\Folding\TextEditorWithParseInformationFolding.cs" />
<Compile Include="Src\Folding\TextEditorWithParseInformationFoldingFactory.cs" />
@ -132,6 +144,7 @@ @@ -132,6 +144,7 @@
<Compile Include="Src\Folding\WebFormsHtmlFoldParser.cs" />
<Compile Include="Src\Folding\HtmlNode.cs" />
<Compile Include="Src\Folding\SimpleWebFormsHtmlReader.cs" />
<Compile Include="Src\Folding\WebFormsHtmlReaderFactory.cs" />
<Compile Include="Src\Folding\WebFormsLanguageBinding.cs" />
<Compile Include="Src\IAddMvcItemToProjectView.cs" />
<Compile Include="Src\IFileSystem.cs" />

17
src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/CSharpRazorLanguageBinding.cs

@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
namespace ICSharpCode.AspNet.Mvc.Folding
{
public class CSharpRazorLanguageBinding : HtmlLanguageBinding
{
public CSharpRazorLanguageBinding()
: base(
new TextEditorWithParseInformationFoldingFactory(),
new RazorFoldGeneratorFactory("cshtml"))
{
}
}
}

17
src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/CharacterReader.cs

@ -9,6 +9,7 @@ namespace ICSharpCode.AspNet.Mvc.Folding @@ -9,6 +9,7 @@ namespace ICSharpCode.AspNet.Mvc.Folding
public class CharacterReader
{
public const int EndOfCharacters = -1;
public const int BeforeStartOffset = -1;
TextReader reader;
@ -20,12 +21,13 @@ namespace ICSharpCode.AspNet.Mvc.Folding @@ -20,12 +21,13 @@ namespace ICSharpCode.AspNet.Mvc.Folding
public CharacterReader(TextReader reader)
{
this.reader = reader;
this.CurrentCharacterOffset = BeforeStartOffset;
}
public bool Read()
{
CurrentCharacter = reader.Read();
Offset++;
CurrentCharacterOffset++;
return HasMoreCharactersToRead();
}
@ -34,10 +36,10 @@ namespace ICSharpCode.AspNet.Mvc.Folding @@ -34,10 +36,10 @@ namespace ICSharpCode.AspNet.Mvc.Folding
return CurrentCharacter != EndOfCharacters;
}
public int Offset { get; private set; }
public int CurrentCharacterOffset { get; private set; }
public int PreviousOffset {
get { return Offset - 1; }
public int NextCharacterOffset {
get { return CurrentCharacterOffset + 1; }
}
public int CurrentCharacter { get; private set; }
@ -81,5 +83,12 @@ namespace ICSharpCode.AspNet.Mvc.Folding @@ -81,5 +83,12 @@ namespace ICSharpCode.AspNet.Mvc.Folding
{
return CurrentCharacter == '\'';
}
public void ReadCharacters(int howMany)
{
for (int i = 0; i < howMany; ++i) {
Read();
}
}
}
}

77
src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/HtmlFoldParser.cs

@ -0,0 +1,77 @@ @@ -0,0 +1,77 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.AvalonEdit.Folding;
namespace ICSharpCode.AspNet.Mvc.Folding
{
public class HtmlFoldParser : IFoldParser
{
List<HtmlElementFold> folds = new List<HtmlElementFold>();
Stack<HtmlElementFold> foldStack = new Stack<HtmlElementFold>();
HtmlReader htmlReader;
IHtmlReaderFactory htmlReaderFactory;
public HtmlFoldParser(IHtmlReaderFactory htmlReaderFactory)
{
this.htmlReaderFactory = htmlReaderFactory;
}
public IEnumerable<NewFolding> GetFolds(string html)
{
ClearPreviousFolds();
htmlReader = CreateHtmlReader(html);
while (htmlReader.Read()) {
if (htmlReader.IsEmptyElement) {
// No folds for empty elements.
} else if (htmlReader.IsEndElement) {
AddFoldForCompletedElement();
} else {
SaveFoldStartOnStack();
}
}
SortFoldsByStartOffset();
return folds;
}
void ClearPreviousFolds()
{
folds.Clear();
}
HtmlReader CreateHtmlReader(string html)
{
return htmlReaderFactory.CreateHtmlReader(html);
}
void SaveFoldStartOnStack()
{
var fold = new HtmlElementFold() {
ElementName = htmlReader.Value,
StartOffset = htmlReader.Offset
};
foldStack.Push(fold);
}
void AddFoldForCompletedElement()
{
if (foldStack.Any()) {
var fold = foldStack.Pop();
if (fold.ElementName == htmlReader.Value) {
fold.EndOffset = htmlReader.EndOffset;
folds.Add(fold);
} else {
AddFoldForCompletedElement();
}
}
}
void SortFoldsByStartOffset()
{
folds.Sort((fold1, fold2) => fold1.StartOffset.CompareTo(fold2.StartOffset));
}
}
}

48
src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/HtmlLanguageBinding.cs

@ -0,0 +1,48 @@ @@ -0,0 +1,48 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Editor;
namespace ICSharpCode.AspNet.Mvc.Folding
{
public class HtmlLanguageBinding : DefaultLanguageBinding
{
ITextEditorWithParseInformationFoldingFactory textEditorFactory;
IFoldGeneratorFactory foldGeneratorFactory;
IFoldGenerator foldGenerator;
public HtmlLanguageBinding(
ITextEditorWithParseInformationFoldingFactory textEditorFactory,
IFoldGeneratorFactory foldGeneratorFactory)
{
this.textEditorFactory = textEditorFactory;
this.foldGeneratorFactory = foldGeneratorFactory;
}
public override IFormattingStrategy FormattingStrategy {
get { return new DefaultFormattingStrategy(); }
}
public override LanguageProperties Properties {
get { return LanguageProperties.None; }
}
public override void Attach(ITextEditor editor)
{
Attach(textEditorFactory.CreateTextEditor(editor));
}
void Attach(ITextEditorWithParseInformationFolding editor)
{
foldGenerator = foldGeneratorFactory.CreateFoldGenerator(editor);
}
public override void Detach()
{
foldGenerator.Dispose();
}
}
}

117
src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/HtmlReader.cs

@ -0,0 +1,117 @@ @@ -0,0 +1,117 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.IO;
namespace ICSharpCode.AspNet.Mvc.Folding
{
public class HtmlReader
{
CharacterReader reader;
HtmlNode currentNode = new HtmlNode();
public HtmlReader(string html)
: this(new StringReader(html))
{
}
public HtmlReader(TextReader reader)
: this(new CharacterReader(reader))
{
}
public HtmlReader(CharacterReader reader)
{
this.reader = reader;
}
public string Value {
get { return currentNode.Value; }
}
public int Offset { get; private set; }
public int Length { get; private set; }
public int EndOffset {
get { return Offset + Length; }
}
public bool IsEmptyElement { get; private set; }
public bool IsEndElement { get; private set; }
public bool IsStartElement {
get { return !IsEndElement; }
}
public bool Read()
{
while (ReadNextCharacter()) {
if (!IsHtml()) {
// Skip character
} else if (IsElementStartCharacter()) {
currentNode = new HtmlNode();
IsEndElement = reader.IsNextCharacterForwardSlash();
IsEmptyElement = false;
Offset = reader.CurrentCharacterOffset;
} else if (IsElementEndCharacter()) {
Length = reader.NextCharacterOffset - Offset;
return true;
} else if (reader.IsForwardSlash()) {
IsEmptyElement = !IsEndElement;
} else if (IsElementNameCharacter()) {
currentNode.Append(reader.CurrentCharacter);
} else if (reader.IsDoubleQuote()) {
ReadDoubleQuotedString();
} else if (reader.IsSingleQuote()) {
ReadSingleQuotedString();
}
}
return false;
}
protected virtual bool IsHtml()
{
return true;
}
bool ReadNextCharacter()
{
return reader.Read();
}
bool IsElementStartCharacter()
{
return reader.IsLessThanSign();
}
bool IsElementEndCharacter()
{
return reader.IsGreaterThanSign();
}
bool IsElementNameCharacter()
{
return reader.IsLetterOrDigit() || reader.IsSpace();
}
void ReadDoubleQuotedString()
{
ReadUntil(() => reader.IsDoubleQuote());
}
void ReadUntil(Func<bool> match)
{
while (ReadNextCharacter()) {
if (match()) {
return;
}
}
}
void ReadSingleQuotedString()
{
ReadUntil(() => reader.IsSingleQuote());
}
}
}

2
src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/IWebFormsFoldGeneratorFactory.cs → src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/IFoldGeneratorFactory.cs

@ -5,7 +5,7 @@ using System; @@ -5,7 +5,7 @@ using System;
namespace ICSharpCode.AspNet.Mvc.Folding
{
public interface IWebFormsFoldGeneratorFactory
public interface IFoldGeneratorFactory
{
IFoldGenerator CreateFoldGenerator(ITextEditorWithParseInformationFolding textEditor);
}

12
src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/IHtmlReaderFactory.cs

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
namespace ICSharpCode.AspNet.Mvc.Folding
{
public interface IHtmlReaderFactory
{
HtmlReader CreateHtmlReader(string html);
}
}

23
src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/RazorFoldGeneratorFactory.cs

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
namespace ICSharpCode.AspNet.Mvc.Folding
{
public class RazorFoldGeneratorFactory : IFoldGeneratorFactory
{
public RazorFoldGeneratorFactory(string extension)
{
this.Extension = extension;
}
string Extension { get; set; }
public IFoldGenerator CreateFoldGenerator(ITextEditorWithParseInformationFolding textEditor)
{
return new ScheduledFoldGenerator(
new FoldGenerator(textEditor, new RazorHtmlFoldParser(Extension)));
}
}
}

22
src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/RazorHtmlFoldParser.cs

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using ICSharpCode.AvalonEdit.Folding;
namespace ICSharpCode.AspNet.Mvc.Folding
{
public class RazorHtmlFoldParser : HtmlFoldParser
{
public RazorHtmlFoldParser(string extension)
: this(new RazorHtmlReaderFactory(extension))
{
}
public RazorHtmlFoldParser(RazorHtmlReaderFactory htmlReaderFactory)
: base(htmlReaderFactory)
{
}
}
}

29
src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/RazorHtmlReader.cs

@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.IO;
namespace ICSharpCode.AspNet.Mvc.Folding
{
public class RazorHtmlReader : HtmlReader
{
RazorMarkupCharacterReader reader;
public RazorHtmlReader(string html)
: this(new RazorMarkupCharacterReader(html))
{
}
public RazorHtmlReader(RazorMarkupCharacterReader reader)
: base(reader)
{
this.reader = reader;
}
protected override bool IsHtml()
{
return reader.IsHtml;
}
}
}

19
src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/RazorHtmlReaderFactory.cs

@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
namespace ICSharpCode.AspNet.Mvc.Folding
{
public class RazorHtmlReaderFactory : IHtmlReaderFactory
{
public RazorHtmlReaderFactory(string extension)
{
}
public HtmlReader CreateHtmlReader(string html)
{
return new RazorHtmlReader(html);
}
}
}

55
src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/RazorHtmlSpans.cs

@ -0,0 +1,55 @@ @@ -0,0 +1,55 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.IO;
using System.Web.Razor;
using System.Web.Razor.Parser.SyntaxTree;
using System.Web.Razor.Text;
namespace ICSharpCode.AspNet.Mvc.Folding
{
public class RazorHtmlSpans
{
List<Span> spans;
public RazorHtmlSpans(string html)
{
ReadHtmlSpans(html);
}
void ReadHtmlSpans(string html)
{
RazorEngineHost razorEngineHost = new RazorEngineHost(RazorCodeLanguage.GetLanguageByExtension(".cshtml"));
RazorTemplateEngine engine = new RazorTemplateEngine(razorEngineHost);
ParserResults results = engine.ParseTemplate(new StringReader(html));
spans = new List<Span>(results.Document.Flatten());
spans.RemoveAll(span => span.Kind != SpanKind.Markup);
}
public bool IsHtml(int offset)
{
if (offset >= 0) {
return HtmlSpansContainOffset(offset);
}
return true;
}
bool HtmlSpansContainOffset(int offset)
{
foreach (Span span in spans) {
if (IsInSpan(span, offset)) {
return true;
}
}
return false;
}
bool IsInSpan(Span span, int offset)
{
int spanOffset = span.Start.AbsoluteIndex;
return (offset >= spanOffset) && (offset < spanOffset + span.Length);
}
}
}

22
src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/RazorMarkupCharacterReader.cs

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
namespace ICSharpCode.AspNet.Mvc.Folding
{
public class RazorMarkupCharacterReader : CharacterReader
{
RazorHtmlSpans htmlSpans;
public RazorMarkupCharacterReader(string html)
: base(html)
{
htmlSpans = new RazorHtmlSpans(html);
}
public bool IsHtml {
get { return htmlSpans.IsHtml(CurrentCharacterOffset); }
}
}
}

95
src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/SimpleWebFormsHtmlReader.cs

@ -7,105 +7,16 @@ using System.Text; @@ -7,105 +7,16 @@ using System.Text;
namespace ICSharpCode.AspNet.Mvc.Folding
{
public class SimpleWebFormsHtmlReader
public class SimpleWebFormsHtmlReader : HtmlReader
{
CharacterReader reader;
HtmlNode currentNode = new HtmlNode();
public SimpleWebFormsHtmlReader(string html)
: this(new StringReader(html))
{
}
public SimpleWebFormsHtmlReader(TextReader reader)
: this(new CharacterReader(reader))
: this(new CharacterReader(html))
{
}
public SimpleWebFormsHtmlReader(CharacterReader reader)
: base(reader)
{
this.reader = reader;
}
public string Value {
get { return currentNode.Value; }
}
public int Offset { get; private set; }
public int Length { get; private set; }
public int EndOffset {
get { return Offset + Length; }
}
public bool IsEmptyElement { get; private set; }
public bool IsEndElement { get; private set; }
public bool IsStartElement {
get { return !IsEndElement; }
}
public bool Read()
{
while (ReadNextCharacter()) {
if (IsElementStartCharacter()) {
currentNode = new HtmlNode();
IsEndElement = reader.IsNextCharacterForwardSlash();
IsEmptyElement = false;
Offset = reader.PreviousOffset;
} else if (IsElementEndCharacter()) {
Length = reader.Offset - Offset;
return true;
} else if (reader.IsForwardSlash()) {
IsEmptyElement = !IsEndElement;
} else if (IsElementNameCharacter()) {
currentNode.Append(reader.CurrentCharacter);
} else if (reader.IsDoubleQuote()) {
ReadDoubleQuotedString();
} else if (reader.IsSingleQuote()) {
ReadSingleQuotedString();
}
}
return false;
}
bool ReadNextCharacter()
{
return reader.Read();
}
bool IsElementStartCharacter()
{
return reader.IsLessThanSign();
}
bool IsElementEndCharacter()
{
return reader.IsGreaterThanSign();
}
bool IsElementNameCharacter()
{
return reader.IsLetterOrDigit() || reader.IsSpace();
}
void ReadDoubleQuotedString()
{
ReadUntil(() => reader.IsDoubleQuote());
}
void ReadUntil(Func<bool> match)
{
while (ReadNextCharacter()) {
if (match()) {
return;
}
}
}
void ReadSingleQuotedString()
{
ReadUntil(() => reader.IsSingleQuote());
}
}
}

2
src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/WebFormsFoldGeneratorFactory.cs

@ -5,7 +5,7 @@ using System; @@ -5,7 +5,7 @@ using System;
namespace ICSharpCode.AspNet.Mvc.Folding
{
public class WebFormsFoldGeneratorFactory : IWebFormsFoldGeneratorFactory
public class WebFormsFoldGeneratorFactory : IFoldGeneratorFactory
{
public IFoldGenerator CreateFoldGenerator(ITextEditorWithParseInformationFolding textEditor)
{

56
src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/WebFormsHtmlFoldParser.cs

@ -2,65 +2,19 @@ @@ -2,65 +2,19 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.AvalonEdit.Folding;
namespace ICSharpCode.AspNet.Mvc.Folding
{
public class WebFormsHtmlFoldParser : IFoldParser
public class WebFormsHtmlFoldParser : HtmlFoldParser
{
List<HtmlElementFold> folds = new List<HtmlElementFold>();
Stack<HtmlElementFold> foldStack = new Stack<HtmlElementFold>();
SimpleWebFormsHtmlReader htmlReader;
public IEnumerable<NewFolding> GetFolds(string html)
{
ClearPreviousFolds();
htmlReader = new SimpleWebFormsHtmlReader(html);
while (htmlReader.Read()) {
if (htmlReader.IsEmptyElement) {
// No folds for empty elements.
} else if (htmlReader.IsEndElement) {
AddFoldForCompletedElement();
} else {
SaveFoldStartOnStack();
}
}
SortFoldsByStartOffset();
return folds;
}
void ClearPreviousFolds()
{
folds.Clear();
}
void SaveFoldStartOnStack()
{
var fold = new HtmlElementFold() {
ElementName = htmlReader.Value,
StartOffset = htmlReader.Offset
};
foldStack.Push(fold);
}
void AddFoldForCompletedElement()
public WebFormsHtmlFoldParser(IHtmlReaderFactory htmlReaderFactory)
: base(htmlReaderFactory)
{
if (foldStack.Any()) {
var fold = foldStack.Pop();
if (fold.ElementName == htmlReader.Value) {
fold.EndOffset = htmlReader.EndOffset;
folds.Add(fold);
} else {
AddFoldForCompletedElement();
}
}
}
void SortFoldsByStartOffset()
public WebFormsHtmlFoldParser()
: this(new WebFormsHtmlReaderFactory())
{
folds.Sort((fold1, fold2) => fold1.StartOffset.CompareTo(fold2.StartOffset));
}
}
}

15
src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/WebFormsHtmlReaderFactory.cs

@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
namespace ICSharpCode.AspNet.Mvc.Folding
{
public class WebFormsHtmlReaderFactory : IHtmlReaderFactory
{
public HtmlReader CreateHtmlReader(string html)
{
return new SimpleWebFormsHtmlReader(html);
}
}
}

38
src/AddIns/BackendBindings/AspNet.Mvc/Project/Src/Folding/WebFormsLanguageBinding.cs

@ -3,19 +3,13 @@ @@ -3,19 +3,13 @@
using System;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Editor;
namespace ICSharpCode.AspNet.Mvc.Folding
{
public class WebFormsLanguageBinding : DefaultLanguageBinding
public class WebFormsLanguageBinding : HtmlLanguageBinding
{
ITextEditorWithParseInformationFoldingFactory textEditorFactory;
IWebFormsFoldGeneratorFactory foldGeneratorFactory;
IFoldGenerator foldGenerator;
public WebFormsLanguageBinding()
: this(
: base(
new TextEditorWithParseInformationFoldingFactory(),
new WebFormsFoldGeneratorFactory())
{
@ -23,33 +17,9 @@ namespace ICSharpCode.AspNet.Mvc.Folding @@ -23,33 +17,9 @@ namespace ICSharpCode.AspNet.Mvc.Folding
public WebFormsLanguageBinding(
ITextEditorWithParseInformationFoldingFactory textEditorFactory,
IWebFormsFoldGeneratorFactory foldGeneratorFactory)
{
this.textEditorFactory = textEditorFactory;
this.foldGeneratorFactory = foldGeneratorFactory;
}
public override IFormattingStrategy FormattingStrategy {
get { return new DefaultFormattingStrategy(); }
}
public override LanguageProperties Properties {
get { return LanguageProperties.None; }
}
public override void Attach(ITextEditor editor)
{
Attach(textEditorFactory.CreateTextEditor(editor));
}
void Attach(ITextEditorWithParseInformationFolding editor)
{
foldGenerator = foldGeneratorFactory.CreateFoldGenerator(editor);
}
public override void Detach()
IFoldGeneratorFactory foldGeneratorFactory)
: base(textEditorFactory, foldGeneratorFactory)
{
foldGenerator.Dispose();
}
}
}

4
src/AddIns/BackendBindings/AspNet.Mvc/Test/AspNet.Mvc.Tests.csproj

@ -112,7 +112,11 @@ @@ -112,7 +112,11 @@
<Compile Include="Src\CodeTemplates\RazorCSharpEditViewTemplateTests.cs" />
<Compile Include="Src\CodeTemplates\RazorCSharpEmptyViewTemplateTests.cs" />
<Compile Include="Src\CodeTemplates\RazorCSharpListViewTemplateTests.cs" />
<Compile Include="Src\Folding\CharacterReaderTests.cs" />
<Compile Include="Src\Folding\RazorHtmlFoldParserTests.cs" />
<Compile Include="Src\Folding\HtmlElementFoldTests.cs" />
<Compile Include="Src\Folding\RazorHtmlReaderTests.cs" />
<Compile Include="Src\Folding\RazorMarkupCharacterReaderTests.cs" />
<Compile Include="Src\Folding\ScheduledFoldGeneratorTests.cs" />
<Compile Include="Src\Folding\FoldGeneratorTests.cs" />
<Compile Include="Src\Folding\WebFormsHtmlFoldParserTests.cs" />

30
src/AddIns/BackendBindings/AspNet.Mvc/Test/Src/Folding/CharacterReaderTests.cs

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using ICSharpCode.AspNet.Mvc.Folding;
using NUnit.Framework;
namespace AspNet.Mvc.Tests.Folding
{
[TestFixture]
public class CharacterReaderTests
{
CharacterReader reader;
void CreateReader(string html)
{
reader = new CharacterReader(html);
}
[Test]
public void ReadCharacters_ReadTwoCharacters_SecondCharacterIsCurrentCharacter()
{
CreateReader("12345");
reader.ReadCharacters(2);
Assert.AreEqual('2', reader.CurrentCharacter);
}
}
}

76
src/AddIns/BackendBindings/AspNet.Mvc/Test/Src/Folding/RazorHtmlFoldParserTests.cs

@ -0,0 +1,76 @@ @@ -0,0 +1,76 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.AspNet.Mvc.Folding;
using ICSharpCode.AvalonEdit.Folding;
using NUnit.Framework;
namespace AspNet.Mvc.Tests.Folding
{
[TestFixture]
public class RazorHtmlFoldParserTests
{
RazorHtmlFoldParser parser;
List<NewFolding> folds;
void CreateCSharpParser()
{
parser = new RazorHtmlFoldParser("cshtml");
}
void GetFolds(string text)
{
folds = parser.GetFolds(text).ToList();
}
[Test]
public void GetFolds_ParagraphStartAndEndTag_ReturnsOneFoldForParagraphTag()
{
CreateCSharpParser();
string text =
"<p>\r\n" +
"</p>";
GetFolds(text);
var expectedFolds = new HtmlElementFold[] {
new HtmlElementFold() {
ElementName = "p",
StartOffset = 0,
EndOffset = 9
}
};
CollectionAssert.AreEqual(expectedFolds, folds);
}
[Test]
public void GetFolds_EndAnchorTagInsideIfStatement_ReturnsOneFoldForParagraphTagAndNotAnchorTag()
{
CreateCSharpParser();
string text =
"@if (i<a || b>i) {\r\n" +
" </a>\r\n" +
" <p></p>\r\n" +
"}\r\n";
GetFolds(text);
var expectedFolds = new HtmlElementFold[] {
new HtmlElementFold() {
ElementName = "p",
StartOffset = 34,
EndOffset = 41
}
};
CollectionAssert.AreEqual(expectedFolds, folds);
}
}
}

38
src/AddIns/BackendBindings/AspNet.Mvc/Test/Src/Folding/RazorHtmlReaderTests.cs

@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using ICSharpCode.AspNet.Mvc.Folding;
using NUnit.Framework;
namespace AspNet.Mvc.Tests.Folding
{
[TestFixture]
public class RazorHtmlReaderTests
{
RazorHtmlReader htmlReader;
void CreateHtmlReader(string html)
{
htmlReader = new RazorHtmlReader(html);
}
[Test]
public void Value_ReadFirstParagraphTagInsideIfStatementWithLessThanSign_ReturnsParagraphTagName()
{
string html =
"@if (i<a || b>i) {\r\n" +
" <p></p>\r\n" +
"}\r\n";
CreateHtmlReader(html);
htmlReader.Read();
string value = htmlReader.Value;
Assert.AreEqual("p", value);
}
}
}

63
src/AddIns/BackendBindings/AspNet.Mvc/Test/Src/Folding/RazorMarkupCharacterReaderTests.cs

@ -0,0 +1,63 @@ @@ -0,0 +1,63 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using ICSharpCode.AspNet.Mvc.Folding;
using NUnit.Framework;
namespace AspNet.Mvc.Tests.Folding
{
[TestFixture]
public class RazorMarkupCharacterReaderTests
{
RazorMarkupCharacterReader reader;
void CreateReader(string html)
{
reader = new RazorMarkupCharacterReader(html);
}
[Test]
public void IsHtml_CurrentCharacterIsAtStartOfHtml_ReturnsTrue()
{
CreateReader("<br/>");
bool htmlCharacterRead = reader.IsHtml;
Assert.IsTrue(htmlCharacterRead);
}
[Test]
public void IsHtml_FirstCharacterReadIsRazorTransitionSymbol_ReturnsFalse()
{
CreateReader("@model");
reader.Read();
bool result = reader.IsHtml;
Assert.IsFalse(result);
}
[Test]
public void IsHtml_ReadFirstRazorTransitionSymbolAfterParagraphTag_ReturnsFalse()
{
CreateReader("<p>@model.Message</p>");
reader.ReadCharacters(4);
bool htmlCharacterRead = reader.IsHtml;
Assert.IsFalse(htmlCharacterRead);
}
[Test]
public void IsHtml_ReadFirstCharacterAfterRazorTransitionSymbol_ReturnsFalse()
{
CreateReader("<p>@model.Message</p>");
reader.ReadCharacters(5);
bool htmlCharacterRead = reader.IsHtml;
Assert.IsFalse(htmlCharacterRead);
}
}
}

4
src/AddIns/BackendBindings/AspNet.Mvc/Test/Src/Folding/WebFormsLanguageBindingTests.cs

@ -17,7 +17,7 @@ namespace AspNet.Mvc.Tests.Folding @@ -17,7 +17,7 @@ namespace AspNet.Mvc.Tests.Folding
WebFormsLanguageBinding languageBinding;
ITextEditor fakeTextEditor;
ITextEditorWithParseInformationFoldingFactory fakeTextEditorFactory;
IWebFormsFoldGeneratorFactory fakeFoldGeneratorFactory;
IFoldGeneratorFactory fakeFoldGeneratorFactory;
IFoldGenerator fakeFoldGenerator;
[SetUp]
@ -39,7 +39,7 @@ namespace AspNet.Mvc.Tests.Folding @@ -39,7 +39,7 @@ namespace AspNet.Mvc.Tests.Folding
void CreateFakeFoldGeneratorFactory()
{
fakeFoldGeneratorFactory = MockRepository.GenerateStub<IWebFormsFoldGeneratorFactory>();
fakeFoldGeneratorFactory = MockRepository.GenerateStub<IFoldGeneratorFactory>();
}
void AddFakeFoldGeneratorToFactory()

Loading…
Cancel
Save