Add tests from AvalonEdit (#49)
This commit is contained in:
Родитель
e21a08982f
Коммит
2caf1679fa
|
@ -7,6 +7,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AvaloniaEdit", "src\Avaloni
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AvaloniaEdit.Demo", "src\AvaloniaEdit.Demo\AvaloniaEdit.Demo.csproj", "{03763F37-9BD9-4D1D-ADC9-1050F6F8C062}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AvaloniaEdit.Tests", "test\AvaloniaEdit.Tests\AvaloniaEdit.Tests.csproj", "{9E5D4372-D362-44A2-984D-578288870AB8}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -31,6 +33,14 @@ Global
|
|||
{03763F37-9BD9-4D1D-ADC9-1050F6F8C062}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{03763F37-9BD9-4D1D-ADC9-1050F6F8C062}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{03763F37-9BD9-4D1D-ADC9-1050F6F8C062}.Release|x64.Build.0 = Release|Any CPU
|
||||
{9E5D4372-D362-44A2-984D-578288870AB8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9E5D4372-D362-44A2-984D-578288870AB8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9E5D4372-D362-44A2-984D-578288870AB8}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{9E5D4372-D362-44A2-984D-578288870AB8}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{9E5D4372-D362-44A2-984D-578288870AB8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9E5D4372-D362-44A2-984D-578288870AB8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9E5D4372-D362-44A2-984D-578288870AB8}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{9E5D4372-D362-44A2-984D-578288870AB8}.Release|x64.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
using Avalonia.Metadata;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Avalonia.Metadata;
|
||||
|
||||
[assembly: XmlnsDefinition("https://github.com/avaloniaui/avaloniaedit", "AvaloniaEdit")]
|
||||
[assembly: XmlnsDefinition("https://github.com/avaloniaui/avaloniaedit", "AvaloniaEdit.Editing")]
|
||||
[assembly: XmlnsDefinition("https://github.com/avaloniaui/avaloniaedit", "AvaloniaEdit.Rendering")]
|
||||
[assembly: XmlnsDefinition("https://github.com/avaloniaui/avaloniaedit", "AvaloniaEdit.Highlighting")]
|
||||
[assembly: XmlnsDefinition("https://github.com/avaloniaui/avaloniaedit", "AvaloniaEdit.Search")]
|
||||
|
||||
[assembly: InternalsVisibleTo("AvaloniaEdit.Tests")]
|
||||
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.1" />
|
||||
<PackageReference Include="Moq" Version="4.10.1" />
|
||||
<PackageReference Include="NUnit" Version="3.11.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.13.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\AvaloniaEdit\AvaloniaEdit.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,70 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Avalonia;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Platform;
|
||||
using Moq;
|
||||
|
||||
namespace AvaloniaEdit.AvaloniaMocks
|
||||
{
|
||||
public class MockPlatformRenderInterface : IPlatformRenderInterface
|
||||
{
|
||||
public IEnumerable<string> InstalledFontNames => throw new NotImplementedException();
|
||||
|
||||
public IFormattedTextImpl CreateFormattedText(
|
||||
string text,
|
||||
Typeface typeface,
|
||||
TextAlignment textAlignment,
|
||||
TextWrapping wrapping,
|
||||
Size constraint,
|
||||
IReadOnlyList<FormattedTextStyleSpan> spans)
|
||||
{
|
||||
return Mock.Of<IFormattedTextImpl>();
|
||||
}
|
||||
|
||||
public IRenderTarget CreateRenderTarget(IEnumerable<object> surfaces)
|
||||
{
|
||||
return Mock.Of<IRenderTarget>();
|
||||
}
|
||||
|
||||
public IRenderTargetBitmapImpl CreateRenderTargetBitmap(
|
||||
int width,
|
||||
int height,
|
||||
double dpiX,
|
||||
double dpiY)
|
||||
{
|
||||
return Mock.Of<IRenderTargetBitmapImpl>();
|
||||
}
|
||||
|
||||
public IRenderTargetBitmapImpl CreateRenderTargetBitmap(PixelSize size, Vector dpi)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IStreamGeometryImpl CreateStreamGeometry()
|
||||
{
|
||||
return new MockStreamGeometryImpl();
|
||||
}
|
||||
|
||||
public IWriteableBitmapImpl CreateWriteableBitmap(PixelSize size, Vector dpi, PixelFormat? format = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IBitmapImpl LoadBitmap(Stream stream)
|
||||
{
|
||||
return Mock.Of<IBitmapImpl>();
|
||||
}
|
||||
|
||||
public IBitmapImpl LoadBitmap(string fileName)
|
||||
{
|
||||
return Mock.Of<IBitmapImpl>();
|
||||
}
|
||||
|
||||
public IBitmapImpl LoadBitmap(PixelFormat format, IntPtr data, PixelSize size, Vector dpi, int stride)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Avalonia;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Platform;
|
||||
|
||||
namespace AvaloniaEdit.AvaloniaMocks
|
||||
{
|
||||
public class MockStreamGeometryImpl : IStreamGeometryImpl, ITransformedGeometryImpl
|
||||
{
|
||||
private MockStreamGeometryContext _context;
|
||||
|
||||
public MockStreamGeometryImpl()
|
||||
{
|
||||
Transform = Matrix.Identity;
|
||||
_context = new MockStreamGeometryContext();
|
||||
}
|
||||
|
||||
public MockStreamGeometryImpl(Matrix transform)
|
||||
{
|
||||
Transform = transform;
|
||||
_context = new MockStreamGeometryContext();
|
||||
}
|
||||
|
||||
private MockStreamGeometryImpl(Matrix transform, MockStreamGeometryContext context)
|
||||
{
|
||||
Transform = transform;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public IGeometryImpl SourceGeometry { get; }
|
||||
|
||||
public Rect Bounds => _context.CalculateBounds();
|
||||
|
||||
public Matrix Transform { get; }
|
||||
|
||||
public IStreamGeometryImpl Clone()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public bool FillContains(Point point)
|
||||
{
|
||||
return _context.FillContains(point);
|
||||
}
|
||||
|
||||
public bool StrokeContains(Pen pen, Point point)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public Rect GetRenderBounds(Pen pen) => Bounds;
|
||||
|
||||
public IGeometryImpl Intersect(IGeometryImpl geometry)
|
||||
{
|
||||
return new MockStreamGeometryImpl(Transform);
|
||||
}
|
||||
|
||||
public IStreamGeometryContextImpl Open()
|
||||
{
|
||||
return _context;
|
||||
}
|
||||
|
||||
public ITransformedGeometryImpl WithTransform(Matrix transform)
|
||||
{
|
||||
return new MockStreamGeometryImpl(transform, _context);
|
||||
}
|
||||
|
||||
class MockStreamGeometryContext : IStreamGeometryContextImpl
|
||||
{
|
||||
private List<Point> points = new List<Point>();
|
||||
public void ArcTo(Point point, Size size, double rotationAngle, bool isLargeArc, SweepDirection sweepDirection)
|
||||
{
|
||||
}
|
||||
|
||||
public void BeginFigure(Point startPoint, bool isFilled)
|
||||
{
|
||||
points.Add(startPoint);
|
||||
}
|
||||
|
||||
public Rect CalculateBounds()
|
||||
{
|
||||
var left = double.MaxValue;
|
||||
var right = double.MinValue;
|
||||
var top = double.MaxValue;
|
||||
var bottom = double.MinValue;
|
||||
|
||||
foreach (var p in points)
|
||||
{
|
||||
left = Math.Min(p.X, left);
|
||||
right = Math.Max(p.X, right);
|
||||
top = Math.Min(p.Y, top);
|
||||
bottom = Math.Max(p.Y, bottom);
|
||||
}
|
||||
|
||||
return new Rect(new Point(left, top), new Point(right, bottom));
|
||||
}
|
||||
|
||||
public void CubicBezierTo(Point point1, Point point2, Point point3)
|
||||
{
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public void EndFigure(bool isClosed)
|
||||
{
|
||||
}
|
||||
|
||||
public void LineTo(Point point)
|
||||
{
|
||||
points.Add(point);
|
||||
}
|
||||
|
||||
public void QuadraticBezierTo(Point control, Point endPoint)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void SetFillRule(FillRule fillRule)
|
||||
{
|
||||
}
|
||||
|
||||
public bool FillContains(Point point)
|
||||
{
|
||||
// Use the algorithm from http://www.blackpawn.com/texts/pointinpoly/default.html
|
||||
// to determine if the point is in the geometry (since it will always be convex in this situation)
|
||||
for (int i = 0; i < points.Count; i++)
|
||||
{
|
||||
var a = points[i];
|
||||
var b = points[(i + 1) % points.Count];
|
||||
var c = points[(i + 2) % points.Count];
|
||||
|
||||
Vector v0 = c - a;
|
||||
Vector v1 = b - a;
|
||||
Vector v2 = point - a;
|
||||
|
||||
var dot00 = v0 * v0;
|
||||
var dot01 = v0 * v1;
|
||||
var dot02 = v0 * v2;
|
||||
var dot11 = v1 * v1;
|
||||
var dot12 = v1 * v2;
|
||||
|
||||
|
||||
var invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
|
||||
var u = (dot11 * dot02 - dot01 * dot12) * invDenom;
|
||||
var v = (dot00 * dot12 - dot01 * dot02) * invDenom;
|
||||
if ((u >= 0) && (v >= 0) && (u + v < 1)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
using System;
|
||||
using Avalonia.Platform;
|
||||
using Moq;
|
||||
|
||||
namespace AvaloniaEdit.AvaloniaMocks
|
||||
{
|
||||
public class MockWindowingPlatform : IWindowingPlatform
|
||||
{
|
||||
private readonly Func<IWindowImpl> _windowImpl;
|
||||
private readonly Func<IPopupImpl> _popupImpl;
|
||||
|
||||
public MockWindowingPlatform(Func<IWindowImpl> windowImpl = null, Func<IPopupImpl> popupImpl = null)
|
||||
{
|
||||
_windowImpl = windowImpl;
|
||||
_popupImpl = popupImpl;
|
||||
}
|
||||
|
||||
public IWindowImpl CreateWindow()
|
||||
{
|
||||
return _windowImpl?.Invoke() ?? Mock.Of<IWindowImpl>(x => x.Scaling == 1);
|
||||
}
|
||||
|
||||
public IEmbeddableWindowImpl CreateEmbeddableWindow()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IPopupImpl CreatePopup() => _popupImpl?.Invoke() ?? Mock.Of<IPopupImpl>(x => x.Scaling == 1);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reactive.Concurrency;
|
||||
using Avalonia;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.Rendering;
|
||||
using Avalonia.Shared.PlatformSupport;
|
||||
using Avalonia.Styling;
|
||||
using Avalonia.Themes.Default;
|
||||
using Moq;
|
||||
|
||||
namespace AvaloniaEdit.AvaloniaMocks
|
||||
{
|
||||
public class TestServices
|
||||
{
|
||||
public static readonly TestServices StyledWindow = new TestServices(
|
||||
assetLoader: new AssetLoader(),
|
||||
layoutManager: new LayoutManager(),
|
||||
platform: new AppBuilder().RuntimePlatform,
|
||||
renderInterface: new MockPlatformRenderInterface(),
|
||||
standardCursorFactory: Mock.Of<IStandardCursorFactory>(),
|
||||
styler: new Styler(),
|
||||
theme: () => CreateDefaultTheme(),
|
||||
threadingInterface: Mock.Of<IPlatformThreadingInterface>(x => x.CurrentThreadIsLoopThread == true),
|
||||
windowingPlatform: new MockWindowingPlatform());
|
||||
|
||||
public static readonly TestServices MockPlatformRenderInterface = new TestServices(
|
||||
renderInterface: new MockPlatformRenderInterface());
|
||||
|
||||
public static readonly TestServices MockPlatformWrapper = new TestServices(
|
||||
platform: Mock.Of<IRuntimePlatform>());
|
||||
|
||||
public static readonly TestServices MockStyler = new TestServices(
|
||||
styler: Mock.Of<IStyler>());
|
||||
|
||||
public static readonly TestServices MockThreadingInterface = new TestServices(
|
||||
threadingInterface: Mock.Of<IPlatformThreadingInterface>(x => x.CurrentThreadIsLoopThread == true));
|
||||
|
||||
public static readonly TestServices MockWindowingPlatform = new TestServices(
|
||||
windowingPlatform: new MockWindowingPlatform());
|
||||
|
||||
public static readonly TestServices RealFocus = new TestServices(
|
||||
focusManager: new FocusManager(),
|
||||
keyboardDevice: () => new KeyboardDevice(),
|
||||
keyboardNavigation: new KeyboardNavigationHandler(),
|
||||
inputManager: new InputManager());
|
||||
|
||||
public static readonly TestServices RealLayoutManager = new TestServices(
|
||||
layoutManager: new LayoutManager());
|
||||
|
||||
public static readonly TestServices RealStyler = new TestServices(
|
||||
styler: new Styler());
|
||||
|
||||
public TestServices(
|
||||
IAssetLoader assetLoader = null,
|
||||
IFocusManager focusManager = null,
|
||||
IInputManager inputManager = null,
|
||||
Func<IKeyboardDevice> keyboardDevice = null,
|
||||
IKeyboardNavigationHandler keyboardNavigation = null,
|
||||
ILayoutManager layoutManager = null,
|
||||
Func<IMouseDevice> mouseDevice = null,
|
||||
IRuntimePlatform platform = null,
|
||||
IPlatformRenderInterface renderInterface = null,
|
||||
IRenderLoop renderLoop = null,
|
||||
IScheduler scheduler = null,
|
||||
IStandardCursorFactory standardCursorFactory = null,
|
||||
IStyler styler = null,
|
||||
Func<Styles> theme = null,
|
||||
IPlatformThreadingInterface threadingInterface = null,
|
||||
IWindowImpl windowImpl = null,
|
||||
IWindowingPlatform windowingPlatform = null)
|
||||
{
|
||||
AssetLoader = assetLoader;
|
||||
FocusManager = focusManager;
|
||||
InputManager = inputManager;
|
||||
KeyboardDevice = keyboardDevice;
|
||||
KeyboardNavigation = keyboardNavigation;
|
||||
LayoutManager = layoutManager;
|
||||
MouseDevice = mouseDevice;
|
||||
Platform = platform;
|
||||
RenderInterface = renderInterface;
|
||||
Scheduler = scheduler;
|
||||
StandardCursorFactory = standardCursorFactory;
|
||||
Styler = styler;
|
||||
Theme = theme;
|
||||
ThreadingInterface = threadingInterface;
|
||||
WindowImpl = windowImpl;
|
||||
WindowingPlatform = windowingPlatform;
|
||||
}
|
||||
|
||||
public IAssetLoader AssetLoader { get; }
|
||||
public IInputManager InputManager { get; }
|
||||
public IFocusManager FocusManager { get; }
|
||||
public Func<IKeyboardDevice> KeyboardDevice { get; }
|
||||
public IKeyboardNavigationHandler KeyboardNavigation { get; }
|
||||
public ILayoutManager LayoutManager { get; }
|
||||
public Func<IMouseDevice> MouseDevice { get; }
|
||||
public IRuntimePlatform Platform { get; }
|
||||
public IPlatformRenderInterface RenderInterface { get; }
|
||||
public IScheduler Scheduler { get; }
|
||||
public IStandardCursorFactory StandardCursorFactory { get; }
|
||||
public IStyler Styler { get; }
|
||||
public Func<Styles> Theme { get; }
|
||||
public IPlatformThreadingInterface ThreadingInterface { get; }
|
||||
public IWindowImpl WindowImpl { get; }
|
||||
public IWindowingPlatform WindowingPlatform { get; }
|
||||
|
||||
public TestServices With(
|
||||
IAssetLoader assetLoader = null,
|
||||
IFocusManager focusManager = null,
|
||||
IInputManager inputManager = null,
|
||||
Func<IKeyboardDevice> keyboardDevice = null,
|
||||
IKeyboardNavigationHandler keyboardNavigation = null,
|
||||
ILayoutManager layoutManager = null,
|
||||
Func<IMouseDevice> mouseDevice = null,
|
||||
IRuntimePlatform platform = null,
|
||||
IPlatformRenderInterface renderInterface = null,
|
||||
IRenderLoop renderLoop = null,
|
||||
IScheduler scheduler = null,
|
||||
IStandardCursorFactory standardCursorFactory = null,
|
||||
IStyler styler = null,
|
||||
Func<Styles> theme = null,
|
||||
IPlatformThreadingInterface threadingInterface = null,
|
||||
IWindowImpl windowImpl = null,
|
||||
IWindowingPlatform windowingPlatform = null)
|
||||
{
|
||||
return new TestServices(
|
||||
assetLoader: assetLoader ?? AssetLoader,
|
||||
focusManager: focusManager ?? FocusManager,
|
||||
inputManager: inputManager ?? InputManager,
|
||||
keyboardDevice: keyboardDevice ?? KeyboardDevice,
|
||||
keyboardNavigation: keyboardNavigation ?? KeyboardNavigation,
|
||||
layoutManager: layoutManager ?? LayoutManager,
|
||||
mouseDevice: mouseDevice ?? MouseDevice,
|
||||
platform: platform ?? Platform,
|
||||
renderInterface: renderInterface ?? RenderInterface,
|
||||
scheduler: scheduler ?? Scheduler,
|
||||
standardCursorFactory: standardCursorFactory ?? StandardCursorFactory,
|
||||
styler: styler ?? Styler,
|
||||
theme: theme ?? Theme,
|
||||
threadingInterface: threadingInterface ?? ThreadingInterface,
|
||||
windowingPlatform: windowingPlatform ?? WindowingPlatform,
|
||||
windowImpl: windowImpl ?? WindowImpl);
|
||||
}
|
||||
|
||||
private static Styles CreateDefaultTheme()
|
||||
{
|
||||
var result = new Styles
|
||||
{
|
||||
new DefaultTheme(),
|
||||
};
|
||||
|
||||
var loader = new AvaloniaXamlLoader();
|
||||
var baseLight = (IStyle)loader.Load(
|
||||
new Uri("resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default"));
|
||||
result.Add(baseLight);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static IPlatformRenderInterface CreateRenderInterfaceMock()
|
||||
{
|
||||
return Mock.Of<IPlatformRenderInterface>(x =>
|
||||
x.CreateFormattedText(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<Typeface>(),
|
||||
It.IsAny<TextAlignment>(),
|
||||
It.IsAny<TextWrapping>(),
|
||||
It.IsAny<Size>(),
|
||||
It.IsAny<IReadOnlyList<FormattedTextStyleSpan>>()) == Mock.Of<IFormattedTextImpl>() &&
|
||||
x.CreateStreamGeometry() == Mock.Of<IStreamGeometryImpl>(
|
||||
y => y.Open() == Mock.Of<IStreamGeometryContextImpl>()));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
using System;
|
||||
using System.Reactive.Concurrency;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Reflection;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.Styling;
|
||||
using Avalonia.Threading;
|
||||
|
||||
namespace AvaloniaEdit.AvaloniaMocks
|
||||
{
|
||||
public class UnitTestApplication : Application
|
||||
{
|
||||
public UnitTestApplication(TestServices services)
|
||||
{
|
||||
Services = services ?? new TestServices();
|
||||
RegisterServices();
|
||||
}
|
||||
|
||||
public TestServices Services { get; }
|
||||
|
||||
public static IDisposable Start(TestServices services = null)
|
||||
{
|
||||
AvaloniaLocator.Current = (AvaloniaLocator.CurrentMutable = new AvaloniaLocator());
|
||||
var app = new UnitTestApplication(services);
|
||||
AvaloniaLocator.CurrentMutable.BindToSelf<Application>(app);
|
||||
var updateServices = Dispatcher.UIThread.GetType().GetMethod("UpdateServices", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
updateServices?.Invoke(Dispatcher.UIThread, null);
|
||||
return Disposable.Create(() =>
|
||||
{
|
||||
updateServices?.Invoke(Dispatcher.UIThread, null);
|
||||
AvaloniaLocator.CurrentMutable = null;
|
||||
AvaloniaLocator.Current = null;
|
||||
});
|
||||
}
|
||||
|
||||
public override void RegisterServices()
|
||||
{
|
||||
AvaloniaLocator.CurrentMutable
|
||||
.Bind<IAssetLoader>().ToConstant(Services.AssetLoader)
|
||||
.Bind<IFocusManager>().ToConstant(Services.FocusManager)
|
||||
.BindToSelf<IGlobalStyles>(this)
|
||||
.Bind<IInputManager>().ToConstant(Services.InputManager)
|
||||
.Bind<IKeyboardDevice>().ToConstant(Services.KeyboardDevice?.Invoke())
|
||||
.Bind<IKeyboardNavigationHandler>().ToConstant(Services.KeyboardNavigation)
|
||||
.Bind<ILayoutManager>().ToConstant(Services.LayoutManager)
|
||||
.Bind<IMouseDevice>().ToConstant(Services.MouseDevice?.Invoke())
|
||||
.Bind<IRuntimePlatform>().ToConstant(Services.Platform)
|
||||
.Bind<IPlatformRenderInterface>().ToConstant(Services.RenderInterface)
|
||||
.Bind<IPlatformThreadingInterface>().ToConstant(Services.ThreadingInterface)
|
||||
.Bind<IScheduler>().ToConstant(Services.Scheduler)
|
||||
.Bind<IStandardCursorFactory>().ToConstant(Services.StandardCursorFactory)
|
||||
.Bind<IStyler>().ToConstant(Services.Styler)
|
||||
.Bind<IWindowingPlatform>().ToConstant(Services.WindowingPlatform)
|
||||
.Bind<IApplicationLifecycle>().ToConstant(this);
|
||||
var styles = Services.Theme?.Invoke();
|
||||
|
||||
if (styles != null)
|
||||
{
|
||||
Styles.AddRange(styles);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// 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.Linq;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace AvaloniaEdit.Document
|
||||
{
|
||||
[TestFixture]
|
||||
public class ChangeTrackingTest
|
||||
{
|
||||
[Test]
|
||||
public void NoChanges()
|
||||
{
|
||||
TextDocument document = new TextDocument("initial text");
|
||||
ITextSource snapshot1 = document.CreateSnapshot();
|
||||
ITextSource snapshot2 = document.CreateSnapshot();
|
||||
Assert.AreEqual(0, snapshot1.Version.CompareAge(snapshot2.Version));
|
||||
Assert.AreEqual(0, snapshot1.Version.GetChangesTo(snapshot2.Version).Count());
|
||||
Assert.AreEqual(document.Text, snapshot1.Text);
|
||||
Assert.AreEqual(document.Text, snapshot2.Text);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ForwardChanges()
|
||||
{
|
||||
TextDocument document = new TextDocument("initial text");
|
||||
ITextSource snapshot1 = document.CreateSnapshot();
|
||||
document.Replace(0, 7, "nw");
|
||||
document.Insert(1, "e");
|
||||
ITextSource snapshot2 = document.CreateSnapshot();
|
||||
Assert.AreEqual(-1, snapshot1.Version.CompareAge(snapshot2.Version));
|
||||
TextChangeEventArgs[] arr = snapshot1.Version.GetChangesTo(snapshot2.Version).ToArray();
|
||||
Assert.AreEqual(2, arr.Length);
|
||||
Assert.AreEqual("nw", arr[0].InsertedText.Text);
|
||||
Assert.AreEqual("e", arr[1].InsertedText.Text);
|
||||
|
||||
Assert.AreEqual("initial text", snapshot1.Text);
|
||||
Assert.AreEqual("new text", snapshot2.Text);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BackwardChanges()
|
||||
{
|
||||
TextDocument document = new TextDocument("initial text");
|
||||
ITextSource snapshot1 = document.CreateSnapshot();
|
||||
document.Replace(0, 7, "nw");
|
||||
document.Insert(1, "e");
|
||||
ITextSource snapshot2 = document.CreateSnapshot();
|
||||
Assert.AreEqual(1, snapshot2.Version.CompareAge(snapshot1.Version));
|
||||
TextChangeEventArgs[] arr = snapshot2.Version.GetChangesTo(snapshot1.Version).ToArray();
|
||||
Assert.AreEqual(2, arr.Length);
|
||||
Assert.AreEqual("", arr[0].InsertedText.Text);
|
||||
Assert.AreEqual("initial", arr[1].InsertedText.Text);
|
||||
|
||||
Assert.AreEqual("initial text", snapshot1.Text);
|
||||
Assert.AreEqual("new text", snapshot2.Text);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// 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 AvaloniaEdit.Rendering;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace AvaloniaEdit.Document
|
||||
{
|
||||
[TestFixture]
|
||||
public class CollapsingTests
|
||||
{
|
||||
TextDocument document;
|
||||
HeightTree heightTree;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
document = new TextDocument();
|
||||
document.Text = "1\n2\n3\n4\n5\n6\n7\n8\n9\n10";
|
||||
heightTree = new HeightTree(document, 10);
|
||||
foreach (DocumentLine line in document.Lines) {
|
||||
heightTree.SetHeight(line, line.LineNumber);
|
||||
}
|
||||
}
|
||||
|
||||
CollapsedLineSection SimpleCheck(int from, int to)
|
||||
{
|
||||
CollapsedLineSection sec1 = heightTree.CollapseText(document.GetLineByNumber(from), document.GetLineByNumber(to));
|
||||
for (int i = 1; i < from; i++) {
|
||||
Assert.IsFalse(heightTree.GetIsCollapsed(i));
|
||||
}
|
||||
for (int i = from; i <= to; i++) {
|
||||
Assert.IsTrue(heightTree.GetIsCollapsed(i));
|
||||
}
|
||||
for (int i = to + 1; i <= 10; i++) {
|
||||
Assert.IsFalse(heightTree.GetIsCollapsed(i));
|
||||
}
|
||||
CheckHeights();
|
||||
return sec1;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SimpleCheck()
|
||||
{
|
||||
SimpleCheck(4, 6);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SimpleUncollapse()
|
||||
{
|
||||
CollapsedLineSection sec1 = heightTree.CollapseText(document.GetLineByNumber(4), document.GetLineByNumber(6));
|
||||
sec1.Uncollapse();
|
||||
for (int i = 1; i <= 10; i++) {
|
||||
Assert.IsFalse(heightTree.GetIsCollapsed(i));
|
||||
}
|
||||
CheckHeights();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FullCheck()
|
||||
{
|
||||
for (int from = 1; from <= 10; from++) {
|
||||
for (int to = from; to <= 10; to++) {
|
||||
try {
|
||||
SimpleCheck(from, to).Uncollapse();
|
||||
for (int i = 1; i <= 10; i++) {
|
||||
Assert.IsFalse(heightTree.GetIsCollapsed(i));
|
||||
}
|
||||
CheckHeights();
|
||||
} catch {
|
||||
Console.WriteLine("from = " + from + ", to = " + to);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InsertInCollapsedSection()
|
||||
{
|
||||
CollapsedLineSection sec1 = heightTree.CollapseText(document.GetLineByNumber(4), document.GetLineByNumber(6));
|
||||
document.Insert(document.GetLineByNumber(5).Offset, "a\nb\nc");
|
||||
for (int i = 1; i < 4; i++) {
|
||||
Assert.IsFalse(heightTree.GetIsCollapsed(i));
|
||||
}
|
||||
for (int i = 4; i <= 8; i++) {
|
||||
Assert.IsTrue(heightTree.GetIsCollapsed(i));
|
||||
}
|
||||
for (int i = 9; i <= 12; i++) {
|
||||
Assert.IsFalse(heightTree.GetIsCollapsed(i));
|
||||
}
|
||||
CheckHeights();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveInCollapsedSection()
|
||||
{
|
||||
CollapsedLineSection sec1 = heightTree.CollapseText(document.GetLineByNumber(3), document.GetLineByNumber(7));
|
||||
int line4Offset = document.GetLineByNumber(4).Offset;
|
||||
int line6Offset = document.GetLineByNumber(6).Offset;
|
||||
document.Remove(line4Offset, line6Offset - line4Offset);
|
||||
for (int i = 1; i < 3; i++) {
|
||||
Assert.IsFalse(heightTree.GetIsCollapsed(i));
|
||||
}
|
||||
for (int i = 3; i <= 5; i++) {
|
||||
Assert.IsTrue(heightTree.GetIsCollapsed(i));
|
||||
}
|
||||
for (int i = 6; i <= 8; i++) {
|
||||
Assert.IsFalse(heightTree.GetIsCollapsed(i));
|
||||
}
|
||||
CheckHeights();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveEndOfCollapsedSection()
|
||||
{
|
||||
CollapsedLineSection sec1 = heightTree.CollapseText(document.GetLineByNumber(3), document.GetLineByNumber(6));
|
||||
int line5Offset = document.GetLineByNumber(5).Offset;
|
||||
int line8Offset = document.GetLineByNumber(8).Offset;
|
||||
document.Remove(line5Offset, line8Offset - line5Offset);
|
||||
for (int i = 1; i < 3; i++) {
|
||||
Assert.IsFalse(heightTree.GetIsCollapsed(i));
|
||||
}
|
||||
for (int i = 3; i <= 5; i++) {
|
||||
Assert.IsTrue(heightTree.GetIsCollapsed(i));
|
||||
}
|
||||
for (int i = 6; i <= 7; i++) {
|
||||
Assert.IsFalse(heightTree.GetIsCollapsed(i));
|
||||
}
|
||||
CheckHeights();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveCollapsedSection()
|
||||
{
|
||||
CollapsedLineSection sec1 = heightTree.CollapseText(document.GetLineByNumber(3), document.GetLineByNumber(3));
|
||||
int line3Offset = document.GetLineByNumber(3).Offset;
|
||||
document.Remove(line3Offset - 1, 1);
|
||||
for (int i = 1; i <= 9; i++) {
|
||||
Assert.IsFalse(heightTree.GetIsCollapsed(i));
|
||||
}
|
||||
CheckHeights();
|
||||
Assert.AreSame(null, sec1.Start);
|
||||
Assert.AreSame(null, sec1.End);
|
||||
// section gets uncollapsed when it is removed
|
||||
Assert.IsFalse(sec1.IsCollapsed);
|
||||
}
|
||||
|
||||
void CheckHeights()
|
||||
{
|
||||
HeightTests.CheckHeights(document, heightTree);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// 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 System.Linq;
|
||||
using AvaloniaEdit.Rendering;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace AvaloniaEdit.Document
|
||||
{
|
||||
[TestFixture]
|
||||
public class HeightTests
|
||||
{
|
||||
TextDocument document;
|
||||
HeightTree heightTree;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
document = new TextDocument();
|
||||
document.Text = "1\n2\n3\n4\n5\n6\n7\n8\n9\n10";
|
||||
heightTree = new HeightTree(document, 10);
|
||||
foreach (DocumentLine line in document.Lines) {
|
||||
heightTree.SetHeight(line, line.LineNumber);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SimpleCheck()
|
||||
{
|
||||
CheckHeights();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestLinesRemoved()
|
||||
{
|
||||
document.Remove(5, 4);
|
||||
CheckHeights();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestHeightChanged()
|
||||
{
|
||||
heightTree.SetHeight(document.GetLineByNumber(4), 100);
|
||||
CheckHeights();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestLinesInserted()
|
||||
{
|
||||
document.Insert(0, "x\ny\n");
|
||||
heightTree.SetHeight(document.Lines[0], 100);
|
||||
heightTree.SetHeight(document.Lines[1], 1000);
|
||||
heightTree.SetHeight(document.Lines[2], 10000);
|
||||
CheckHeights();
|
||||
}
|
||||
|
||||
void CheckHeights()
|
||||
{
|
||||
CheckHeights(document, heightTree);
|
||||
}
|
||||
|
||||
internal static void CheckHeights(TextDocument document, HeightTree heightTree)
|
||||
{
|
||||
double[] heights = document.Lines.Select(l => heightTree.GetIsCollapsed(l.LineNumber) ? 0 : heightTree.GetHeight(l)).ToArray();
|
||||
double[] visualPositions = new double[document.LineCount+1];
|
||||
for (int i = 0; i < heights.Length; i++) {
|
||||
visualPositions[i+1]=visualPositions[i]+heights[i];
|
||||
}
|
||||
foreach (DocumentLine ls in document.Lines) {
|
||||
Assert.AreEqual(visualPositions[ls.LineNumber-1], heightTree.GetVisualPosition(ls));
|
||||
}
|
||||
Assert.AreEqual(visualPositions[document.LineCount], heightTree.TotalHeight);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,585 @@
|
|||
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// 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 System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace AvaloniaEdit.Document
|
||||
{
|
||||
[TestFixture]
|
||||
public class LineManagerTests
|
||||
{
|
||||
TextDocument document;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
document = new TextDocument();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CheckEmptyDocument()
|
||||
{
|
||||
Assert.AreEqual("", document.Text);
|
||||
Assert.AreEqual(0, document.TextLength);
|
||||
Assert.AreEqual(1, document.LineCount);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CheckClearingDocument()
|
||||
{
|
||||
document.Text = "Hello,\nWorld!";
|
||||
Assert.AreEqual(2, document.LineCount);
|
||||
var oldLines = document.Lines.ToArray();
|
||||
document.Text = "";
|
||||
Assert.AreEqual("", document.Text);
|
||||
Assert.AreEqual(0, document.TextLength);
|
||||
Assert.AreEqual(1, document.LineCount);
|
||||
Assert.AreSame(oldLines[0], document.Lines.Single());
|
||||
Assert.IsFalse(oldLines[0].IsDeleted);
|
||||
Assert.IsTrue(oldLines[1].IsDeleted);
|
||||
Assert.IsNull(oldLines[0].NextLine);
|
||||
Assert.IsNull(oldLines[1].PreviousLine);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CheckGetLineInEmptyDocument()
|
||||
{
|
||||
Assert.AreEqual(1, document.Lines.Count);
|
||||
List<DocumentLine> lines = new List<DocumentLine>(document.Lines);
|
||||
Assert.AreEqual(1, lines.Count);
|
||||
DocumentLine line = document.Lines[0];
|
||||
Assert.AreSame(line, lines[0]);
|
||||
Assert.AreSame(line, document.GetLineByNumber(1));
|
||||
Assert.AreSame(line, document.GetLineByOffset(0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CheckLineSegmentInEmptyDocument()
|
||||
{
|
||||
DocumentLine line = document.GetLineByNumber(1);
|
||||
Assert.AreEqual(1, line.LineNumber);
|
||||
Assert.AreEqual(0, line.Offset);
|
||||
Assert.IsFalse(line.IsDeleted);
|
||||
Assert.AreEqual(0, line.Length);
|
||||
Assert.AreEqual(0, line.TotalLength);
|
||||
Assert.AreEqual(0, line.DelimiterLength);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void LineIndexOfTest()
|
||||
{
|
||||
DocumentLine line = document.GetLineByNumber(1);
|
||||
Assert.AreEqual(0, document.Lines.IndexOf(line));
|
||||
DocumentLine lineFromOtherDocument = new TextDocument().GetLineByNumber(1);
|
||||
Assert.AreEqual(-1, document.Lines.IndexOf(lineFromOtherDocument));
|
||||
document.Text = "a\nb\nc";
|
||||
DocumentLine middleLine = document.GetLineByNumber(2);
|
||||
Assert.AreEqual(1, document.Lines.IndexOf(middleLine));
|
||||
document.Remove(1, 3);
|
||||
Assert.IsTrue(middleLine.IsDeleted);
|
||||
Assert.AreEqual(-1, document.Lines.IndexOf(middleLine));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InsertInEmptyDocument()
|
||||
{
|
||||
document.Insert(0, "a");
|
||||
Assert.AreEqual(document.LineCount, 1);
|
||||
DocumentLine line = document.GetLineByNumber(1);
|
||||
Assert.AreEqual("a", document.GetText(line));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SetText()
|
||||
{
|
||||
document.Text = "a";
|
||||
Assert.AreEqual(document.LineCount, 1);
|
||||
DocumentLine line = document.GetLineByNumber(1);
|
||||
Assert.AreEqual("a", document.GetText(line));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InsertNothing()
|
||||
{
|
||||
document.Insert(0, "");
|
||||
Assert.AreEqual(document.LineCount, 1);
|
||||
Assert.AreEqual(document.TextLength, 0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InsertNull()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>(() => document.Insert(0, (string)null));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SetTextNull()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>(() => document.Text = null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveNothing()
|
||||
{
|
||||
document.Remove(0, 0);
|
||||
Assert.AreEqual(document.LineCount, 1);
|
||||
Assert.AreEqual(document.TextLength, 0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetCharAt0EmptyDocument()
|
||||
{
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => document.GetCharAt(0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetCharAtNegativeOffset()
|
||||
{
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() =>
|
||||
{
|
||||
document.Text = "a\nb";
|
||||
document.GetCharAt(-1);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetCharAtEndOffset()
|
||||
{
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() =>
|
||||
{
|
||||
document.Text = "a\nb";
|
||||
document.GetCharAt(document.TextLength);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InsertAtNegativeOffset()
|
||||
{
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() =>
|
||||
{
|
||||
document.Text = "a\nb";
|
||||
document.Insert(-1, "text");
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InsertAfterEndOffset()
|
||||
{
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() =>
|
||||
{
|
||||
document.Text = "a\nb";
|
||||
document.Insert(4, "text");
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveNegativeAmount()
|
||||
{
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() =>
|
||||
{
|
||||
document.Text = "abcd";
|
||||
document.Remove(2, -1);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveTooMuch()
|
||||
{
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() =>
|
||||
{
|
||||
document.Text = "abcd";
|
||||
document.Remove(2, 10);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetLineByNumberNegative()
|
||||
{
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() =>
|
||||
{
|
||||
document.Text = "a\nb";
|
||||
document.GetLineByNumber(-1);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetLineByNumberTooHigh()
|
||||
{
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() =>
|
||||
{
|
||||
document.Text = "a\nb";
|
||||
document.GetLineByNumber(3);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetLineByOffsetNegative()
|
||||
{
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() =>
|
||||
{
|
||||
document.Text = "a\nb";
|
||||
document.GetLineByOffset(-1);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void GetLineByOffsetToHigh()
|
||||
{
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() =>
|
||||
{
|
||||
document.Text = "a\nb";
|
||||
document.GetLineByOffset(10);
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InsertAtEndOffset()
|
||||
{
|
||||
document.Text = "a\nb";
|
||||
CheckDocumentLines("a",
|
||||
"b");
|
||||
document.Insert(3, "text");
|
||||
CheckDocumentLines("a",
|
||||
"btext");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetCharAt()
|
||||
{
|
||||
document.Text = "a\r\nb";
|
||||
Assert.AreEqual('a', document.GetCharAt(0));
|
||||
Assert.AreEqual('\r', document.GetCharAt(1));
|
||||
Assert.AreEqual('\n', document.GetCharAt(2));
|
||||
Assert.AreEqual('b', document.GetCharAt(3));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CheckMixedNewLineTest()
|
||||
{
|
||||
const string mixedNewlineText = "line 1\nline 2\r\nline 3\rline 4";
|
||||
document.Text = mixedNewlineText;
|
||||
Assert.AreEqual(mixedNewlineText, document.Text);
|
||||
Assert.AreEqual(4, document.LineCount);
|
||||
for (int i = 1; i < 4; i++)
|
||||
{
|
||||
DocumentLine line = document.GetLineByNumber(i);
|
||||
Assert.AreEqual(i, line.LineNumber);
|
||||
Assert.AreEqual("line " + i, document.GetText(line));
|
||||
}
|
||||
Assert.AreEqual(1, document.GetLineByNumber(1).DelimiterLength);
|
||||
Assert.AreEqual(2, document.GetLineByNumber(2).DelimiterLength);
|
||||
Assert.AreEqual(1, document.GetLineByNumber(3).DelimiterLength);
|
||||
Assert.AreEqual(0, document.GetLineByNumber(4).DelimiterLength);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void LfCrIsTwoNewLinesTest()
|
||||
{
|
||||
document.Text = "a\n\rb";
|
||||
Assert.AreEqual("a\n\rb", document.Text);
|
||||
CheckDocumentLines("a",
|
||||
"",
|
||||
"b");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveFirstPartOfDelimiter()
|
||||
{
|
||||
document.Text = "a\r\nb";
|
||||
document.Remove(1, 1);
|
||||
Assert.AreEqual("a\nb", document.Text);
|
||||
CheckDocumentLines("a",
|
||||
"b");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveLineContentAndJoinDelimiters()
|
||||
{
|
||||
document.Text = "a\rb\nc";
|
||||
document.Remove(2, 1);
|
||||
Assert.AreEqual("a\r\nc", document.Text);
|
||||
CheckDocumentLines("a",
|
||||
"c");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveLineContentAndJoinDelimiters2()
|
||||
{
|
||||
document.Text = "a\rb\nc\nd";
|
||||
document.Remove(2, 3);
|
||||
Assert.AreEqual("a\r\nd", document.Text);
|
||||
CheckDocumentLines("a",
|
||||
"d");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveLineContentAndJoinDelimiters3()
|
||||
{
|
||||
document.Text = "a\rb\r\nc";
|
||||
document.Remove(2, 2);
|
||||
Assert.AreEqual("a\r\nc", document.Text);
|
||||
CheckDocumentLines("a",
|
||||
"c");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveLineContentAndJoinNonMatchingDelimiters()
|
||||
{
|
||||
document.Text = "a\nb\nc";
|
||||
document.Remove(2, 1);
|
||||
Assert.AreEqual("a\n\nc", document.Text);
|
||||
CheckDocumentLines("a",
|
||||
"",
|
||||
"c");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveLineContentAndJoinNonMatchingDelimiters2()
|
||||
{
|
||||
document.Text = "a\nb\rc";
|
||||
document.Remove(2, 1);
|
||||
Assert.AreEqual("a\n\rc", document.Text);
|
||||
CheckDocumentLines("a",
|
||||
"",
|
||||
"c");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveMultilineUpToFirstPartOfDelimiter()
|
||||
{
|
||||
document.Text = "0\n1\r\n2";
|
||||
document.Remove(1, 3);
|
||||
Assert.AreEqual("0\n2", document.Text);
|
||||
CheckDocumentLines("0",
|
||||
"2");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveSecondPartOfDelimiter()
|
||||
{
|
||||
document.Text = "a\r\nb";
|
||||
document.Remove(2, 1);
|
||||
Assert.AreEqual("a\rb", document.Text);
|
||||
CheckDocumentLines("a",
|
||||
"b");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveFromSecondPartOfDelimiter()
|
||||
{
|
||||
document.Text = "a\r\nb\nc";
|
||||
document.Remove(2, 3);
|
||||
Assert.AreEqual("a\rc", document.Text);
|
||||
CheckDocumentLines("a",
|
||||
"c");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveFromSecondPartOfDelimiterToDocumentEnd()
|
||||
{
|
||||
document.Text = "a\r\nb";
|
||||
document.Remove(2, 2);
|
||||
Assert.AreEqual("a\r", document.Text);
|
||||
CheckDocumentLines("a",
|
||||
"");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveUpToMatchingDelimiter1()
|
||||
{
|
||||
document.Text = "a\r\nb\nc";
|
||||
document.Remove(2, 2);
|
||||
Assert.AreEqual("a\r\nc", document.Text);
|
||||
CheckDocumentLines("a",
|
||||
"c");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveUpToMatchingDelimiter2()
|
||||
{
|
||||
document.Text = "a\r\nb\r\nc";
|
||||
document.Remove(2, 3);
|
||||
Assert.AreEqual("a\r\nc", document.Text);
|
||||
CheckDocumentLines("a",
|
||||
"c");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveUpToNonMatchingDelimiter()
|
||||
{
|
||||
document.Text = "a\r\nb\rc";
|
||||
document.Remove(2, 2);
|
||||
Assert.AreEqual("a\r\rc", document.Text);
|
||||
CheckDocumentLines("a",
|
||||
"",
|
||||
"c");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveTwoCharDelimiter()
|
||||
{
|
||||
document.Text = "a\r\nb";
|
||||
document.Remove(1, 2);
|
||||
Assert.AreEqual("ab", document.Text);
|
||||
CheckDocumentLines("ab");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveOneCharDelimiter()
|
||||
{
|
||||
document.Text = "a\nb";
|
||||
document.Remove(1, 1);
|
||||
Assert.AreEqual("ab", document.Text);
|
||||
CheckDocumentLines("ab");
|
||||
}
|
||||
|
||||
void CheckDocumentLines(params string[] lines)
|
||||
{
|
||||
Assert.AreEqual(lines.Length, document.LineCount, "LineCount");
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
Assert.AreEqual(lines[i], document.GetText(document.Lines[i]), "Text of line " + (i + 1));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FixUpFirstPartOfDelimiter()
|
||||
{
|
||||
document.Text = "a\n\nb";
|
||||
document.Replace(1, 1, "\r");
|
||||
Assert.AreEqual("a\r\nb", document.Text);
|
||||
CheckDocumentLines("a",
|
||||
"b");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FixUpSecondPartOfDelimiter()
|
||||
{
|
||||
document.Text = "a\r\rb";
|
||||
document.Replace(2, 1, "\n");
|
||||
Assert.AreEqual("a\r\nb", document.Text);
|
||||
CheckDocumentLines("a",
|
||||
"b");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InsertInsideDelimiter()
|
||||
{
|
||||
document.Text = "a\r\nc";
|
||||
document.Insert(2, "b");
|
||||
Assert.AreEqual("a\rb\nc", document.Text);
|
||||
CheckDocumentLines("a",
|
||||
"b",
|
||||
"c");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InsertInsideDelimiter2()
|
||||
{
|
||||
document.Text = "a\r\nd";
|
||||
document.Insert(2, "b\nc");
|
||||
Assert.AreEqual("a\rb\nc\nd", document.Text);
|
||||
CheckDocumentLines("a",
|
||||
"b",
|
||||
"c",
|
||||
"d");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InsertInsideDelimiter3()
|
||||
{
|
||||
document.Text = "a\r\nc";
|
||||
document.Insert(2, "b\r");
|
||||
Assert.AreEqual("a\rb\r\nc", document.Text);
|
||||
CheckDocumentLines("a",
|
||||
"b",
|
||||
"c");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExtendDelimiter1()
|
||||
{
|
||||
document.Text = "a\nc";
|
||||
document.Insert(1, "b\r");
|
||||
Assert.AreEqual("ab\r\nc", document.Text);
|
||||
CheckDocumentLines("ab",
|
||||
"c");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ExtendDelimiter2()
|
||||
{
|
||||
document.Text = "a\rc";
|
||||
document.Insert(2, "\nb");
|
||||
Assert.AreEqual("a\r\nbc", document.Text);
|
||||
CheckDocumentLines("a",
|
||||
"bc");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ReplaceLineContentBetweenMatchingDelimiters()
|
||||
{
|
||||
document.Text = "a\rb\nc";
|
||||
document.Replace(2, 1, "x");
|
||||
Assert.AreEqual("a\rx\nc", document.Text);
|
||||
CheckDocumentLines("a",
|
||||
"x",
|
||||
"c");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetOffset()
|
||||
{
|
||||
document.Text = "Hello,\nWorld!";
|
||||
Assert.AreEqual(0, document.GetOffset(1, 1));
|
||||
Assert.AreEqual(1, document.GetOffset(1, 2));
|
||||
Assert.AreEqual(5, document.GetOffset(1, 6));
|
||||
Assert.AreEqual(6, document.GetOffset(1, 7));
|
||||
Assert.AreEqual(7, document.GetOffset(2, 1));
|
||||
Assert.AreEqual(8, document.GetOffset(2, 2));
|
||||
Assert.AreEqual(12, document.GetOffset(2, 6));
|
||||
Assert.AreEqual(13, document.GetOffset(2, 7));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetOffsetIgnoreNegativeColumns()
|
||||
{
|
||||
document.Text = "Hello,\nWorld!";
|
||||
Assert.AreEqual(0, document.GetOffset(1, -1));
|
||||
Assert.AreEqual(0, document.GetOffset(1, -100));
|
||||
Assert.AreEqual(0, document.GetOffset(1, 0));
|
||||
Assert.AreEqual(7, document.GetOffset(2, -1));
|
||||
Assert.AreEqual(7, document.GetOffset(2, -100));
|
||||
Assert.AreEqual(7, document.GetOffset(2, 0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetOffsetIgnoreTooHighColumns()
|
||||
{
|
||||
document.Text = "Hello,\nWorld!";
|
||||
Assert.AreEqual(6, document.GetOffset(1, 8));
|
||||
Assert.AreEqual(6, document.GetOffset(1, 100));
|
||||
Assert.AreEqual(13, document.GetOffset(2, 8));
|
||||
Assert.AreEqual(13, document.GetOffset(2, 100));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,183 @@
|
|||
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// 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 System.Collections.Generic;
|
||||
using AvaloniaEdit.Rendering;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace AvaloniaEdit.Document
|
||||
{
|
||||
/// <summary>
|
||||
/// A randomized test for the line manager.
|
||||
/// </summary>
|
||||
[TestFixture]
|
||||
public class RandomizedLineManagerTest
|
||||
{
|
||||
TextDocument document;
|
||||
Random rnd;
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void FixtureSetup()
|
||||
{
|
||||
int seed = Environment.TickCount;
|
||||
Console.WriteLine("RandomizedLineManagerTest Seed: " + seed);
|
||||
rnd = new Random(seed);
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
document = new TextDocument();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShortReplacements()
|
||||
{
|
||||
char[] chars = { 'a', 'b', '\r', '\n' };
|
||||
char[] buffer = new char[20];
|
||||
for (int i = 0; i < 2500; i++) {
|
||||
int offset = rnd.Next(0, document.TextLength);
|
||||
int length = rnd.Next(0, document.TextLength - offset);
|
||||
int newTextLength = rnd.Next(0, 20);
|
||||
for (int j = 0; j < newTextLength; j++) {
|
||||
buffer[j] = chars[rnd.Next(0, chars.Length)];
|
||||
}
|
||||
|
||||
document.Replace(offset, length, new string(buffer, 0, newTextLength));
|
||||
CheckLines();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void LargeReplacements()
|
||||
{
|
||||
char[] chars = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', '\r', '\n' };
|
||||
char[] buffer = new char[1000];
|
||||
for (int i = 0; i < 20; i++) {
|
||||
int offset = rnd.Next(0, document.TextLength);
|
||||
int length = rnd.Next(0, (document.TextLength - offset) / 4);
|
||||
int newTextLength = rnd.Next(0, 1000);
|
||||
for (int j = 0; j < newTextLength; j++) {
|
||||
buffer[j] = chars[rnd.Next(0, chars.Length)];
|
||||
}
|
||||
|
||||
string newText = new string(buffer, 0, newTextLength);
|
||||
string expectedText = document.Text.Remove(offset, length).Insert(offset, newText);
|
||||
document.Replace(offset, length, newText);
|
||||
Assert.AreEqual(expectedText, document.Text);
|
||||
CheckLines();
|
||||
}
|
||||
}
|
||||
|
||||
void CheckLines()
|
||||
{
|
||||
string text = document.Text;
|
||||
int lineNumber = 1;
|
||||
int lineStart = 0;
|
||||
for (int i = 0; i < text.Length; i++) {
|
||||
char c = text[i];
|
||||
if (c == '\r' && i + 1 < text.Length && text[i + 1] == '\n') {
|
||||
DocumentLine line = document.GetLineByNumber(lineNumber);
|
||||
Assert.AreEqual(lineNumber, line.LineNumber);
|
||||
Assert.AreEqual(2, line.DelimiterLength);
|
||||
Assert.AreEqual(lineStart, line.Offset);
|
||||
Assert.AreEqual(i - lineStart, line.Length);
|
||||
i++; // consume \n
|
||||
lineNumber++;
|
||||
lineStart = i+1;
|
||||
} else if (c == '\r' || c == '\n') {
|
||||
DocumentLine line = document.GetLineByNumber(lineNumber);
|
||||
Assert.AreEqual(lineNumber, line.LineNumber);
|
||||
Assert.AreEqual(1, line.DelimiterLength);
|
||||
Assert.AreEqual(lineStart, line.Offset);
|
||||
Assert.AreEqual(i - lineStart, line.Length);
|
||||
lineNumber++;
|
||||
lineStart = i+1;
|
||||
}
|
||||
}
|
||||
Assert.AreEqual(lineNumber, document.LineCount);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CollapsingTest()
|
||||
{
|
||||
char[] chars = { 'a', 'b', '\r', '\n' };
|
||||
char[] buffer = new char[20];
|
||||
HeightTree heightTree = new HeightTree(document, 10);
|
||||
List<CollapsedLineSection> collapsedSections = new List<CollapsedLineSection>();
|
||||
for (int i = 0; i < 2500; i++) {
|
||||
// Console.WriteLine("Iteration " + i);
|
||||
// Console.WriteLine(heightTree.GetTreeAsString());
|
||||
// foreach (CollapsedLineSection cs in collapsedSections) {
|
||||
// Console.WriteLine(cs);
|
||||
// }
|
||||
|
||||
switch (rnd.Next(0, 10)) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
int offset = rnd.Next(0, document.TextLength);
|
||||
int length = rnd.Next(0, document.TextLength - offset);
|
||||
int newTextLength = rnd.Next(0, 20);
|
||||
for (int j = 0; j < newTextLength; j++) {
|
||||
buffer[j] = chars[rnd.Next(0, chars.Length)];
|
||||
}
|
||||
|
||||
document.Replace(offset, length, new string(buffer, 0, newTextLength));
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
int startLine = rnd.Next(1, document.LineCount + 1);
|
||||
int endLine = rnd.Next(startLine, document.LineCount + 1);
|
||||
collapsedSections.Add(heightTree.CollapseText(document.GetLineByNumber(startLine), document.GetLineByNumber(endLine)));
|
||||
break;
|
||||
case 8:
|
||||
if (collapsedSections.Count > 0) {
|
||||
CollapsedLineSection cs = collapsedSections[rnd.Next(0, collapsedSections.Count)];
|
||||
// unless the text section containing the CollapsedSection was deleted:
|
||||
if (cs.Start != null) {
|
||||
cs.Uncollapse();
|
||||
}
|
||||
collapsedSections.Remove(cs);
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
foreach (DocumentLine ls in document.Lines) {
|
||||
heightTree.SetHeight(ls, ls.LineNumber);
|
||||
}
|
||||
break;
|
||||
}
|
||||
var treeSections = new HashSet<CollapsedLineSection>(heightTree.GetAllCollapsedSections());
|
||||
int expectedCount = 0;
|
||||
foreach (CollapsedLineSection cs in collapsedSections) {
|
||||
if (cs.Start != null) {
|
||||
expectedCount++;
|
||||
Assert.IsTrue(treeSections.Contains(cs));
|
||||
}
|
||||
}
|
||||
Assert.AreEqual(expectedCount, treeSections.Count);
|
||||
CheckLines();
|
||||
HeightTests.CheckHeights(document, heightTree);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,328 @@
|
|||
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// 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 System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace AvaloniaEdit.Document
|
||||
{
|
||||
[TestFixture]
|
||||
public class TextAnchorTest
|
||||
{
|
||||
TextDocument document;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
document = new TextDocument();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AnchorInEmptyDocument()
|
||||
{
|
||||
TextAnchor a1 = document.CreateAnchor(0);
|
||||
TextAnchor a2 = document.CreateAnchor(0);
|
||||
a1.MovementType = AnchorMovementType.BeforeInsertion;
|
||||
a2.MovementType = AnchorMovementType.AfterInsertion;
|
||||
Assert.AreEqual(0, a1.Offset);
|
||||
Assert.AreEqual(0, a2.Offset);
|
||||
document.Insert(0, "x");
|
||||
Assert.AreEqual(0, a1.Offset);
|
||||
Assert.AreEqual(1, a2.Offset);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AnchorsSurviveDeletion()
|
||||
{
|
||||
document.Text = new string(' ', 10);
|
||||
TextAnchor[] a1 = new TextAnchor[11];
|
||||
TextAnchor[] a2 = new TextAnchor[11];
|
||||
for (int i = 0; i < 11; i++) {
|
||||
//Console.WriteLine("Insert first at i = " + i);
|
||||
a1[i] = document.CreateAnchor(i);
|
||||
a1[i].SurviveDeletion = true;
|
||||
//Console.WriteLine(document.GetTextAnchorTreeAsString());
|
||||
//Console.WriteLine("Insert second at i = " + i);
|
||||
a2[i] = document.CreateAnchor(i);
|
||||
a2[i].SurviveDeletion = false;
|
||||
//Console.WriteLine(document.GetTextAnchorTreeAsString());
|
||||
}
|
||||
for (int i = 0; i < 11; i++) {
|
||||
Assert.AreEqual(i, a1[i].Offset);
|
||||
Assert.AreEqual(i, a2[i].Offset);
|
||||
}
|
||||
document.Remove(1, 8);
|
||||
for (int i = 0; i < 11; i++) {
|
||||
if (i <= 1) {
|
||||
Assert.IsFalse(a1[i].IsDeleted);
|
||||
Assert.IsFalse(a2[i].IsDeleted);
|
||||
Assert.AreEqual(i, a1[i].Offset);
|
||||
Assert.AreEqual(i, a2[i].Offset);
|
||||
} else if (i <= 8) {
|
||||
Assert.IsFalse(a1[i].IsDeleted);
|
||||
Assert.IsTrue(a2[i].IsDeleted);
|
||||
Assert.AreEqual(1, a1[i].Offset);
|
||||
} else {
|
||||
Assert.IsFalse(a1[i].IsDeleted);
|
||||
Assert.IsFalse(a2[i].IsDeleted);
|
||||
Assert.AreEqual(i - 8, a1[i].Offset);
|
||||
Assert.AreEqual(i - 8, a2[i].Offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Random rnd;
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void FixtureSetup()
|
||||
{
|
||||
int seed = Environment.TickCount;
|
||||
Console.WriteLine("TextAnchorTest Seed: " + seed);
|
||||
rnd = new Random(seed);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateAnchors()
|
||||
{
|
||||
List<TextAnchor> anchors = new List<TextAnchor>();
|
||||
List<int> expectedOffsets = new List<int>();
|
||||
document.Text = new string(' ', 1000);
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
int offset = rnd.Next(1000);
|
||||
anchors.Add(document.CreateAnchor(offset));
|
||||
expectedOffsets.Add(offset);
|
||||
}
|
||||
for (int i = 0; i < anchors.Count; i++) {
|
||||
Assert.AreEqual(expectedOffsets[i], anchors[i].Offset);
|
||||
}
|
||||
GC.KeepAlive(anchors);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateAndGCAnchors()
|
||||
{
|
||||
List<TextAnchor> anchors = new List<TextAnchor>();
|
||||
List<int> expectedOffsets = new List<int>();
|
||||
document.Text = new string(' ', 1000);
|
||||
for (int t = 0; t < 250; t++) {
|
||||
int c = rnd.Next(50);
|
||||
if (rnd.Next(2) == 0) {
|
||||
for (int i = 0; i < c; i++) {
|
||||
int offset = rnd.Next(1000);
|
||||
anchors.Add(document.CreateAnchor(offset));
|
||||
expectedOffsets.Add(offset);
|
||||
}
|
||||
} else if (c <= anchors.Count) {
|
||||
anchors.RemoveRange(0, c);
|
||||
expectedOffsets.RemoveRange(0, c);
|
||||
GC.Collect();
|
||||
}
|
||||
for (int j = 0; j < anchors.Count; j++) {
|
||||
Assert.AreEqual(expectedOffsets[j], anchors[j].Offset);
|
||||
}
|
||||
}
|
||||
GC.KeepAlive(anchors);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MoveAnchorsDuringReplace()
|
||||
{
|
||||
document.Text = "abcd";
|
||||
TextAnchor start = document.CreateAnchor(1);
|
||||
TextAnchor middleDeletable = document.CreateAnchor(2);
|
||||
TextAnchor middleSurvivorLeft = document.CreateAnchor(2);
|
||||
middleSurvivorLeft.SurviveDeletion = true;
|
||||
middleSurvivorLeft.MovementType = AnchorMovementType.BeforeInsertion;
|
||||
TextAnchor middleSurvivorRight = document.CreateAnchor(2);
|
||||
middleSurvivorRight.SurviveDeletion = true;
|
||||
middleSurvivorRight.MovementType = AnchorMovementType.AfterInsertion;
|
||||
TextAnchor end = document.CreateAnchor(3);
|
||||
document.Replace(1, 2, "BxC");
|
||||
|
||||
Assert.AreEqual(1, start.Offset);
|
||||
Assert.IsTrue(middleDeletable.IsDeleted);
|
||||
Assert.AreEqual(1, middleSurvivorLeft.Offset);
|
||||
Assert.AreEqual(4, middleSurvivorRight.Offset);
|
||||
Assert.AreEqual(4, end.Offset);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateAndMoveAnchors()
|
||||
{
|
||||
List<TextAnchor> anchors = new List<TextAnchor>();
|
||||
List<int> expectedOffsets = new List<int>();
|
||||
document.Text = new string(' ', 1000);
|
||||
for (int t = 0; t < 250; t++) {
|
||||
//Console.Write("t = " + t + " ");
|
||||
int c = rnd.Next(50);
|
||||
switch (rnd.Next(5)) {
|
||||
case 0:
|
||||
//Console.WriteLine("Add c=" + c + " anchors");
|
||||
for (int i = 0; i < c; i++) {
|
||||
int offset = rnd.Next(document.TextLength);
|
||||
TextAnchor anchor = document.CreateAnchor(offset);
|
||||
if (rnd.Next(2) == 0)
|
||||
anchor.MovementType = AnchorMovementType.BeforeInsertion;
|
||||
else
|
||||
anchor.MovementType = AnchorMovementType.AfterInsertion;
|
||||
anchor.SurviveDeletion = rnd.Next(2) == 0;
|
||||
anchors.Add(anchor);
|
||||
expectedOffsets.Add(offset);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (c <= anchors.Count) {
|
||||
//Console.WriteLine("Remove c=" + c + " anchors");
|
||||
anchors.RemoveRange(0, c);
|
||||
expectedOffsets.RemoveRange(0, c);
|
||||
GC.Collect();
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
int insertOffset = rnd.Next(document.TextLength);
|
||||
int insertLength = rnd.Next(1000);
|
||||
//Console.WriteLine("insertOffset=" + insertOffset + " insertLength="+insertLength);
|
||||
document.Insert(insertOffset, new string(' ', insertLength));
|
||||
for (int i = 0; i < anchors.Count; i++) {
|
||||
if (anchors[i].MovementType == AnchorMovementType.BeforeInsertion) {
|
||||
if (expectedOffsets[i] > insertOffset)
|
||||
expectedOffsets[i] += insertLength;
|
||||
} else {
|
||||
if (expectedOffsets[i] >= insertOffset)
|
||||
expectedOffsets[i] += insertLength;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
int removalOffset = rnd.Next(document.TextLength);
|
||||
int removalLength = rnd.Next(document.TextLength - removalOffset);
|
||||
//Console.WriteLine("RemovalOffset=" + removalOffset + " RemovalLength="+removalLength);
|
||||
document.Remove(removalOffset, removalLength);
|
||||
for (int i = anchors.Count - 1; i >= 0; i--) {
|
||||
if (expectedOffsets[i] > removalOffset && expectedOffsets[i] < removalOffset + removalLength) {
|
||||
if (anchors[i].SurviveDeletion) {
|
||||
expectedOffsets[i] = removalOffset;
|
||||
} else {
|
||||
Assert.IsTrue(anchors[i].IsDeleted);
|
||||
anchors.RemoveAt(i);
|
||||
expectedOffsets.RemoveAt(i);
|
||||
}
|
||||
} else if (expectedOffsets[i] > removalOffset) {
|
||||
expectedOffsets[i] -= removalLength;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
int replaceOffset = rnd.Next(document.TextLength);
|
||||
int replaceRemovalLength = rnd.Next(document.TextLength - replaceOffset);
|
||||
int replaceInsertLength = rnd.Next(1000);
|
||||
//Console.WriteLine("ReplaceOffset=" + replaceOffset + " RemovalLength="+replaceRemovalLength + " InsertLength=" + replaceInsertLength);
|
||||
document.Replace(replaceOffset, replaceRemovalLength, new string(' ', replaceInsertLength));
|
||||
for (int i = anchors.Count - 1; i >= 0; i--) {
|
||||
if (expectedOffsets[i] > replaceOffset && expectedOffsets[i] < replaceOffset + replaceRemovalLength) {
|
||||
if (anchors[i].SurviveDeletion) {
|
||||
if (anchors[i].MovementType == AnchorMovementType.AfterInsertion)
|
||||
expectedOffsets[i] = replaceOffset + replaceInsertLength;
|
||||
else
|
||||
expectedOffsets[i] = replaceOffset;
|
||||
} else {
|
||||
Assert.IsTrue(anchors[i].IsDeleted);
|
||||
anchors.RemoveAt(i);
|
||||
expectedOffsets.RemoveAt(i);
|
||||
}
|
||||
} else if (expectedOffsets[i] > replaceOffset) {
|
||||
expectedOffsets[i] += replaceInsertLength - replaceRemovalLength;
|
||||
} else if (expectedOffsets[i] == replaceOffset && replaceRemovalLength == 0 && anchors[i].MovementType == AnchorMovementType.AfterInsertion) {
|
||||
expectedOffsets[i] += replaceInsertLength - replaceRemovalLength;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
Assert.AreEqual(anchors.Count, expectedOffsets.Count);
|
||||
for (int j = 0; j < anchors.Count; j++) {
|
||||
Assert.AreEqual(expectedOffsets[j], anchors[j].Offset);
|
||||
}
|
||||
}
|
||||
GC.KeepAlive(anchors);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RepeatedTextDragDrop()
|
||||
{
|
||||
document.Text = new string(' ', 1000);
|
||||
for (int i = 0; i < 20; i++) {
|
||||
TextAnchor a = document.CreateAnchor(144);
|
||||
TextAnchor b = document.CreateAnchor(157);
|
||||
document.Insert(128, new string('a', 13));
|
||||
document.Remove(157, 13);
|
||||
a = document.CreateAnchor(128);
|
||||
b = document.CreateAnchor(141);
|
||||
|
||||
document.Insert(157, new string('b', 13));
|
||||
document.Remove(128, 13);
|
||||
|
||||
a = null;
|
||||
b = null;
|
||||
if ((i % 5) == 0)
|
||||
GC.Collect();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ReplaceSpacesWithTab()
|
||||
{
|
||||
document.Text = "a b";
|
||||
TextAnchor before = document.CreateAnchor(1);
|
||||
before.MovementType = AnchorMovementType.AfterInsertion;
|
||||
TextAnchor after = document.CreateAnchor(5);
|
||||
TextAnchor survivingMiddle = document.CreateAnchor(2);
|
||||
TextAnchor deletedMiddle = document.CreateAnchor(3);
|
||||
|
||||
document.Replace(1, 4, "\t", OffsetChangeMappingType.CharacterReplace);
|
||||
Assert.AreEqual("a\tb", document.Text);
|
||||
// yes, the movement is a bit strange; but that's how CharacterReplace works when the text gets shorter
|
||||
Assert.AreEqual(1, before.Offset);
|
||||
Assert.AreEqual(2, after.Offset);
|
||||
Assert.AreEqual(2, survivingMiddle.Offset);
|
||||
Assert.AreEqual(2, deletedMiddle.Offset);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ReplaceTwoCharactersWithThree()
|
||||
{
|
||||
document.Text = "a12b";
|
||||
TextAnchor before = document.CreateAnchor(1);
|
||||
before.MovementType = AnchorMovementType.AfterInsertion;
|
||||
TextAnchor after = document.CreateAnchor(3);
|
||||
before.MovementType = AnchorMovementType.BeforeInsertion;
|
||||
TextAnchor middleB = document.CreateAnchor(2);
|
||||
before.MovementType = AnchorMovementType.BeforeInsertion;
|
||||
TextAnchor middleA = document.CreateAnchor(2);
|
||||
before.MovementType = AnchorMovementType.AfterInsertion;
|
||||
|
||||
document.Replace(1, 2, "123", OffsetChangeMappingType.CharacterReplace);
|
||||
Assert.AreEqual("a123b", document.Text);
|
||||
Assert.AreEqual(1, before.Offset);
|
||||
Assert.AreEqual(4, after.Offset);
|
||||
Assert.AreEqual(2, middleA.Offset);
|
||||
Assert.AreEqual(2, middleB.Offset);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,365 @@
|
|||
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// 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 System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace AvaloniaEdit.Document
|
||||
{
|
||||
[TestFixture]
|
||||
public class TextSegmentTreeTest
|
||||
{
|
||||
Random rnd;
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void FixtureSetup()
|
||||
{
|
||||
int seed = Environment.TickCount;
|
||||
Console.WriteLine("TextSegmentTreeTest Seed: " + seed);
|
||||
rnd = new Random(seed);
|
||||
}
|
||||
|
||||
class TestTextSegment : TextSegment
|
||||
{
|
||||
internal int ExpectedOffset, ExpectedLength;
|
||||
|
||||
public TestTextSegment(int expectedOffset, int expectedLength)
|
||||
{
|
||||
this.ExpectedOffset = expectedOffset;
|
||||
this.ExpectedLength = expectedLength;
|
||||
this.StartOffset = expectedOffset;
|
||||
this.Length = expectedLength;
|
||||
}
|
||||
}
|
||||
|
||||
TextSegmentCollection<TestTextSegment> tree;
|
||||
List<TestTextSegment> expectedSegments;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
tree = new TextSegmentCollection<TestTextSegment>();
|
||||
expectedSegments = new List<TestTextSegment>();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FindInEmptyTree()
|
||||
{
|
||||
Assert.AreSame(null, tree.FindFirstSegmentWithStartAfter(0));
|
||||
Assert.AreEqual(0, tree.FindSegmentsContaining(0).Count);
|
||||
Assert.AreEqual(0, tree.FindOverlappingSegments(10, 20).Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FindFirstSegmentWithStartAfter()
|
||||
{
|
||||
var s1 = new TestTextSegment(5, 10);
|
||||
var s2 = new TestTextSegment(10, 10);
|
||||
tree.Add(s1);
|
||||
tree.Add(s2);
|
||||
Assert.AreSame(s1, tree.FindFirstSegmentWithStartAfter(-100));
|
||||
Assert.AreSame(s1, tree.FindFirstSegmentWithStartAfter(0));
|
||||
Assert.AreSame(s1, tree.FindFirstSegmentWithStartAfter(4));
|
||||
Assert.AreSame(s1, tree.FindFirstSegmentWithStartAfter(5));
|
||||
Assert.AreSame(s2, tree.FindFirstSegmentWithStartAfter(6));
|
||||
Assert.AreSame(s2, tree.FindFirstSegmentWithStartAfter(9));
|
||||
Assert.AreSame(s2, tree.FindFirstSegmentWithStartAfter(10));
|
||||
Assert.AreSame(null, tree.FindFirstSegmentWithStartAfter(11));
|
||||
Assert.AreSame(null, tree.FindFirstSegmentWithStartAfter(100));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FindFirstSegmentWithStartAfterWithDuplicates()
|
||||
{
|
||||
var s1 = new TestTextSegment(5, 10);
|
||||
var s1b = new TestTextSegment(5, 7);
|
||||
var s2 = new TestTextSegment(10, 10);
|
||||
var s2b = new TestTextSegment(10, 7);
|
||||
tree.Add(s1);
|
||||
tree.Add(s1b);
|
||||
tree.Add(s2);
|
||||
tree.Add(s2b);
|
||||
Assert.AreSame(s1b, tree.GetNextSegment(s1));
|
||||
Assert.AreSame(s2b, tree.GetNextSegment(s2));
|
||||
Assert.AreSame(s1, tree.FindFirstSegmentWithStartAfter(-100));
|
||||
Assert.AreSame(s1, tree.FindFirstSegmentWithStartAfter(0));
|
||||
Assert.AreSame(s1, tree.FindFirstSegmentWithStartAfter(4));
|
||||
Assert.AreSame(s1, tree.FindFirstSegmentWithStartAfter(5));
|
||||
Assert.AreSame(s2, tree.FindFirstSegmentWithStartAfter(6));
|
||||
Assert.AreSame(s2, tree.FindFirstSegmentWithStartAfter(9));
|
||||
Assert.AreSame(s2, tree.FindFirstSegmentWithStartAfter(10));
|
||||
Assert.AreSame(null, tree.FindFirstSegmentWithStartAfter(11));
|
||||
Assert.AreSame(null, tree.FindFirstSegmentWithStartAfter(100));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FindFirstSegmentWithStartAfterWithDuplicates2()
|
||||
{
|
||||
var s1 = new TestTextSegment(5, 1);
|
||||
var s2 = new TestTextSegment(5, 2);
|
||||
var s3 = new TestTextSegment(5, 3);
|
||||
var s4 = new TestTextSegment(5, 4);
|
||||
tree.Add(s1);
|
||||
tree.Add(s2);
|
||||
tree.Add(s3);
|
||||
tree.Add(s4);
|
||||
Assert.AreSame(s1, tree.FindFirstSegmentWithStartAfter(0));
|
||||
Assert.AreSame(s1, tree.FindFirstSegmentWithStartAfter(1));
|
||||
Assert.AreSame(s1, tree.FindFirstSegmentWithStartAfter(4));
|
||||
Assert.AreSame(s1, tree.FindFirstSegmentWithStartAfter(5));
|
||||
Assert.AreSame(null, tree.FindFirstSegmentWithStartAfter(6));
|
||||
}
|
||||
|
||||
TestTextSegment AddSegment(int offset, int length)
|
||||
{
|
||||
// Console.WriteLine("Add " + offset + ", " + length);
|
||||
TestTextSegment s = new TestTextSegment(offset, length);
|
||||
tree.Add(s);
|
||||
expectedSegments.Add(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
void RemoveSegment(TestTextSegment s)
|
||||
{
|
||||
// Console.WriteLine("Remove " + s);
|
||||
expectedSegments.Remove(s);
|
||||
tree.Remove(s);
|
||||
}
|
||||
|
||||
void TestRetrieval(int offset, int length)
|
||||
{
|
||||
HashSet<TestTextSegment> actual = new HashSet<TestTextSegment>(tree.FindOverlappingSegments(offset, length));
|
||||
HashSet<TestTextSegment> expected = new HashSet<TestTextSegment>();
|
||||
foreach (TestTextSegment e in expectedSegments) {
|
||||
if (e.ExpectedOffset + e.ExpectedLength < offset)
|
||||
continue;
|
||||
if (e.ExpectedOffset > offset + length)
|
||||
continue;
|
||||
expected.Add(e);
|
||||
}
|
||||
Assert.IsTrue(actual.IsSubsetOf(expected));
|
||||
Assert.IsTrue(expected.IsSubsetOf(actual));
|
||||
}
|
||||
|
||||
void CheckSegments()
|
||||
{
|
||||
Assert.AreEqual(expectedSegments.Count, tree.Count);
|
||||
foreach (TestTextSegment s in expectedSegments) {
|
||||
Assert.AreEqual(s.ExpectedOffset, s.StartOffset /*, "startoffset for " + s*/);
|
||||
Assert.AreEqual(s.ExpectedLength, s.Length /*, "length for " + s*/);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AddSegments()
|
||||
{
|
||||
TestTextSegment s1 = AddSegment(10, 20);
|
||||
TestTextSegment s2 = AddSegment(15, 10);
|
||||
CheckSegments();
|
||||
}
|
||||
|
||||
void ChangeDocument(OffsetChangeMapEntry change)
|
||||
{
|
||||
tree.UpdateOffsets(change);
|
||||
foreach (TestTextSegment s in expectedSegments) {
|
||||
int endOffset = s.ExpectedOffset + s.ExpectedLength;
|
||||
s.ExpectedOffset = change.GetNewOffset(s.ExpectedOffset, AnchorMovementType.AfterInsertion);
|
||||
s.ExpectedLength = Math.Max(0, change.GetNewOffset(endOffset, AnchorMovementType.BeforeInsertion) - s.ExpectedOffset);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InsertionBeforeAllSegments()
|
||||
{
|
||||
TestTextSegment s1 = AddSegment(10, 20);
|
||||
TestTextSegment s2 = AddSegment(15, 10);
|
||||
ChangeDocument(new OffsetChangeMapEntry(5, 0, 2));
|
||||
CheckSegments();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ReplacementBeforeAllSegmentsTouchingFirstSegment()
|
||||
{
|
||||
TestTextSegment s1 = AddSegment(10, 20);
|
||||
TestTextSegment s2 = AddSegment(15, 10);
|
||||
ChangeDocument(new OffsetChangeMapEntry(5, 5, 2));
|
||||
CheckSegments();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InsertionAfterAllSegments()
|
||||
{
|
||||
TestTextSegment s1 = AddSegment(10, 20);
|
||||
TestTextSegment s2 = AddSegment(15, 10);
|
||||
ChangeDocument(new OffsetChangeMapEntry(45, 0, 2));
|
||||
CheckSegments();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ReplacementOverlappingWithStartOfSegment()
|
||||
{
|
||||
TestTextSegment s1 = AddSegment(10, 20);
|
||||
TestTextSegment s2 = AddSegment(15, 10);
|
||||
ChangeDocument(new OffsetChangeMapEntry(9, 7, 2));
|
||||
CheckSegments();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ReplacementOfWholeSegment()
|
||||
{
|
||||
TestTextSegment s1 = AddSegment(10, 20);
|
||||
TestTextSegment s2 = AddSegment(15, 10);
|
||||
ChangeDocument(new OffsetChangeMapEntry(10, 20, 30));
|
||||
CheckSegments();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ReplacementAtEndOfSegment()
|
||||
{
|
||||
TestTextSegment s1 = AddSegment(10, 20);
|
||||
TestTextSegment s2 = AddSegment(15, 10);
|
||||
ChangeDocument(new OffsetChangeMapEntry(24, 6, 10));
|
||||
CheckSegments();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RandomizedNoDocumentChanges()
|
||||
{
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
// Console.WriteLine(tree.GetTreeAsString());
|
||||
// Console.WriteLine("Iteration " + i);
|
||||
|
||||
switch (rnd.Next(3)) {
|
||||
case 0:
|
||||
AddSegment(rnd.Next(500), rnd.Next(30));
|
||||
break;
|
||||
case 1:
|
||||
AddSegment(rnd.Next(500), rnd.Next(300));
|
||||
break;
|
||||
case 2:
|
||||
if (tree.Count > 0) {
|
||||
RemoveSegment(expectedSegments[rnd.Next(tree.Count)]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
CheckSegments();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RandomizedCloseNoDocumentChanges()
|
||||
{
|
||||
// Lots of segments in a short document. Tests how the tree copes with multiple identical segments.
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
switch (rnd.Next(3)) {
|
||||
case 0:
|
||||
AddSegment(rnd.Next(20), rnd.Next(10));
|
||||
break;
|
||||
case 1:
|
||||
AddSegment(rnd.Next(20), rnd.Next(20));
|
||||
break;
|
||||
case 2:
|
||||
if (tree.Count > 0) {
|
||||
RemoveSegment(expectedSegments[rnd.Next(tree.Count)]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
CheckSegments();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RandomizedRetrievalTest()
|
||||
{
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
AddSegment(rnd.Next(500), rnd.Next(300));
|
||||
}
|
||||
CheckSegments();
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
TestRetrieval(rnd.Next(1000) - 100, rnd.Next(500));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RandomizedWithDocumentChanges()
|
||||
{
|
||||
for (int i = 0; i < 500; i++) {
|
||||
// Console.WriteLine(tree.GetTreeAsString());
|
||||
// Console.WriteLine("Iteration " + i);
|
||||
|
||||
switch (rnd.Next(6)) {
|
||||
case 0:
|
||||
AddSegment(rnd.Next(500), rnd.Next(30));
|
||||
break;
|
||||
case 1:
|
||||
AddSegment(rnd.Next(500), rnd.Next(300));
|
||||
break;
|
||||
case 2:
|
||||
if (tree.Count > 0) {
|
||||
RemoveSegment(expectedSegments[rnd.Next(tree.Count)]);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
ChangeDocument(new OffsetChangeMapEntry(rnd.Next(800), rnd.Next(50), rnd.Next(50)));
|
||||
break;
|
||||
case 4:
|
||||
ChangeDocument(new OffsetChangeMapEntry(rnd.Next(800), 0, rnd.Next(50)));
|
||||
break;
|
||||
case 5:
|
||||
ChangeDocument(new OffsetChangeMapEntry(rnd.Next(800), rnd.Next(50), 0));
|
||||
break;
|
||||
}
|
||||
CheckSegments();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RandomizedWithDocumentChangesClose()
|
||||
{
|
||||
for (int i = 0; i < 500; i++) {
|
||||
// Console.WriteLine(tree.GetTreeAsString());
|
||||
// Console.WriteLine("Iteration " + i);
|
||||
|
||||
switch (rnd.Next(6)) {
|
||||
case 0:
|
||||
AddSegment(rnd.Next(50), rnd.Next(30));
|
||||
break;
|
||||
case 1:
|
||||
AddSegment(rnd.Next(50), rnd.Next(3));
|
||||
break;
|
||||
case 2:
|
||||
if (tree.Count > 0) {
|
||||
RemoveSegment(expectedSegments[rnd.Next(tree.Count)]);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
ChangeDocument(new OffsetChangeMapEntry(rnd.Next(80), rnd.Next(10), rnd.Next(10)));
|
||||
break;
|
||||
case 4:
|
||||
ChangeDocument(new OffsetChangeMapEntry(rnd.Next(80), 0, rnd.Next(10)));
|
||||
break;
|
||||
case 5:
|
||||
ChangeDocument(new OffsetChangeMapEntry(rnd.Next(80), rnd.Next(10), 0));
|
||||
break;
|
||||
}
|
||||
CheckSegments();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// 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 NUnit.Framework;
|
||||
|
||||
namespace AvaloniaEdit.Document
|
||||
{
|
||||
[TestFixture]
|
||||
public class TextUtilitiesTests
|
||||
{
|
||||
#region GetWhitespaceAfter
|
||||
[Test]
|
||||
public void TestGetWhitespaceAfter()
|
||||
{
|
||||
Assert.AreEqual(new SimpleSegment(2, 3), TextUtilities.GetWhitespaceAfter(new StringTextSource("a \t \tb"), 2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestGetWhitespaceAfterDoesNotSkipNewLine()
|
||||
{
|
||||
Assert.AreEqual(new SimpleSegment(2, 3), TextUtilities.GetWhitespaceAfter(new StringTextSource("a \t \tb"), 2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestGetWhitespaceAfterEmptyResult()
|
||||
{
|
||||
Assert.AreEqual(new SimpleSegment(2, 0), TextUtilities.GetWhitespaceAfter(new StringTextSource("a b"), 2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestGetWhitespaceAfterEndOfString()
|
||||
{
|
||||
Assert.AreEqual(new SimpleSegment(2, 0), TextUtilities.GetWhitespaceAfter(new StringTextSource("a "), 2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestGetWhitespaceAfterUntilEndOfString()
|
||||
{
|
||||
Assert.AreEqual(new SimpleSegment(2, 3), TextUtilities.GetWhitespaceAfter(new StringTextSource("a \t \t"), 2));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetWhitespaceBefore
|
||||
[Test]
|
||||
public void TestGetWhitespaceBefore()
|
||||
{
|
||||
Assert.AreEqual(new SimpleSegment(1, 3), TextUtilities.GetWhitespaceBefore(new StringTextSource("a\t \t b"), 4));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestGetWhitespaceBeforeDoesNotSkipNewLine()
|
||||
{
|
||||
Assert.AreEqual(new SimpleSegment(2, 1), TextUtilities.GetWhitespaceBefore(new StringTextSource("a\n b"), 3));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestGetWhitespaceBeforeEmptyResult()
|
||||
{
|
||||
Assert.AreEqual(new SimpleSegment(2, 0), TextUtilities.GetWhitespaceBefore(new StringTextSource(" a b"), 2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestGetWhitespaceBeforeStartOfString()
|
||||
{
|
||||
Assert.AreEqual(new SimpleSegment(0, 0), TextUtilities.GetWhitespaceBefore(new StringTextSource(" a"), 0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestGetWhitespaceBeforeUntilStartOfString()
|
||||
{
|
||||
Assert.AreEqual(new SimpleSegment(0, 2), TextUtilities.GetWhitespaceBefore(new StringTextSource(" \t a"), 2));
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// 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 NUnit.Framework;
|
||||
|
||||
namespace AvaloniaEdit.Document
|
||||
{
|
||||
public class UndoStackTests
|
||||
{
|
||||
[Test]
|
||||
public void ContinueUndoGroup()
|
||||
{
|
||||
var doc = new TextDocument();
|
||||
doc.Insert(0, "a");
|
||||
doc.UndoStack.StartContinuedUndoGroup();
|
||||
doc.Insert(1, "b");
|
||||
doc.UndoStack.EndUndoGroup();
|
||||
doc.UndoStack.Undo();
|
||||
Assert.AreEqual("", doc.Text);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ContinueEmptyUndoGroup()
|
||||
{
|
||||
var doc = new TextDocument();
|
||||
doc.Insert(0, "a");
|
||||
doc.UndoStack.StartUndoGroup();
|
||||
doc.UndoStack.EndUndoGroup();
|
||||
doc.UndoStack.StartContinuedUndoGroup();
|
||||
doc.Insert(1, "b");
|
||||
doc.UndoStack.EndUndoGroup();
|
||||
doc.UndoStack.Undo();
|
||||
Assert.AreEqual("a", doc.Text);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ContinueEmptyUndoGroup_WithOptionalEntries()
|
||||
{
|
||||
var doc = new TextDocument();
|
||||
doc.Insert(0, "a");
|
||||
doc.UndoStack.StartUndoGroup();
|
||||
doc.UndoStack.PushOptional(new StubUndoableAction());
|
||||
doc.UndoStack.EndUndoGroup();
|
||||
doc.UndoStack.StartContinuedUndoGroup();
|
||||
doc.Insert(1, "b");
|
||||
doc.UndoStack.EndUndoGroup();
|
||||
doc.UndoStack.Undo();
|
||||
Assert.AreEqual("a", doc.Text);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmptyContinuationGroup()
|
||||
{
|
||||
var doc = new TextDocument();
|
||||
doc.Insert(0, "a");
|
||||
doc.UndoStack.StartContinuedUndoGroup();
|
||||
doc.UndoStack.EndUndoGroup();
|
||||
doc.UndoStack.StartContinuedUndoGroup();
|
||||
doc.Insert(1, "b");
|
||||
doc.UndoStack.EndUndoGroup();
|
||||
doc.UndoStack.Undo();
|
||||
Assert.AreEqual("", doc.Text);
|
||||
}
|
||||
|
||||
class StubUndoableAction : IUndoableOperation
|
||||
{
|
||||
public void Undo()
|
||||
{
|
||||
}
|
||||
|
||||
public void Redo()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// 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.Text;
|
||||
using AvaloniaEdit.AvaloniaMocks;
|
||||
using AvaloniaEdit.Document;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace AvaloniaEdit.Editing
|
||||
{
|
||||
[TestFixture]
|
||||
public class ChangeDocumentTests
|
||||
{
|
||||
[Test]
|
||||
public void ClearCaretAndSelectionOnDocumentChange()
|
||||
{
|
||||
using (UnitTestApplication.Start(new TestServices(renderInterface: new MockPlatformRenderInterface())))
|
||||
{
|
||||
TextArea textArea = new TextArea();
|
||||
textArea.Document = new TextDocument("1\n2\n3\n4th line");
|
||||
textArea.Caret.Offset = 6;
|
||||
textArea.Selection = Selection.Create(textArea, 3, 6);
|
||||
textArea.Document = new TextDocument("1\n2nd");
|
||||
Assert.AreEqual(0, textArea.Caret.Offset);
|
||||
Assert.AreEqual(new TextLocation(1, 1), textArea.Caret.Location);
|
||||
Assert.IsTrue(textArea.Selection.IsEmpty);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SetDocumentToNull()
|
||||
{
|
||||
using (UnitTestApplication.Start(new TestServices(renderInterface: new MockPlatformRenderInterface())))
|
||||
{
|
||||
TextArea textArea = new TextArea();
|
||||
textArea.Document = new TextDocument("1\n2\n3\n4th line");
|
||||
textArea.Caret.Offset = 6;
|
||||
textArea.Selection = Selection.Create(textArea, 3, 6);
|
||||
textArea.Document = null;
|
||||
Assert.AreEqual(0, textArea.Caret.Offset);
|
||||
Assert.AreEqual(new TextLocation(1, 1), textArea.Caret.Location);
|
||||
Assert.IsTrue(textArea.Selection.IsEmpty);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CheckEventOrderOnDocumentChange()
|
||||
{
|
||||
using (UnitTestApplication.Start(new TestServices(renderInterface: new MockPlatformRenderInterface())))
|
||||
{
|
||||
TextArea textArea = new TextArea();
|
||||
TextDocument newDocument = new TextDocument();
|
||||
StringBuilder b = new StringBuilder();
|
||||
textArea.TextView.DocumentChanged += delegate
|
||||
{
|
||||
b.Append("TextView.DocumentChanged;");
|
||||
Assert.AreSame(newDocument, textArea.TextView.Document);
|
||||
Assert.AreSame(newDocument, textArea.Document);
|
||||
};
|
||||
textArea.DocumentChanged += delegate
|
||||
{
|
||||
b.Append("TextArea.DocumentChanged;");
|
||||
Assert.AreSame(newDocument, textArea.TextView.Document);
|
||||
Assert.AreSame(newDocument, textArea.Document);
|
||||
};
|
||||
textArea.Document = newDocument;
|
||||
Assert.AreEqual("TextView.DocumentChanged;TextArea.DocumentChanged;", b.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,183 @@
|
|||
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// 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 AvaloniaEdit.Document;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace AvaloniaEdit.Editing
|
||||
{
|
||||
[TestFixture]
|
||||
public class TextSegmentReadOnlySectionTests
|
||||
{
|
||||
TextSegmentCollection<TextSegment> segments;
|
||||
TextSegmentReadOnlySectionProvider<TextSegment> provider;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
segments = new TextSegmentCollection<TextSegment>();
|
||||
provider = new TextSegmentReadOnlySectionProvider<TextSegment>(segments);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InsertionPossibleWhenNothingIsReadOnly()
|
||||
{
|
||||
Assert.IsTrue(provider.CanInsert(0));
|
||||
Assert.IsTrue(provider.CanInsert(100));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeletionPossibleWhenNothingIsReadOnly()
|
||||
{
|
||||
var result = provider.GetDeletableSegments(new SimpleSegment(10, 20)).ToList();
|
||||
Assert.AreEqual(1, result.Count);
|
||||
Assert.AreEqual(10, result[0].Offset);
|
||||
Assert.AreEqual(20, result[0].Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmptyDeletionPossibleWhenNothingIsReadOnly()
|
||||
{
|
||||
var result = provider.GetDeletableSegments(new SimpleSegment(10, 0)).ToList();
|
||||
Assert.AreEqual(1, result.Count);
|
||||
Assert.AreEqual(10, result[0].Offset);
|
||||
Assert.AreEqual(0, result[0].Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InsertionPossibleBeforeReadOnlySegment()
|
||||
{
|
||||
segments.Add(new TextSegment { StartOffset = 10, EndOffset = 15 });
|
||||
Assert.IsTrue(provider.CanInsert(5));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InsertionPossibleAtStartOfReadOnlySegment()
|
||||
{
|
||||
segments.Add(new TextSegment { StartOffset = 10, EndOffset = 15 });
|
||||
Assert.IsTrue(provider.CanInsert(10));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InsertionImpossibleInsideReadOnlySegment()
|
||||
{
|
||||
segments.Add(new TextSegment { StartOffset = 10, EndOffset = 15 });
|
||||
Assert.IsFalse(provider.CanInsert(11));
|
||||
Assert.IsFalse(provider.CanInsert(12));
|
||||
Assert.IsFalse(provider.CanInsert(13));
|
||||
Assert.IsFalse(provider.CanInsert(14));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InsertionPossibleAtEndOfReadOnlySegment()
|
||||
{
|
||||
segments.Add(new TextSegment { StartOffset = 10, EndOffset = 15 });
|
||||
Assert.IsTrue(provider.CanInsert(15));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InsertionPossibleBetweenReadOnlySegments()
|
||||
{
|
||||
segments.Add(new TextSegment { StartOffset = 10, EndOffset = 15 });
|
||||
segments.Add(new TextSegment { StartOffset = 15, EndOffset = 20 });
|
||||
Assert.IsTrue(provider.CanInsert(15));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeletionImpossibleInReadOnlySegment()
|
||||
{
|
||||
segments.Add(new TextSegment { StartOffset = 10, Length = 5 });
|
||||
var result = provider.GetDeletableSegments(new SimpleSegment(11, 2)).ToList();
|
||||
Assert.AreEqual(0, result.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmptyDeletionImpossibleInReadOnlySegment()
|
||||
{
|
||||
segments.Add(new TextSegment { StartOffset = 10, Length = 5 });
|
||||
var result = provider.GetDeletableSegments(new SimpleSegment(11, 0)).ToList();
|
||||
Assert.AreEqual(0, result.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmptyDeletionPossibleAtStartOfReadOnlySegment()
|
||||
{
|
||||
segments.Add(new TextSegment { StartOffset = 10, Length = 5 });
|
||||
var result = provider.GetDeletableSegments(new SimpleSegment(10, 0)).ToList();
|
||||
Assert.AreEqual(1, result.Count);
|
||||
Assert.AreEqual(10, result[0].Offset);
|
||||
Assert.AreEqual(0, result[0].Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmptyDeletionPossibleAtEndOfReadOnlySegment()
|
||||
{
|
||||
segments.Add(new TextSegment { StartOffset = 10, Length = 5 });
|
||||
var result = provider.GetDeletableSegments(new SimpleSegment(15, 0)).ToList();
|
||||
Assert.AreEqual(1, result.Count);
|
||||
Assert.AreEqual(15, result[0].Offset);
|
||||
Assert.AreEqual(0, result[0].Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeletionAroundReadOnlySegment()
|
||||
{
|
||||
segments.Add(new TextSegment { StartOffset = 20, Length = 5 });
|
||||
var result = provider.GetDeletableSegments(new SimpleSegment(15, 16)).ToList();
|
||||
Assert.AreEqual(2, result.Count);
|
||||
Assert.AreEqual(15, result[0].Offset);
|
||||
Assert.AreEqual(5, result[0].Length);
|
||||
Assert.AreEqual(25, result[1].Offset);
|
||||
Assert.AreEqual(6, result[1].Length);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeleteLastCharacterInReadOnlySegment()
|
||||
{
|
||||
segments.Add(new TextSegment { StartOffset = 20, Length = 5 });
|
||||
var result = provider.GetDeletableSegments(new SimpleSegment(24, 1)).ToList();
|
||||
Assert.AreEqual(0, result.Count);
|
||||
/* // we would need this result for the old Backspace code so that the last character doesn't get selected:
|
||||
Assert.AreEqual(1, result.Count);
|
||||
Assert.AreEqual(25, result[0].Offset);
|
||||
Assert.AreEqual(0, result[0].Length);*/
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeleteFirstCharacterInReadOnlySegment()
|
||||
{
|
||||
segments.Add(new TextSegment { StartOffset = 20, Length = 5 });
|
||||
var result = provider.GetDeletableSegments(new SimpleSegment(20, 1)).ToList();
|
||||
Assert.AreEqual(0, result.Count);
|
||||
/* // we would need this result for the old Delete code so that the first character doesn't get selected:
|
||||
Assert.AreEqual(1, result.Count);
|
||||
Assert.AreEqual(2, result[0].Offset);
|
||||
Assert.AreEqual(0, result[0].Length);*/
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DeleteWholeReadOnlySegment()
|
||||
{
|
||||
segments.Add(new TextSegment { StartOffset = 20, Length = 5 });
|
||||
var result = provider.GetDeletableSegments(new SimpleSegment(20, 5)).ToList();
|
||||
Assert.AreEqual(0, result.Count);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// 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.Collections.Generic;
|
||||
using AvaloniaEdit.Document;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace AvaloniaEdit.Highlighting
|
||||
{
|
||||
[TestFixture]
|
||||
public class HighlightedLineMergeTests
|
||||
{
|
||||
IDocument document = new TextDocument(new string(' ', 20));
|
||||
|
||||
[Test]
|
||||
public void SimpleMerge1()
|
||||
{
|
||||
HighlightedLine baseLine = new HighlightedLine(document, document.GetLineByNumber(1));
|
||||
baseLine.Sections.Add(MakeSection(0, 1, "B"));
|
||||
|
||||
HighlightedLine additionalLine = new HighlightedLine(document, document.GetLineByNumber(1));
|
||||
additionalLine.Sections.Add(MakeSection(0, 2, "A"));
|
||||
|
||||
baseLine.MergeWith(additionalLine);
|
||||
// The additional section gets split up so that it fits into the tree structure
|
||||
Assert.That(baseLine.Sections, Is.EqualTo(
|
||||
new[] {
|
||||
MakeSection(0, 1, "B"),
|
||||
MakeSection(0, 1, "A"),
|
||||
MakeSection(1, 2, "A")
|
||||
}).Using(new SectionComparer()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SimpleMerge2()
|
||||
{
|
||||
HighlightedLine baseLine = new HighlightedLine(document, document.GetLineByNumber(1));
|
||||
baseLine.Sections.Add(MakeSection(0, 1, "B"));
|
||||
baseLine.Sections.Add(MakeSection(0, 1, "BN"));
|
||||
|
||||
HighlightedLine additionalLine = new HighlightedLine(document, document.GetLineByNumber(1));
|
||||
additionalLine.Sections.Add(MakeSection(0, 2, "A"));
|
||||
|
||||
baseLine.MergeWith(additionalLine);
|
||||
// The additional section gets split up so that it fits into the tree structure
|
||||
Assert.That(baseLine.Sections, Is.EqualTo(
|
||||
new[] {
|
||||
MakeSection(0, 1, "B"),
|
||||
MakeSection(0, 1, "BN"),
|
||||
MakeSection(0, 1, "A"),
|
||||
MakeSection(1, 2, "A")
|
||||
}).Using(new SectionComparer()));
|
||||
}
|
||||
|
||||
HighlightedSection MakeSection(int start, int end, string name)
|
||||
{
|
||||
return new HighlightedSection { Offset = start, Length = end - start, Color = new HighlightingColor { Name = name }};
|
||||
}
|
||||
|
||||
class SectionComparer : IEqualityComparer<HighlightedSection>
|
||||
{
|
||||
public bool Equals(HighlightedSection a, HighlightedSection b)
|
||||
{
|
||||
return a.Offset == b.Offset && a.Length == b.Length && a.Color.Name == b.Color.Name;
|
||||
}
|
||||
|
||||
public int GetHashCode(HighlightedSection obj)
|
||||
{
|
||||
return obj.Offset;
|
||||
}
|
||||
}
|
||||
|
||||
#region Automatic Test
|
||||
/*
|
||||
const int combinations = 6 * 3 * 4 * 3 * 3 * 4;
|
||||
HighlightingColor[] baseLineColors = {
|
||||
new HighlightingColor { Name = "Base-A" },
|
||||
new HighlightingColor { Name = "Base-B" },
|
||||
new HighlightingColor { Name = "Base-N" },
|
||||
new HighlightingColor { Name = "Base-C" }
|
||||
};
|
||||
HighlightingColor[] additionalLineColors = {
|
||||
new HighlightingColor { Name = "Add-A" },
|
||||
new HighlightingColor { Name = "Add-B" },
|
||||
new HighlightingColor { Name = "Add-N" },
|
||||
new HighlightingColor { Name = "Add-C" }
|
||||
};
|
||||
|
||||
HighlightedLine BuildHighlightedLine(int num, HighlightingColor[] colors)
|
||||
{
|
||||
// We are build a HighlightedLine with 4 segments:
|
||||
// A B C (top-level) and N nested within B.
|
||||
// These are the integers controlling the generating process:
|
||||
|
||||
int aStart = GetNum(ref num, 5); // start offset of A
|
||||
int aLength = GetNum(ref num, 2); // length of A
|
||||
|
||||
int bDistance = GetNum(ref num, 3); // distance from start of B to end of A
|
||||
int bStart = aStart + aLength + bDistance;
|
||||
int nDistance = GetNum(ref num, 2); // distance from start of B to start of N, range 0-2
|
||||
int nLength = GetNum(ref num, 2); // length of N
|
||||
int bEndDistance = GetNum(ref num, 2); // distance from end of N to end of B
|
||||
int bLength = nDistance + nLength + bEndDistance;
|
||||
|
||||
int cDistance = GetNum(ref num, 3); // distance from end of B to start of C
|
||||
int cStart = bStart + bLength + cDistance;
|
||||
int cLength = 1;
|
||||
Assert.AreEqual(0, num);
|
||||
|
||||
var documentLine = document.GetLineByNumber(1);
|
||||
HighlightedLine line = new HighlightedLine(document, documentLine);
|
||||
line.Sections.Add(new HighlightedSection { Offset = aStart, Length = aLength, Color = colors[0] });
|
||||
line.Sections.Add(new HighlightedSection { Offset = bStart, Length = bLength, Color = colors[1] });
|
||||
line.Sections.Add(new HighlightedSection { Offset = bStart + nDistance, Length = nLength, Color = colors[2] });
|
||||
line.Sections.Add(new HighlightedSection { Offset = cStart, Length = cLength, Color = colors[3] });
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a number between 0 and max (inclusive)
|
||||
/// </summary>
|
||||
int GetNum(ref int num, int max)
|
||||
{
|
||||
int result = num % (max+1);
|
||||
num = num / (max + 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAll()
|
||||
{
|
||||
for (int c1 = 0; c1 < combinations; c1++) {
|
||||
HighlightedLine line1 = BuildHighlightedLine(c1, additionalLineColors);
|
||||
for (int c2 = 0; c2 < combinations; c2++) {
|
||||
HighlightedLine line2 = BuildHighlightedLine(c2, baseLineColors);
|
||||
HighlightingColor[] expectedPerCharColors = new HighlightingColor[document.TextLength];
|
||||
ApplyColors(expectedPerCharColors, line2);
|
||||
ApplyColors(expectedPerCharColors, line1);
|
||||
try {
|
||||
line2.MergeWith(line1);
|
||||
} catch (InvalidOperationException ex) {
|
||||
throw new InvalidOperationException(string.Format("Error for c1 = {0}, c2 = {1}", c1, c2), ex);
|
||||
}
|
||||
|
||||
HighlightingColor[] actualPerCharColors = new HighlightingColor[document.TextLength];
|
||||
ApplyColors(actualPerCharColors, line2);
|
||||
Assert.AreEqual(expectedPerCharColors, actualPerCharColors, string.Format("c1 = {0}, c2 = {1}", c1, c2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyColors(HighlightingColor[] perCharColors, HighlightedLine line)
|
||||
{
|
||||
foreach (var section in line.Sections) {
|
||||
for (int i = 0; i < section.Length; i++) {
|
||||
perCharColors[section.Offset + i] = section.Color;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// 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 System.Windows;
|
||||
using AvaloniaEdit.Document;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace AvaloniaEdit.Highlighting
|
||||
{
|
||||
[TestFixture]
|
||||
public class HtmlClipboardTests
|
||||
{
|
||||
TextDocument document;
|
||||
DocumentHighlighter highlighter;
|
||||
|
||||
public HtmlClipboardTests()
|
||||
{
|
||||
document = new TextDocument("using System.Text;\n\tstring text = SomeMethod();");
|
||||
highlighter = new DocumentHighlighter(document, HighlightingManager.Instance.GetDefinition("C#"));
|
||||
}
|
||||
|
||||
[Test, Ignore("")]
|
||||
public void FullDocumentTest()
|
||||
{
|
||||
var segment = new TextSegment { StartOffset = 0, Length = document.TextLength };
|
||||
string html = HtmlClipboard.CreateHtmlFragment(document, highlighter, segment, new HtmlOptions());
|
||||
Assert.AreEqual("<span style=\"color: #008000; font-weight: bold; \">using</span> System.Text;<br>" + Environment.NewLine +
|
||||
" <span style=\"color: #ff0000; \">string</span> " +
|
||||
"text = <span style=\"color: #191970; font-weight: bold; \">SomeMethod</span>();", html);
|
||||
}
|
||||
|
||||
[Test, Ignore("")]
|
||||
public void PartOfHighlightedWordTest()
|
||||
{
|
||||
var segment = new TextSegment { StartOffset = 1, Length = 3 };
|
||||
string html = HtmlClipboard.CreateHtmlFragment(document, highlighter, segment, new HtmlOptions());
|
||||
Assert.AreEqual("<span style=\"color: #008000; font-weight: bold; \">sin</span>", html);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// 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 System.Linq;
|
||||
using AvaloniaEdit.Document;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace AvaloniaEdit.Search
|
||||
{
|
||||
//[TestFixture]
|
||||
//public class FindTests
|
||||
//{
|
||||
// [Test]
|
||||
// public void SkipWordBorderSimple()
|
||||
// {
|
||||
// var strategy = SearchStrategyFactory.Create("All", false, true, SearchMode.Normal);
|
||||
// var text = new StringTextSource(" FindAllTests ");
|
||||
// var results = strategy.FindAll(text, 0, text.TextLength).ToArray();
|
||||
|
||||
// Assert.IsEmpty(results, "No results should be found!");
|
||||
// }
|
||||
|
||||
// [Test]
|
||||
// public void SkipWordBorder()
|
||||
// {
|
||||
// var strategy = SearchStrategyFactory.Create("AllTests", false, true, SearchMode.Normal);
|
||||
// var text = new StringTextSource("name=\"{FindAllTests}\"");
|
||||
// var results = strategy.FindAll(text, 0, text.TextLength).ToArray();
|
||||
|
||||
// Assert.IsEmpty(results, "No results should be found!");
|
||||
// }
|
||||
|
||||
// [Test]
|
||||
// public void SkipWordBorder2()
|
||||
// {
|
||||
// var strategy = SearchStrategyFactory.Create("AllTests", false, true, SearchMode.Normal);
|
||||
// var text = new StringTextSource("name=\"FindAllTests ");
|
||||
// var results = strategy.FindAll(text, 0, text.TextLength).ToArray();
|
||||
|
||||
// Assert.IsEmpty(results, "No results should be found!");
|
||||
// }
|
||||
|
||||
// [Test]
|
||||
// public void SkipWordBorder3()
|
||||
// {
|
||||
// var strategy = SearchStrategyFactory.Create("// find", false, true, SearchMode.Normal);
|
||||
// var text = new StringTextSource(" // findtest");
|
||||
// var results = strategy.FindAll(text, 0, text.TextLength).ToArray();
|
||||
|
||||
// Assert.IsEmpty(results, "No results should be found!");
|
||||
// }
|
||||
|
||||
// [Test]
|
||||
// public void WordBorderTest()
|
||||
// {
|
||||
// var strategy = SearchStrategyFactory.Create("// find", false, true, SearchMode.Normal);
|
||||
// var text = new StringTextSource(" // find me");
|
||||
// var results = strategy.FindAll(text, 0, text.TextLength).ToArray();
|
||||
|
||||
// Assert.AreEqual(1, results.Length, "One result should be found!");
|
||||
// Assert.AreEqual(" ".Length, results[0].Offset);
|
||||
// Assert.AreEqual("// find".Length, results[0].Length);
|
||||
// }
|
||||
|
||||
// [Test]
|
||||
// public void ResultAtStart()
|
||||
// {
|
||||
// var strategy = SearchStrategyFactory.Create("result", false, true, SearchMode.Normal);
|
||||
// var text = new StringTextSource("result // find me");
|
||||
// var results = strategy.FindAll(text, 0, text.TextLength).ToArray();
|
||||
|
||||
// Assert.AreEqual(1, results.Length, "One result should be found!");
|
||||
// Assert.AreEqual(0, results[0].Offset);
|
||||
// Assert.AreEqual("result".Length, results[0].Length);
|
||||
// }
|
||||
|
||||
// [Test]
|
||||
// public void ResultAtEnd()
|
||||
// {
|
||||
// var strategy = SearchStrategyFactory.Create("me", false, true, SearchMode.Normal);
|
||||
// var text = new StringTextSource("result // find me");
|
||||
// var results = strategy.FindAll(text, 0, text.TextLength).ToArray();
|
||||
|
||||
// Assert.AreEqual(1, results.Length, "One result should be found!");
|
||||
// Assert.AreEqual("result // find ".Length, results[0].Offset);
|
||||
// Assert.AreEqual("me".Length, results[0].Length);
|
||||
// }
|
||||
|
||||
// [Test]
|
||||
// public void TextWithDots()
|
||||
// {
|
||||
// var strategy = SearchStrategyFactory.Create("Text", false, true, SearchMode.Normal);
|
||||
// var text = new StringTextSource(".Text.");
|
||||
// var results = strategy.FindAll(text, 0, text.TextLength).ToArray();
|
||||
|
||||
// Assert.AreEqual(1, results.Length, "One result should be found!");
|
||||
// Assert.AreEqual(".".Length, results[0].Offset);
|
||||
// Assert.AreEqual("Text".Length, results[0].Length);
|
||||
// }
|
||||
|
||||
// [Test]
|
||||
// public void SimpleTest()
|
||||
// {
|
||||
// var strategy = SearchStrategyFactory.Create("AllTests", false, false, SearchMode.Normal);
|
||||
// var text = new StringTextSource("name=\"FindAllTests ");
|
||||
// var results = strategy.FindAll(text, 0, text.TextLength).ToArray();
|
||||
|
||||
// Assert.AreEqual(1, results.Length, "One result should be found!");
|
||||
// Assert.AreEqual("name=\"Find".Length, results[0].Offset);
|
||||
// Assert.AreEqual("AllTests".Length, results[0].Length);
|
||||
// }
|
||||
//}
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// 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 AvaloniaEdit.Document;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace AvaloniaEdit.Utils
|
||||
{
|
||||
[TestFixture]
|
||||
public class CaretNavigationTests
|
||||
{
|
||||
int GetNextCaretStop(string text, int offset, CaretPositioningMode mode)
|
||||
{
|
||||
return TextUtilities.GetNextCaretPosition(new StringTextSource(text), offset, LogicalDirection.Forward, mode);
|
||||
}
|
||||
|
||||
int GetPrevCaretStop(string text, int offset, CaretPositioningMode mode)
|
||||
{
|
||||
return TextUtilities.GetNextCaretPosition(new StringTextSource(text), offset, LogicalDirection.Backward, mode);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CaretStopInEmptyString()
|
||||
{
|
||||
Assert.AreEqual(0, GetNextCaretStop("", -1, CaretPositioningMode.Normal));
|
||||
Assert.AreEqual(-1, GetNextCaretStop("", 0, CaretPositioningMode.Normal));
|
||||
Assert.AreEqual(-1, GetPrevCaretStop("", 0, CaretPositioningMode.Normal));
|
||||
Assert.AreEqual(0, GetPrevCaretStop("", 1, CaretPositioningMode.Normal));
|
||||
|
||||
Assert.AreEqual(-1, GetNextCaretStop("", -1, CaretPositioningMode.WordStart));
|
||||
Assert.AreEqual(-1, GetNextCaretStop("", -1, CaretPositioningMode.WordBorder));
|
||||
Assert.AreEqual(-1, GetPrevCaretStop("", 1, CaretPositioningMode.WordStart));
|
||||
Assert.AreEqual(-1, GetPrevCaretStop("", 1, CaretPositioningMode.WordBorder));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void StartOfDocumentWithWordStart()
|
||||
{
|
||||
Assert.AreEqual(0, GetNextCaretStop("word", -1, CaretPositioningMode.Normal));
|
||||
Assert.AreEqual(0, GetNextCaretStop("word", -1, CaretPositioningMode.WordStart));
|
||||
Assert.AreEqual(0, GetNextCaretStop("word", -1, CaretPositioningMode.WordBorder));
|
||||
|
||||
Assert.AreEqual(0, GetPrevCaretStop("word", 1, CaretPositioningMode.Normal));
|
||||
Assert.AreEqual(0, GetPrevCaretStop("word", 1, CaretPositioningMode.WordStart));
|
||||
Assert.AreEqual(0, GetPrevCaretStop("word", 1, CaretPositioningMode.WordBorder));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void StartOfDocumentNoWordStart()
|
||||
{
|
||||
Assert.AreEqual(0, GetNextCaretStop(" word", -1, CaretPositioningMode.Normal));
|
||||
Assert.AreEqual(1, GetNextCaretStop(" word", -1, CaretPositioningMode.WordStart));
|
||||
Assert.AreEqual(1, GetNextCaretStop(" word", -1, CaretPositioningMode.WordBorder));
|
||||
|
||||
Assert.AreEqual(0, GetPrevCaretStop(" word", 1, CaretPositioningMode.Normal));
|
||||
Assert.AreEqual(-1, GetPrevCaretStop(" word", 1, CaretPositioningMode.WordStart));
|
||||
Assert.AreEqual(-1, GetPrevCaretStop(" word", 1, CaretPositioningMode.WordBorder));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EndOfDocumentWordBorder()
|
||||
{
|
||||
Assert.AreEqual(4, GetNextCaretStop("word", 3, CaretPositioningMode.Normal));
|
||||
Assert.AreEqual(-1, GetNextCaretStop("word", 3, CaretPositioningMode.WordStart));
|
||||
Assert.AreEqual(4, GetNextCaretStop("word", 3, CaretPositioningMode.WordBorder));
|
||||
|
||||
Assert.AreEqual(4, GetPrevCaretStop("word", 5, CaretPositioningMode.Normal));
|
||||
Assert.AreEqual(0, GetPrevCaretStop("word", 5, CaretPositioningMode.WordStart));
|
||||
Assert.AreEqual(4, GetPrevCaretStop("word", 5, CaretPositioningMode.WordBorder));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EndOfDocumentNoWordBorder()
|
||||
{
|
||||
Assert.AreEqual(4, GetNextCaretStop("txt ", 3, CaretPositioningMode.Normal));
|
||||
Assert.AreEqual(-1, GetNextCaretStop("txt ", 3, CaretPositioningMode.WordStart));
|
||||
Assert.AreEqual(-1, GetNextCaretStop("txt ", 3, CaretPositioningMode.WordBorder));
|
||||
|
||||
Assert.AreEqual(4, GetPrevCaretStop("txt ", 5, CaretPositioningMode.Normal));
|
||||
Assert.AreEqual(0, GetPrevCaretStop("txt ", 5, CaretPositioningMode.WordStart));
|
||||
Assert.AreEqual(3, GetPrevCaretStop("txt ", 5, CaretPositioningMode.WordBorder));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SingleCharacterOutsideBMP()
|
||||
{
|
||||
string c = "\U0001D49E";
|
||||
Assert.AreEqual(2, GetNextCaretStop(c, 0, CaretPositioningMode.Normal));
|
||||
Assert.AreEqual(0, GetPrevCaretStop(c, 2, CaretPositioningMode.Normal));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DetectWordBordersOutsideBMP()
|
||||
{
|
||||
string c = " a\U0001D49Eb ";
|
||||
Assert.AreEqual(1, GetNextCaretStop(c, 0, CaretPositioningMode.WordBorder));
|
||||
Assert.AreEqual(5, GetNextCaretStop(c, 1, CaretPositioningMode.WordBorder));
|
||||
|
||||
Assert.AreEqual(5, GetPrevCaretStop(c, 6, CaretPositioningMode.WordBorder));
|
||||
Assert.AreEqual(1, GetPrevCaretStop(c, 5, CaretPositioningMode.WordBorder));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DetectWordBordersOutsideBMP2()
|
||||
{
|
||||
string c = " \U0001D49E\U0001D4AA ";
|
||||
Assert.AreEqual(1, GetNextCaretStop(c, 0, CaretPositioningMode.WordBorder));
|
||||
Assert.AreEqual(5, GetNextCaretStop(c, 1, CaretPositioningMode.WordBorder));
|
||||
|
||||
Assert.AreEqual(5, GetPrevCaretStop(c, 6, CaretPositioningMode.WordBorder));
|
||||
Assert.AreEqual(1, GetPrevCaretStop(c, 5, CaretPositioningMode.WordBorder));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CombiningMark()
|
||||
{
|
||||
string str = " x͆ ";
|
||||
Assert.AreEqual(3, GetNextCaretStop(str, 1, CaretPositioningMode.Normal));
|
||||
Assert.AreEqual(1, GetPrevCaretStop(str, 3, CaretPositioningMode.Normal));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void StackedCombiningMark()
|
||||
{
|
||||
string str = " x͆͆͆͆ ";
|
||||
Assert.AreEqual(6, GetNextCaretStop(str, 1, CaretPositioningMode.Normal));
|
||||
Assert.AreEqual(1, GetPrevCaretStop(str, 6, CaretPositioningMode.Normal));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SingleClosingBraceAtLineEnd()
|
||||
{
|
||||
string str = "\t\t}";
|
||||
Assert.AreEqual(2, GetNextCaretStop(str, 1, CaretPositioningMode.WordStart));
|
||||
Assert.AreEqual(-1, GetPrevCaretStop(str, 1, CaretPositioningMode.WordStart));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// 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 System.Linq;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace AvaloniaEdit.Utils
|
||||
{
|
||||
[TestFixture]
|
||||
public class CompressingTreeListTests
|
||||
{
|
||||
[Test]
|
||||
public void EmptyTreeList()
|
||||
{
|
||||
CompressingTreeList<string> list = new CompressingTreeList<string>(string.Equals);
|
||||
Assert.AreEqual(0, list.Count);
|
||||
foreach (string v in list) {
|
||||
Assert.Fail();
|
||||
}
|
||||
string[] arr = new string[0];
|
||||
list.CopyTo(arr, 0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CheckAdd10BillionElements()
|
||||
{
|
||||
const int billion = 1000000000;
|
||||
CompressingTreeList<string> list = new CompressingTreeList<string>(string.Equals);
|
||||
list.InsertRange(0, billion, "A");
|
||||
list.InsertRange(1, billion, "B");
|
||||
Assert.AreEqual(2 * billion, list.Count);
|
||||
Assert.Throws<OverflowException>(delegate { list.InsertRange(2, billion, "C"); });
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AddRepeated()
|
||||
{
|
||||
CompressingTreeList<int> list = new CompressingTreeList<int>((a, b) => a == b);
|
||||
list.Add(42);
|
||||
list.Add(42);
|
||||
list.Add(42);
|
||||
list.Insert(0, 42);
|
||||
list.Insert(1, 42);
|
||||
Assert.AreEqual(new[] { 42, 42, 42, 42, 42 }, list.ToArray());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveRange()
|
||||
{
|
||||
CompressingTreeList<int> list = new CompressingTreeList<int>((a, b) => a == b);
|
||||
for (int i = 1; i <= 3; i++) {
|
||||
list.InsertRange(list.Count, 2, i);
|
||||
}
|
||||
Assert.AreEqual(new[] { 1, 1, 2, 2, 3, 3 }, list.ToArray());
|
||||
list.RemoveRange(1, 4);
|
||||
Assert.AreEqual(new[] { 1, 3 }, list.ToArray());
|
||||
list.Insert(1, 1);
|
||||
list.InsertRange(2, 2, 2);
|
||||
list.Insert(4, 1);
|
||||
Assert.AreEqual(new[] { 1, 1, 2, 2, 1, 3 }, list.ToArray());
|
||||
list.RemoveRange(2, 2);
|
||||
Assert.AreEqual(new[] { 1, 1, 1, 3 }, list.ToArray());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveAtEnd()
|
||||
{
|
||||
CompressingTreeList<int> list = new CompressingTreeList<int>((a, b) => a == b);
|
||||
for (int i = 1; i <= 3; i++) {
|
||||
list.InsertRange(list.Count, 2, i);
|
||||
}
|
||||
Assert.AreEqual(new[] { 1, 1, 2, 2, 3, 3 }, list.ToArray());
|
||||
list.RemoveRange(3, 3);
|
||||
Assert.AreEqual(new[] { 1, 1, 2 }, list.ToArray());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveAtStart()
|
||||
{
|
||||
CompressingTreeList<int> list = new CompressingTreeList<int>((a, b) => a == b);
|
||||
for (int i = 1; i <= 3; i++) {
|
||||
list.InsertRange(list.Count, 2, i);
|
||||
}
|
||||
Assert.AreEqual(new[] { 1, 1, 2, 2, 3, 3 }, list.ToArray());
|
||||
list.RemoveRange(0, 1);
|
||||
Assert.AreEqual(new[] { 1, 2, 2, 3, 3 }, list.ToArray());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void RemoveAtStart2()
|
||||
{
|
||||
CompressingTreeList<int> list = new CompressingTreeList<int>((a, b) => a == b);
|
||||
for (int i = 1; i <= 3; i++) {
|
||||
list.InsertRange(list.Count, 2, i);
|
||||
}
|
||||
Assert.AreEqual(new[] { 1, 1, 2, 2, 3, 3 }, list.ToArray());
|
||||
list.RemoveRange(0, 3);
|
||||
Assert.AreEqual(new[] { 2, 3, 3 }, list.ToArray());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Transform()
|
||||
{
|
||||
CompressingTreeList<int> list = new CompressingTreeList<int>((a, b) => a == b);
|
||||
list.AddRange(new[] { 0, 1, 1, 0 });
|
||||
int calls = 0;
|
||||
list.Transform(i => { calls++; return i + 1; });
|
||||
Assert.AreEqual(3, calls);
|
||||
Assert.AreEqual(new[] { 1, 2, 2, 1 }, list.ToArray());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TransformToZero()
|
||||
{
|
||||
CompressingTreeList<int> list = new CompressingTreeList<int>((a, b) => a == b);
|
||||
list.AddRange(new[] { 0, 1, 1, 0 });
|
||||
list.Transform(i => 0);
|
||||
Assert.AreEqual(new[] { 0, 0, 0, 0 }, list.ToArray());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TransformRange()
|
||||
{
|
||||
CompressingTreeList<int> list = new CompressingTreeList<int>((a, b) => a == b);
|
||||
list.AddRange(new[] { 0, 1, 1, 1, 0, 0 });
|
||||
list.TransformRange(2, 3, i => 0);
|
||||
Assert.AreEqual(new[] { 0, 1, 0, 0, 0, 0 }, list.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// 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 NUnit.Framework;
|
||||
|
||||
namespace AvaloniaEdit.Utils
|
||||
{
|
||||
[TestFixture]
|
||||
public class ExtensionMethodsTests
|
||||
{
|
||||
[Test]
|
||||
public void ZeroIsNotCloseToOne()
|
||||
{
|
||||
Assert.IsFalse(0.0.IsClose(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ZeroIsCloseToZero()
|
||||
{
|
||||
Assert.IsTrue(0.0.IsClose(0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InfinityIsCloseToInfinity()
|
||||
{
|
||||
Assert.IsTrue(double.PositiveInfinity.IsClose(double.PositiveInfinity));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void NaNIsNotCloseToNaN()
|
||||
{
|
||||
Assert.IsFalse(double.NaN.IsClose(double.NaN));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// 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 NUnit.Framework;
|
||||
|
||||
namespace AvaloniaEdit.Utils
|
||||
{
|
||||
[TestFixture]
|
||||
public class IndentationStringTests
|
||||
{
|
||||
[Test]
|
||||
public void IndentWithSingleTab()
|
||||
{
|
||||
var options = new TextEditorOptions { IndentationSize = 4, ConvertTabsToSpaces = false };
|
||||
Assert.AreEqual("\t", options.IndentationString);
|
||||
Assert.AreEqual("\t", options.GetIndentationString(2));
|
||||
Assert.AreEqual("\t", options.GetIndentationString(3));
|
||||
Assert.AreEqual("\t", options.GetIndentationString(4));
|
||||
Assert.AreEqual("\t", options.GetIndentationString(5));
|
||||
Assert.AreEqual("\t", options.GetIndentationString(6));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IndentWith4Spaces()
|
||||
{
|
||||
var options = new TextEditorOptions { IndentationSize = 4, ConvertTabsToSpaces = true };
|
||||
Assert.AreEqual(" ", options.IndentationString);
|
||||
Assert.AreEqual(" ", options.GetIndentationString(2));
|
||||
Assert.AreEqual(" ", options.GetIndentationString(3));
|
||||
Assert.AreEqual(" ", options.GetIndentationString(4));
|
||||
Assert.AreEqual(" ", options.GetIndentationString(5));
|
||||
Assert.AreEqual(" ", options.GetIndentationString(6));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,195 @@
|
|||
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// 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 System.IO;
|
||||
using NUnit.Framework;
|
||||
using System.Text;
|
||||
|
||||
namespace AvaloniaEdit.Utils
|
||||
{
|
||||
[TestFixture]
|
||||
public class RopeTests
|
||||
{
|
||||
[Test]
|
||||
public void EmptyRope()
|
||||
{
|
||||
Rope<char> empty = new Rope<char>();
|
||||
Assert.AreEqual(0, empty.Length);
|
||||
Assert.AreEqual("", empty.ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmptyRopeFromString()
|
||||
{
|
||||
Rope<char> empty = new Rope<char>(string.Empty);
|
||||
Assert.AreEqual(0, empty.Length);
|
||||
Assert.AreEqual("", empty.ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InitializeRopeFromShortString()
|
||||
{
|
||||
Rope<char> rope = new Rope<char>("Hello, World");
|
||||
Assert.AreEqual(12, rope.Length);
|
||||
Assert.AreEqual("Hello, World", rope.ToString());
|
||||
}
|
||||
|
||||
string BuildLongString(int lines)
|
||||
{
|
||||
StringWriter w = new StringWriter();
|
||||
w.NewLine = "\n";
|
||||
for (int i = 1; i <= lines; i++) {
|
||||
w.WriteLine(i.ToString());
|
||||
}
|
||||
return w.ToString();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InitializeRopeFromLongString()
|
||||
{
|
||||
string text = BuildLongString(1000);
|
||||
Rope<char> rope = new Rope<char>(text);
|
||||
Assert.AreEqual(text.Length, rope.Length);
|
||||
Assert.AreEqual(text, rope.ToString());
|
||||
Assert.AreEqual(text.ToCharArray(), rope.ToArray());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestToArrayAndToStringWithParts()
|
||||
{
|
||||
string text = BuildLongString(1000);
|
||||
Rope<char> rope = new Rope<char>(text);
|
||||
|
||||
string textPart = text.Substring(1200, 600);
|
||||
char[] arrayPart = textPart.ToCharArray();
|
||||
Assert.AreEqual(textPart, rope.ToString(1200, 600));
|
||||
Assert.AreEqual(arrayPart, rope.ToArray(1200, 600));
|
||||
|
||||
Rope<char> partialRope = rope.GetRange(1200, 600);
|
||||
Assert.AreEqual(textPart, partialRope.ToString());
|
||||
Assert.AreEqual(arrayPart, partialRope.ToArray());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConcatenateStringToRope()
|
||||
{
|
||||
StringBuilder b = new StringBuilder();
|
||||
Rope<char> rope = new Rope<char>();
|
||||
for (int i = 1; i <= 1000; i++) {
|
||||
b.Append(i.ToString());
|
||||
rope.AddText(i.ToString());
|
||||
b.Append(' ');
|
||||
rope.Add(' ');
|
||||
}
|
||||
Assert.AreEqual(b.ToString(), rope.ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConcatenateSmallRopesToRope()
|
||||
{
|
||||
StringBuilder b = new StringBuilder();
|
||||
Rope<char> rope = new Rope<char>();
|
||||
for (int i = 1; i <= 1000; i++) {
|
||||
b.Append(i.ToString());
|
||||
b.Append(' ');
|
||||
rope.AddRange(CharRope.Create(i.ToString() + " "));
|
||||
}
|
||||
Assert.AreEqual(b.ToString(), rope.ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AppendLongTextToEmptyRope()
|
||||
{
|
||||
string text = BuildLongString(1000);
|
||||
Rope<char> rope = new Rope<char>();
|
||||
rope.AddText(text);
|
||||
Assert.AreEqual(text, rope.ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConcatenateStringToRopeBackwards()
|
||||
{
|
||||
StringBuilder b = new StringBuilder();
|
||||
Rope<char> rope = new Rope<char>();
|
||||
for (int i = 1; i <= 1000; i++) {
|
||||
b.Append(i.ToString());
|
||||
b.Append(' ');
|
||||
}
|
||||
for (int i = 1000; i >= 1; i--) {
|
||||
rope.Insert(0, ' ');
|
||||
rope.InsertText(0, i.ToString());
|
||||
}
|
||||
Assert.AreEqual(b.ToString(), rope.ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConcatenateSmallRopesToRopeBackwards()
|
||||
{
|
||||
StringBuilder b = new StringBuilder();
|
||||
Rope<char> rope = new Rope<char>();
|
||||
for (int i = 1; i <= 1000; i++) {
|
||||
b.Append(i.ToString());
|
||||
b.Append(' ');
|
||||
}
|
||||
for (int i = 1000; i >= 1; i--) {
|
||||
rope.InsertRange(0, CharRope.Create(i.ToString() + " "));
|
||||
}
|
||||
Assert.AreEqual(b.ToString(), rope.ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConcatenateStringToRopeByInsertionInMiddle()
|
||||
{
|
||||
StringBuilder b = new StringBuilder();
|
||||
Rope<char> rope = new Rope<char>();
|
||||
for (int i = 1; i <= 998; i++) {
|
||||
b.Append(i.ToString("d3"));
|
||||
b.Append(' ');
|
||||
}
|
||||
int middle = 0;
|
||||
for (int i = 1; i <= 499; i++) {
|
||||
rope.InsertText(middle, i.ToString("d3"));
|
||||
middle += 3;
|
||||
rope.Insert(middle, ' ');
|
||||
middle++;
|
||||
rope.InsertText(middle, (999-i).ToString("d3"));
|
||||
rope.Insert(middle + 3, ' ');
|
||||
}
|
||||
Assert.AreEqual(b.ToString(), rope.ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConcatenateSmallRopesByInsertionInMiddle()
|
||||
{
|
||||
StringBuilder b = new StringBuilder();
|
||||
Rope<char> rope = new Rope<char>();
|
||||
for (int i = 1; i <= 1000; i++) {
|
||||
b.Append(i.ToString("d3"));
|
||||
b.Append(' ');
|
||||
}
|
||||
int middle = 0;
|
||||
for (int i = 1; i <= 500; i++) {
|
||||
rope.InsertRange(middle, CharRope.Create(i.ToString("d3") + " "));
|
||||
middle += 4;
|
||||
rope.InsertRange(middle, CharRope.Create((1001-i).ToString("d3") + " "));
|
||||
}
|
||||
Assert.AreEqual(b.ToString(), rope.ToString());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// 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 System.Runtime.CompilerServices;
|
||||
using AvaloniaEdit.AvaloniaMocks;
|
||||
using AvaloniaEdit.Document;
|
||||
using AvaloniaEdit.Editing;
|
||||
using AvaloniaEdit.Rendering;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace AvaloniaEdit
|
||||
{
|
||||
[TestFixture]
|
||||
public class WeakReferenceTests
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static WeakReference CreateControl<T>(Action<T> action = null)
|
||||
where T : class, new()
|
||||
{
|
||||
WeakReference wr;
|
||||
|
||||
using (UnitTestApplication.Start(new TestServices(renderInterface: new MockPlatformRenderInterface())))
|
||||
{
|
||||
var control = new T();
|
||||
wr = new WeakReference(control);
|
||||
action?.Invoke(control);
|
||||
control = null;
|
||||
}
|
||||
|
||||
GarbageCollect();
|
||||
|
||||
return wr;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TextViewCanBeCollectedTest()
|
||||
{
|
||||
var wr = CreateControl<TextView>();
|
||||
Assert.IsFalse(wr.IsAlive);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DocumentDoesNotHoldReferenceToTextView()
|
||||
{
|
||||
TextDocument textDocument = new TextDocument();
|
||||
Assert.AreEqual(0, textDocument.LineTrackers.Count);
|
||||
|
||||
var wr = CreateControl<TextView>(t => t.Document = textDocument);
|
||||
|
||||
Assert.IsFalse(wr.IsAlive);
|
||||
// document cannot immediately clear the line tracker
|
||||
Assert.AreEqual(1, textDocument.LineTrackers.Count);
|
||||
|
||||
// but it should clear it on the next change
|
||||
textDocument.Insert(0, "a");
|
||||
Assert.AreEqual(0, textDocument.LineTrackers.Count);
|
||||
}
|
||||
|
||||
//[Test] // currently fails due to some Avalonia static
|
||||
void DocumentDoesNotHoldReferenceToTextArea()
|
||||
{
|
||||
var textDocument = new TextDocument();
|
||||
var wr = CreateControl<TextArea>(t => t.Document = textDocument);
|
||||
Assert.IsFalse(wr.IsAlive);
|
||||
GC.KeepAlive(textDocument);
|
||||
}
|
||||
|
||||
//[Test] // currently fails due to some Avalonia static
|
||||
void DocumentDoesNotHoldReferenceToTextEditor()
|
||||
{
|
||||
var textDocument = new TextDocument();
|
||||
var wr = CreateControl<TextEditor>(t => t.Document = textDocument);
|
||||
Assert.IsFalse(wr.IsAlive);
|
||||
GC.KeepAlive(textDocument);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DocumentDoesNotHoldReferenceToLineMargin()
|
||||
{
|
||||
TextDocument textDocument = new TextDocument();
|
||||
var wr = CreateControl<TextView>(t =>
|
||||
{
|
||||
t.Document = textDocument;
|
||||
new LineNumberMargin { TextView = t };
|
||||
});
|
||||
|
||||
Assert.IsFalse(wr.IsAlive);
|
||||
GC.KeepAlive(textDocument);
|
||||
}
|
||||
|
||||
static void GarbageCollect()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче