mirror of https://github.com/icsharpcode/ILSpy.git
Browse Source
# Conflicts: # ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj # ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs # ICSharpCode.Decompiler/ICSharpCode.Decompiler.csprojpull/900/head
173 changed files with 30403 additions and 2015 deletions
@ -1,205 +0,0 @@
@@ -1,205 +0,0 @@
|
||||
// Copyright (c) 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; |
||||
|
||||
public static class DelegateConstruction |
||||
{ |
||||
class InstanceTests |
||||
{ |
||||
public Action CaptureOfThis() |
||||
{ |
||||
return delegate { |
||||
CaptureOfThis(); |
||||
}; |
||||
} |
||||
|
||||
public Action CaptureOfThisAndParameter(int a) |
||||
{ |
||||
return delegate { |
||||
CaptureOfThisAndParameter(a); |
||||
}; |
||||
} |
||||
|
||||
public Action CaptureOfThisAndParameterInForEach(int a) |
||||
{ |
||||
foreach (int item in Enumerable.Empty<int>()) { |
||||
if (item > 0) { |
||||
return delegate { |
||||
CaptureOfThisAndParameter(item + a); |
||||
}; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public Action CaptureOfThisAndParameterInForEachWithItemCopy(int a) |
||||
{ |
||||
foreach (int item in Enumerable.Empty<int>()) { |
||||
int copyOfItem = item; |
||||
if (item > 0) { |
||||
return delegate { |
||||
CaptureOfThisAndParameter(item + a + copyOfItem); |
||||
}; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public void LambdaInForLoop() |
||||
{ |
||||
for (int i = 0; i < 100000; i++) { |
||||
Bar(() => Foo()); |
||||
} |
||||
} |
||||
|
||||
public int Foo() |
||||
{ |
||||
return 0; |
||||
} |
||||
|
||||
public void Bar(Func<int> f) |
||||
{ |
||||
} |
||||
} |
||||
|
||||
public static void Test(this string a) |
||||
{ |
||||
} |
||||
|
||||
public static Action<string> ExtensionMethodUnbound() |
||||
{ |
||||
return new Action<string>(DelegateConstruction.Test); |
||||
} |
||||
|
||||
public static Action ExtensionMethodBound() |
||||
{ |
||||
return new Action("abc".Test); |
||||
} |
||||
|
||||
public static Action ExtensionMethodBoundOnNull() |
||||
{ |
||||
return new Action(((string)null).Test); |
||||
} |
||||
|
||||
public static object StaticMethod() |
||||
{ |
||||
return new Func<Action>(DelegateConstruction.ExtensionMethodBound); |
||||
} |
||||
|
||||
public static object InstanceMethod() |
||||
{ |
||||
return new Func<string>("hello".ToUpper); |
||||
} |
||||
|
||||
public static object InstanceMethodOnNull() |
||||
{ |
||||
return new Func<string>(((string)null).ToUpper); |
||||
} |
||||
|
||||
public static List<Action<int>> AnonymousMethodStoreWithinLoop() |
||||
{ |
||||
List<Action<int>> list = new List<Action<int>>(); |
||||
for (int i = 0; i < 10; i++) |
||||
{ |
||||
int counter; |
||||
list.Add(delegate(int x) |
||||
{ |
||||
counter = x; |
||||
} |
||||
); |
||||
} |
||||
return list; |
||||
} |
||||
|
||||
public static List<Action<int>> AnonymousMethodStoreOutsideLoop() |
||||
{ |
||||
List<Action<int>> list = new List<Action<int>>(); |
||||
int counter; |
||||
for (int i = 0; i < 10; i++) |
||||
{ |
||||
list.Add(delegate(int x) |
||||
{ |
||||
counter = x; |
||||
} |
||||
); |
||||
} |
||||
return list; |
||||
} |
||||
|
||||
public static Action StaticAnonymousMethodNoClosure() |
||||
{ |
||||
return delegate |
||||
{ |
||||
Console.WriteLine(); |
||||
}; |
||||
} |
||||
|
||||
public static void NameConflict() |
||||
{ |
||||
// i is captured variable,
|
||||
// j is parameter in anonymous method
|
||||
// k is local in anonymous method,
|
||||
// l is local in main method
|
||||
// Ensure that the decompiler doesn't introduce name conflicts
|
||||
List<Action<int>> list = new List<Action<int>>(); |
||||
for (int l = 0; l < 10; l++) { |
||||
int i; |
||||
for (i = 0; i < 10; i++) { |
||||
list.Add( |
||||
delegate (int j) { |
||||
for (int k = 0; k < i; k += j) { |
||||
Console.WriteLine(); |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public static void NameConflict2(int j) |
||||
{ |
||||
List<Action<int>> list = new List<Action<int>>(); |
||||
for (int k = 0; k < 10; k++) { |
||||
list.Add( |
||||
delegate(int i) { |
||||
Console.WriteLine(i); |
||||
}); |
||||
} |
||||
} |
||||
|
||||
public static Action<int> NameConflict3(int i) |
||||
{ |
||||
return delegate(int j) { |
||||
for (int k = 0; k < j; k++) { |
||||
Console.WriteLine(k); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
public static Func<int, Func<int, int>> CurriedAddition(int a) |
||||
{ |
||||
return b => c => a + b + c; |
||||
} |
||||
|
||||
public static Func<int, Func<int, Func<int, int>>> CurriedAddition2(int a) |
||||
{ |
||||
return b => c => d => a + b + c + d; |
||||
} |
||||
} |
@ -1,89 +0,0 @@
@@ -1,89 +0,0 @@
|
||||
// Copyright (c) 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; |
||||
|
||||
public static class Switch |
||||
{ |
||||
public static string ShortSwitchOverString(string text) |
||||
{ |
||||
switch (text) { |
||||
case "First case": |
||||
return "Text"; |
||||
default: |
||||
return "Default"; |
||||
} |
||||
} |
||||
|
||||
public static string SwitchOverString1(string text) |
||||
{ |
||||
switch (text) |
||||
{ |
||||
case "First case": |
||||
return "Text1"; |
||||
case "Second case": |
||||
case "2nd case": |
||||
return "Text2"; |
||||
case "Third case": |
||||
return "Text3"; |
||||
case "Fourth case": |
||||
return "Text4"; |
||||
case "Fifth case": |
||||
return "Text5"; |
||||
case "Sixth case": |
||||
return "Text6"; |
||||
case null: |
||||
return null; |
||||
default: |
||||
return "Default"; |
||||
} |
||||
} |
||||
|
||||
public static string SwitchOverString2() |
||||
{ |
||||
switch (Environment.UserName) |
||||
{ |
||||
case "First case": |
||||
return "Text1"; |
||||
case "Second case": |
||||
return "Text2"; |
||||
case "Third case": |
||||
return "Text3"; |
||||
case "Fourth case": |
||||
return "Text4"; |
||||
case "Fifth case": |
||||
return "Text5"; |
||||
case "Sixth case": |
||||
return "Text6"; |
||||
default: |
||||
return "Default"; |
||||
} |
||||
} |
||||
|
||||
public static string SwitchOverBool(bool b) |
||||
{ |
||||
switch (b) { |
||||
case true: |
||||
return bool.TrueString; |
||||
case false: |
||||
return bool.FalseString; |
||||
default: |
||||
return null; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
.assembly extern mscorlib |
||||
{ |
||||
.publickeytoken = ( b7 7a 5c 56 19 34 e0 89 ) |
||||
.ver 4:0:0:0 |
||||
} |
||||
|
||||
.assembly 'Jmp' |
||||
{ |
||||
.ver 0:0:0:0 |
||||
} |
||||
|
||||
.module Jmp.exe |
||||
.corflags 0x00000001 // ILOnly |
||||
|
||||
.class private auto ansi abstract sealed beforefieldinit Program |
||||
extends [mscorlib]System.Object |
||||
{ |
||||
.method public hidebysig static void Main (string[] args) cil managed |
||||
{ |
||||
.maxstack 8 |
||||
.entrypoint |
||||
|
||||
ldstr "Method1(100) = {0}" |
||||
ldc.i4 100 |
||||
call int32 Program::Method1(int32) |
||||
box int32 |
||||
call void [mscorlib]System.Console::WriteLine(string, object) |
||||
ret |
||||
} // end of method Main |
||||
|
||||
.method public static int32 Method1(int32 val) |
||||
{ |
||||
ldarg.0 |
||||
ldc.i4.1 |
||||
add |
||||
starg.s 0 |
||||
jmp int32 Program::Method2(int32) |
||||
} |
||||
|
||||
.method public static int32 Method2(int32 val) |
||||
{ |
||||
ldarg.0 |
||||
ldc.i4.5 |
||||
mul |
||||
ret |
||||
} |
||||
} |
@ -0,0 +1,390 @@
@@ -0,0 +1,390 @@
|
||||
// This test case is taken from https://blogs.msdn.microsoft.com/lukeh/2007/10/01/taking-linq-to-objects-to-extremes-a-fully-linqified-raytracer/
|
||||
|
||||
using System.Linq; |
||||
using System; |
||||
using System.Collections.Generic; |
||||
|
||||
namespace RayTracer |
||||
{ |
||||
public class RayTracer |
||||
{ |
||||
static void Main() |
||||
{ |
||||
const int width = 50; |
||||
const int height = 50; |
||||
|
||||
RayTracer rayTracer = new RayTracer(width, height, (int x, int y, Color color) => { |
||||
Console.Write("{0},{1}:{2};", x, y, color); |
||||
}); |
||||
rayTracer.Render(rayTracer.DefaultScene); |
||||
} |
||||
|
||||
private int screenWidth; |
||||
private int screenHeight; |
||||
private const int MaxDepth = 5; |
||||
|
||||
public Action<int, int, Color> setPixel; |
||||
|
||||
public RayTracer(int screenWidth, int screenHeight, Action<int, int, Color> setPixel) |
||||
{ |
||||
this.screenWidth = screenWidth; |
||||
this.screenHeight = screenHeight; |
||||
this.setPixel = setPixel; |
||||
} |
||||
|
||||
private class Wrap<T> |
||||
{ |
||||
public readonly Func<Wrap<T>, T> It; |
||||
public Wrap(Func<Wrap<T>, T> it) { It = it; } |
||||
} |
||||
|
||||
public static Func<T, U> Y<T, U>(Func<Func<T, U>, Func<T, U>> f) |
||||
{ |
||||
Func<Wrap<Func<T, U>>, Func<T, U>> g = wx => f(wx.It(wx)); |
||||
return g(new Wrap<Func<T, U>>(wx => f(y => wx.It(wx)(y)))); |
||||
} |
||||
|
||||
class TraceRayArgs |
||||
{ |
||||
public readonly Ray Ray; |
||||
public readonly Scene Scene; |
||||
public readonly int Depth; |
||||
|
||||
public TraceRayArgs(Ray ray, Scene scene, int depth) { Ray = ray; Scene = scene; Depth = depth; } |
||||
} |
||||
|
||||
internal void Render(Scene scene) |
||||
{ |
||||
var pixelsQuery = |
||||
from y in Enumerable.Range(0, screenHeight) |
||||
let recenterY = -(y - (screenHeight / 2.0)) / (2.0 * screenHeight) |
||||
select from x in Enumerable.Range(0, screenWidth) |
||||
let recenterX = (x - (screenWidth / 2.0)) / (2.0 * screenWidth) |
||||
let point = |
||||
Vector.Norm(Vector.Plus(scene.Camera.Forward, |
||||
Vector.Plus(Vector.Times(recenterX, scene.Camera.Right), |
||||
Vector.Times(recenterY, scene.Camera.Up)))) |
||||
let ray = new Ray() { Start = scene.Camera.Pos, Dir = point } |
||||
let computeTraceRay = (Func<Func<TraceRayArgs, Color>, Func<TraceRayArgs, Color>>) |
||||
(f => traceRayArgs => |
||||
(from isect in |
||||
from thing in traceRayArgs.Scene.Things |
||||
select thing.Intersect(traceRayArgs.Ray) |
||||
where isect != null |
||||
orderby isect.Dist |
||||
let d = isect.Ray.Dir |
||||
let pos = Vector.Plus(Vector.Times(isect.Dist, isect.Ray.Dir), isect.Ray.Start) |
||||
let normal = isect.Thing.Normal(pos) |
||||
let reflectDir = Vector.Minus(d, Vector.Times(2 * Vector.Dot(normal, d), normal)) |
||||
let naturalColors = |
||||
from light in traceRayArgs.Scene.Lights |
||||
let ldis = Vector.Minus(light.Pos, pos) |
||||
let livec = Vector.Norm(ldis) |
||||
let testRay = new Ray() { Start = pos, Dir = livec } |
||||
let testIsects = from inter in |
||||
from thing in traceRayArgs.Scene.Things |
||||
select thing.Intersect(testRay) |
||||
where inter != null |
||||
orderby inter.Dist |
||||
select inter |
||||
let testIsect = testIsects.FirstOrDefault() |
||||
let neatIsect = testIsect == null ? 0 : testIsect.Dist |
||||
let isInShadow = !((neatIsect > Vector.Mag(ldis)) || (neatIsect == 0)) |
||||
where !isInShadow |
||||
let illum = Vector.Dot(livec, normal) |
||||
let lcolor = illum > 0 ? Color.Times(illum, light.Color) : Color.Make(0, 0, 0) |
||||
let specular = Vector.Dot(livec, Vector.Norm(reflectDir)) |
||||
let scolor = specular > 0 |
||||
? Color.Times(Math.Pow(specular, isect.Thing.Surface.Roughness), |
||||
light.Color) |
||||
: Color.Make(0, 0, 0) |
||||
select Color.Plus(Color.Times(isect.Thing.Surface.Diffuse(pos), lcolor), |
||||
Color.Times(isect.Thing.Surface.Specular(pos), scolor)) |
||||
let reflectPos = Vector.Plus(pos, Vector.Times(.001, reflectDir)) |
||||
let reflectColor = traceRayArgs.Depth >= MaxDepth |
||||
? Color.Make(.5, .5, .5) |
||||
: Color.Times(isect.Thing.Surface.Reflect(reflectPos), |
||||
f(new TraceRayArgs(new Ray() { |
||||
Start = reflectPos, |
||||
Dir = reflectDir |
||||
}, |
||||
traceRayArgs.Scene, |
||||
traceRayArgs.Depth + 1))) |
||||
select naturalColors.Aggregate(reflectColor, |
||||
(color, natColor) => Color.Plus(color, natColor)) |
||||
).DefaultIfEmpty(Color.Background).First()) |
||||
let traceRay = Y(computeTraceRay) |
||||
select new { X = x, Y = y, Color = traceRay(new TraceRayArgs(ray, scene, 0)) }; |
||||
|
||||
foreach (var row in pixelsQuery) |
||||
foreach (var pixel in row) |
||||
setPixel(pixel.X, pixel.Y, pixel.Color); |
||||
} |
||||
|
||||
internal readonly Scene DefaultScene = |
||||
new Scene() { |
||||
Things = new SceneObject[] { |
||||
new Plane() { |
||||
Norm = Vector.Make(0,1,0), |
||||
Offset = 0, |
||||
Surface = Surfaces.CheckerBoard |
||||
}, |
||||
new Sphere() { |
||||
Center = Vector.Make(0,1,0), |
||||
Radius = 1, |
||||
Surface = Surfaces.Shiny |
||||
}, |
||||
new Sphere() { |
||||
Center = Vector.Make(-1,.5,1.5), |
||||
Radius = .5, |
||||
Surface = Surfaces.Shiny |
||||
}}, |
||||
Lights = new Light[] { |
||||
new Light() { |
||||
Pos = Vector.Make(-2,2.5,0), |
||||
Color = Color.Make(.49,.07,.07) |
||||
}, |
||||
new Light() { |
||||
Pos = Vector.Make(1.5,2.5,1.5), |
||||
Color = Color.Make(.07,.07,.49) |
||||
}, |
||||
new Light() { |
||||
Pos = Vector.Make(1.5,2.5,-1.5), |
||||
Color = Color.Make(.07,.49,.071) |
||||
}, |
||||
new Light() { |
||||
Pos = Vector.Make(0,3.5,0), |
||||
Color = Color.Make(.21,.21,.35) |
||||
}}, |
||||
Camera = Camera.Create(Vector.Make(3, 2, 4), Vector.Make(-1, .5, 0)) |
||||
}; |
||||
} |
||||
|
||||
static class Surfaces |
||||
{ |
||||
// Only works with X-Z plane.
|
||||
public static readonly Surface CheckerBoard = |
||||
new Surface() { |
||||
Diffuse = pos => ((Math.Floor(pos.Z) + Math.Floor(pos.X)) % 2 != 0) |
||||
? Color.Make(1, 1, 1) |
||||
: Color.Make(0, 0, 0), |
||||
Specular = pos => Color.Make(1, 1, 1), |
||||
Reflect = pos => ((Math.Floor(pos.Z) + Math.Floor(pos.X)) % 2 != 0) |
||||
? .1 |
||||
: .7, |
||||
Roughness = 150 |
||||
}; |
||||
|
||||
|
||||
public static readonly Surface Shiny = |
||||
new Surface() { |
||||
Diffuse = pos => Color.Make(1, 1, 1), |
||||
Specular = pos => Color.Make(.5, .5, .5), |
||||
Reflect = pos => .6, |
||||
Roughness = 50 |
||||
}; |
||||
} |
||||
|
||||
class Vector |
||||
{ |
||||
public readonly double X; |
||||
public readonly double Y; |
||||
public readonly double Z; |
||||
|
||||
public Vector(double x, double y, double z) { X = x; Y = y; Z = z; } |
||||
|
||||
public static Vector Make(double x, double y, double z) { return new Vector(x, y, z); } |
||||
public static Vector Times(double n, Vector v) |
||||
{ |
||||
return new Vector(v.X * n, v.Y * n, v.Z * n); |
||||
} |
||||
public static Vector Minus(Vector v1, Vector v2) |
||||
{ |
||||
return new Vector(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z); |
||||
} |
||||
public static Vector Plus(Vector v1, Vector v2) |
||||
{ |
||||
return new Vector(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z); |
||||
} |
||||
public static double Dot(Vector v1, Vector v2) |
||||
{ |
||||
return (v1.X * v2.X) + (v1.Y * v2.Y) + (v1.Z * v2.Z); |
||||
} |
||||
public static double Mag(Vector v) { return Math.Sqrt(Dot(v, v)); } |
||||
public static Vector Norm(Vector v) |
||||
{ |
||||
double mag = Mag(v); |
||||
double div = mag == 0 ? double.PositiveInfinity : 1 / mag; |
||||
return Times(div, v); |
||||
} |
||||
public static Vector Cross(Vector v1, Vector v2) |
||||
{ |
||||
return new Vector(((v1.Y * v2.Z) - (v1.Z * v2.Y)), |
||||
((v1.Z * v2.X) - (v1.X * v2.Z)), |
||||
((v1.X * v2.Y) - (v1.Y * v2.X))); |
||||
} |
||||
public static bool Equals(Vector v1, Vector v2) |
||||
{ |
||||
return (v1.X == v2.X) && (v1.Y == v2.Y) && (v1.Z == v2.Z); |
||||
} |
||||
} |
||||
|
||||
public class Color |
||||
{ |
||||
public double R; |
||||
public double G; |
||||
public double B; |
||||
|
||||
public Color(double r, double g, double b) { R = r; G = g; B = b; } |
||||
|
||||
public static Color Make(double r, double g, double b) { return new Color(r, g, b); } |
||||
|
||||
public static Color Times(double n, Color v) |
||||
{ |
||||
return new Color(n * v.R, n * v.G, n * v.B); |
||||
} |
||||
public static Color Times(Color v1, Color v2) |
||||
{ |
||||
return new Color(v1.R * v2.R, v1.G * v2.G, v1.B * v2.B); |
||||
} |
||||
|
||||
public static Color Plus(Color v1, Color v2) |
||||
{ |
||||
return new Color(v1.R + v2.R, v1.G + v2.G, v1.B + v2.B); |
||||
} |
||||
public static Color Minus(Color v1, Color v2) |
||||
{ |
||||
return new Color(v1.R - v2.R, v1.G - v2.G, v1.B - v2.B); |
||||
} |
||||
|
||||
public static readonly Color Background = Make(0, 0, 0); |
||||
public static readonly Color DefaultColor = Make(0, 0, 0); |
||||
|
||||
private double Legalize(double d) |
||||
{ |
||||
return d > 1 ? 1 : d; |
||||
} |
||||
|
||||
public override string ToString() |
||||
{ |
||||
return string.Format("[{0},{1},{2}]", R, G, B); |
||||
} |
||||
} |
||||
|
||||
class Ray |
||||
{ |
||||
public Vector Start; |
||||
public Vector Dir; |
||||
} |
||||
|
||||
class ISect |
||||
{ |
||||
public SceneObject Thing; |
||||
public Ray Ray; |
||||
public double Dist; |
||||
} |
||||
|
||||
class Surface |
||||
{ |
||||
public Func<Vector, Color> Diffuse; |
||||
public Func<Vector, Color> Specular; |
||||
public Func<Vector, double> Reflect; |
||||
public double Roughness; |
||||
} |
||||
|
||||
class Camera |
||||
{ |
||||
public Vector Pos; |
||||
public Vector Forward; |
||||
public Vector Up; |
||||
public Vector Right; |
||||
|
||||
public static Camera Create(Vector pos, Vector lookAt) |
||||
{ |
||||
Vector forward = Vector.Norm(Vector.Minus(lookAt, pos)); |
||||
Vector down = new Vector(0, -1, 0); |
||||
Vector right = Vector.Times(1.5, Vector.Norm(Vector.Cross(forward, down))); |
||||
Vector up = Vector.Times(1.5, Vector.Norm(Vector.Cross(forward, right))); |
||||
|
||||
return new Camera() { Pos = pos, Forward = forward, Up = up, Right = right }; |
||||
} |
||||
} |
||||
|
||||
class Light |
||||
{ |
||||
public Vector Pos; |
||||
public Color Color; |
||||
} |
||||
|
||||
abstract class SceneObject |
||||
{ |
||||
public Surface Surface; |
||||
public abstract ISect Intersect(Ray ray); |
||||
public abstract Vector Normal(Vector pos); |
||||
} |
||||
|
||||
class Sphere : SceneObject |
||||
{ |
||||
public Vector Center; |
||||
public double Radius; |
||||
|
||||
public override ISect Intersect(Ray ray) |
||||
{ |
||||
Vector eo = Vector.Minus(Center, ray.Start); |
||||
double v = Vector.Dot(eo, ray.Dir); |
||||
double dist; |
||||
if (v < 0) { |
||||
dist = 0; |
||||
} else { |
||||
double disc = Math.Pow(Radius, 2) - (Vector.Dot(eo, eo) - Math.Pow(v, 2)); |
||||
dist = disc < 0 ? 0 : v - Math.Sqrt(disc); |
||||
} |
||||
if (dist == 0) return null; |
||||
return new ISect() { |
||||
Thing = this, |
||||
Ray = ray, |
||||
Dist = dist |
||||
}; |
||||
} |
||||
|
||||
public override Vector Normal(Vector pos) |
||||
{ |
||||
return Vector.Norm(Vector.Minus(pos, Center)); |
||||
} |
||||
} |
||||
|
||||
class Plane : SceneObject |
||||
{ |
||||
public Vector Norm; |
||||
public double Offset; |
||||
|
||||
public override ISect Intersect(Ray ray) |
||||
{ |
||||
double denom = Vector.Dot(Norm, ray.Dir); |
||||
if (denom > 0) return null; |
||||
return new ISect() { |
||||
Thing = this, |
||||
Ray = ray, |
||||
Dist = (Vector.Dot(Norm, ray.Start) + Offset) / (-denom) |
||||
}; |
||||
} |
||||
|
||||
public override Vector Normal(Vector pos) |
||||
{ |
||||
return Norm; |
||||
} |
||||
} |
||||
|
||||
class Scene |
||||
{ |
||||
public SceneObject[] Things; |
||||
public Light[] Lights; |
||||
public Camera Camera; |
||||
|
||||
public IEnumerable<ISect> Intersect(Ray r) |
||||
{ |
||||
return from thing in Things |
||||
select thing.Intersect(r); |
||||
} |
||||
} |
||||
} |
@ -1 +1,3 @@
@@ -1 +1,3 @@
|
||||
/*.res |
||||
/*.dll |
||||
/*.exe |
||||
|
@ -0,0 +1,199 @@
@@ -0,0 +1,199 @@
|
||||
// Copyright (c) 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; |
||||
|
||||
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty |
||||
{ |
||||
public static class DelegateConstruction |
||||
{ |
||||
private class InstanceTests |
||||
{ |
||||
public Action CaptureOfThis() |
||||
{ |
||||
return delegate { |
||||
this.CaptureOfThis(); |
||||
}; |
||||
} |
||||
|
||||
public Action CaptureOfThisAndParameter(int a) |
||||
{ |
||||
return delegate { |
||||
this.CaptureOfThisAndParameter(a); |
||||
}; |
||||
} |
||||
|
||||
public Action CaptureOfThisAndParameterInForEach(int a) |
||||
{ |
||||
foreach (int item in Enumerable.Empty<int>()) { |
||||
if (item > 0) { |
||||
return delegate { |
||||
this.CaptureOfThisAndParameter(item + a); |
||||
}; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public Action CaptureOfThisAndParameterInForEachWithItemCopy(int a) |
||||
{ |
||||
foreach (int item in Enumerable.Empty<int>()) { |
||||
int copyOfItem = item; |
||||
if (item > 0) { |
||||
return delegate { |
||||
this.CaptureOfThisAndParameter(item + a + copyOfItem); |
||||
}; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
public void LambdaInForLoop() |
||||
{ |
||||
for (int i = 0; i < 100000; i++) { |
||||
this.Bar(() => this.Foo()); |
||||
} |
||||
} |
||||
|
||||
public int Foo() |
||||
{ |
||||
return 0; |
||||
} |
||||
|
||||
public void Bar(Func<int> f) |
||||
{ |
||||
} |
||||
} |
||||
|
||||
public static void Test(this string a) |
||||
{ |
||||
} |
||||
|
||||
public static Action<string> ExtensionMethodUnbound() |
||||
{ |
||||
return DelegateConstruction.Test; |
||||
} |
||||
|
||||
public static Action ExtensionMethodBound() |
||||
{ |
||||
return "abc".Test; |
||||
} |
||||
|
||||
public static Action ExtensionMethodBoundOnNull() |
||||
{ |
||||
return ((string)null).Test; |
||||
} |
||||
|
||||
public static object StaticMethod() |
||||
{ |
||||
return new Func<Action>(DelegateConstruction.ExtensionMethodBound); |
||||
} |
||||
|
||||
public static object InstanceMethod() |
||||
{ |
||||
return new Func<string>("hello".ToUpper); |
||||
} |
||||
|
||||
public static object InstanceMethodOnNull() |
||||
{ |
||||
return new Func<string>(((string)null).ToUpper); |
||||
} |
||||
|
||||
public static List<Action<int>> AnonymousMethodStoreWithinLoop() |
||||
{ |
||||
List<Action<int>> list = new List<Action<int>>(); |
||||
for (int i = 0; i < 10; i++) { |
||||
int counter; |
||||
list.Add(delegate(int x) { |
||||
counter = x; |
||||
}); |
||||
} |
||||
return list; |
||||
} |
||||
|
||||
public static List<Action<int>> AnonymousMethodStoreOutsideLoop() |
||||
{ |
||||
List<Action<int>> list = new List<Action<int>>(); |
||||
int counter; |
||||
for (int i = 0; i < 10; i++) { |
||||
list.Add(delegate(int x) { |
||||
counter = x; |
||||
}); |
||||
} |
||||
return list; |
||||
} |
||||
|
||||
public static Action StaticAnonymousMethodNoClosure() |
||||
{ |
||||
return delegate { |
||||
Console.WriteLine(); |
||||
}; |
||||
} |
||||
|
||||
public static void NameConflict() |
||||
{ |
||||
// i is captured variable,
|
||||
// j is parameter in anonymous method
|
||||
// l is local in anonymous method,
|
||||
// k is local in main method
|
||||
// Ensure that the decompiler doesn't introduce name conflicts
|
||||
List<Action<int>> list = new List<Action<int>>(); |
||||
for (int k = 0; k < 10; k++) { |
||||
int i; |
||||
for (i = 0; i < 10; i++) { |
||||
list.Add(delegate(int j) { |
||||
for (int l = 0; l < i; l += j) { |
||||
Console.WriteLine(); |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public static void NameConflict2(int j) |
||||
{ |
||||
List<Action<int>> list = new List<Action<int>>(); |
||||
for (int k = 0; k < 10; k++) { |
||||
list.Add(delegate(int i) { |
||||
Console.WriteLine(i); |
||||
}); |
||||
} |
||||
} |
||||
|
||||
public static Action<int> NameConflict3(int i) |
||||
{ |
||||
return delegate(int j) { |
||||
for (int k = 0; k < j; k++) { |
||||
Console.WriteLine(k); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
public static Func<int, Func<int, int>> CurriedAddition(int a) |
||||
{ |
||||
return (int b) => (int c) => a + b + c; |
||||
} |
||||
|
||||
public static Func<int, Func<int, Func<int, int>>> CurriedAddition2(int a) |
||||
{ |
||||
return (int b) => (int c) => (int d) => a + b + c + d; |
||||
} |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,118 @@
@@ -0,0 +1,118 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Threading.Tasks; |
||||
|
||||
namespace ICSharpCode.Decompiler.Tests.TestCases.ILPretty |
||||
{ |
||||
internal class A |
||||
{ |
||||
protected internal virtual Task<string> Test(string test) |
||||
{ |
||||
return Task.Run(() => test.ToUpper()); |
||||
} |
||||
} |
||||
|
||||
internal class B : A |
||||
{ |
||||
protected internal override async Task<string> Test(string test) |
||||
{ |
||||
return await base.Test(test); |
||||
} |
||||
} |
||||
|
||||
internal class C |
||||
{ |
||||
protected internal virtual string Test(string test) |
||||
{ |
||||
return string.Join(test, "fsdf"); |
||||
} |
||||
} |
||||
|
||||
internal class D : C |
||||
{ |
||||
protected internal IEnumerable<string> Test2(string test) |
||||
{ |
||||
yield return base.Test(test); |
||||
} |
||||
} |
||||
|
||||
internal class E |
||||
{ |
||||
protected internal virtual string Test(string test) |
||||
{ |
||||
return string.Join(test, "fsdf"); |
||||
} |
||||
} |
||||
|
||||
internal class F : E |
||||
{ |
||||
protected internal override string Test(string test) |
||||
{ |
||||
Func<string, string> func = (string a) => base.Test(a); |
||||
test = string.Join(test, "aa"); |
||||
return func(test); |
||||
} |
||||
} |
||||
|
||||
internal class G |
||||
{ |
||||
protected internal virtual void Test(string test) |
||||
{ |
||||
string.Join(test, "fsdf"); |
||||
} |
||||
} |
||||
|
||||
internal class H : G |
||||
{ |
||||
protected internal override void Test(string test) |
||||
{ |
||||
Action<string> action = delegate(string a) { |
||||
base.Test(a); |
||||
}; |
||||
if (test.Equals(1)) { |
||||
throw new Exception("roslyn optimize is inlining the assignment which lets the test fail"); |
||||
} |
||||
action(test); |
||||
} |
||||
} |
||||
|
||||
internal class I |
||||
{ |
||||
protected internal virtual void Test(int a) |
||||
{ |
||||
|
||||
} |
||||
} |
||||
|
||||
internal class J : I |
||||
{ |
||||
protected internal override void Test(int a) |
||||
{ |
||||
Action action = delegate { |
||||
base.Test(a); |
||||
}; |
||||
if (a.Equals(1)) { |
||||
throw new Exception("roslyn optimize is inlining the assignment which lets the test fail"); |
||||
} |
||||
action(); |
||||
|
||||
} |
||||
} |
||||
|
||||
internal class K |
||||
{ |
||||
protected internal virtual IEnumerable<int> Test(int p) |
||||
{ |
||||
yield return p + 1; |
||||
yield return p + 2; |
||||
} |
||||
} |
||||
|
||||
internal class L : K |
||||
{ |
||||
protected internal override IEnumerable<int> Test(int p) |
||||
{ |
||||
yield return base.Test(base.Test(0).GetEnumerator().Current).GetEnumerator().Current; |
||||
} |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,484 @@
@@ -0,0 +1,484 @@
|
||||
// Copyright (c) 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.Globalization; |
||||
using System.Linq; |
||||
using System.Threading; |
||||
|
||||
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty |
||||
{ |
||||
public class InitializerTests |
||||
{ |
||||
#region Types and helpers
|
||||
public class C |
||||
{ |
||||
public int Z; |
||||
public S Y; |
||||
public List<S> L; |
||||
} |
||||
|
||||
public struct S |
||||
{ |
||||
public int A; |
||||
public int B; |
||||
|
||||
public S(int a) |
||||
{ |
||||
this.A = a; |
||||
this.B = 0; |
||||
} |
||||
} |
||||
|
||||
private enum MyEnum |
||||
{ |
||||
a = 0, |
||||
b = 1 |
||||
} |
||||
|
||||
private enum MyEnum2 |
||||
{ |
||||
c = 0, |
||||
d = 1 |
||||
} |
||||
|
||||
private class Data |
||||
{ |
||||
public List<MyEnum2> FieldList = new List<MyEnum2>(); |
||||
public MyEnum a { |
||||
get; |
||||
set; |
||||
} |
||||
public MyEnum b { |
||||
get; |
||||
set; |
||||
} |
||||
public List<MyEnum2> PropertyList { |
||||
get; |
||||
set; |
||||
} |
||||
|
||||
public Data MoreData { |
||||
get; |
||||
set; |
||||
} |
||||
|
||||
public StructData NestedStruct { |
||||
get; |
||||
set; |
||||
} |
||||
|
||||
public Data this[int i] { |
||||
get { |
||||
return null; |
||||
} |
||||
set { |
||||
} |
||||
} |
||||
|
||||
public Data this[int i, string j] { |
||||
get { |
||||
return null; |
||||
} |
||||
set { |
||||
} |
||||
} |
||||
|
||||
public event EventHandler TestEvent; |
||||
} |
||||
|
||||
private struct StructData |
||||
{ |
||||
public int Field; |
||||
public int Property { |
||||
get; |
||||
set; |
||||
} |
||||
|
||||
public Data MoreData { |
||||
get; |
||||
set; |
||||
} |
||||
|
||||
public StructData(int initialValue) |
||||
{ |
||||
this = default(StructData); |
||||
this.Field = initialValue; |
||||
this.Property = initialValue; |
||||
} |
||||
} |
||||
|
||||
// Helper methods used to ensure initializers used within expressions work correctly
|
||||
private static void X(object a, object b) |
||||
{ |
||||
} |
||||
|
||||
private static object Y() |
||||
{ |
||||
return null; |
||||
} |
||||
|
||||
public static void TestCall(int a, Thread thread) |
||||
{ |
||||
|
||||
} |
||||
|
||||
public static C TestCall(int a, C c) |
||||
{ |
||||
return c; |
||||
} |
||||
#endregion
|
||||
|
||||
public C Test1() |
||||
{ |
||||
C c = new C(); |
||||
c.L = new List<S>(); |
||||
c.L.Add(new S(1)); |
||||
return c; |
||||
} |
||||
|
||||
public C Test1Alternative() |
||||
{ |
||||
return InitializerTests.TestCall(1, new C { |
||||
L = new List<S> { |
||||
new S(1) |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public C Test2() |
||||
{ |
||||
C c = new C(); |
||||
c.Z = 1; |
||||
c.Z = 2; |
||||
return c; |
||||
} |
||||
|
||||
public C Test3() |
||||
{ |
||||
C c = new C(); |
||||
c.Y = new S(1); |
||||
c.Y.A = 2; |
||||
return c; |
||||
} |
||||
|
||||
public C Test3b() |
||||
{ |
||||
return InitializerTests.TestCall(0, new C { |
||||
Z = 1, |
||||
Y = { |
||||
A = 2 |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public C Test4() |
||||
{ |
||||
C c = new C(); |
||||
c.Y.A = 1; |
||||
c.Z = 2; |
||||
c.Y.B = 3; |
||||
return c; |
||||
} |
||||
|
||||
|
||||
public static void CollectionInitializerList() |
||||
{ |
||||
InitializerTests.X(InitializerTests.Y(), new List<int> { |
||||
1, |
||||
2, |
||||
3 |
||||
}); |
||||
} |
||||
|
||||
public static object RecursiveCollectionInitializer() |
||||
{ |
||||
List<object> list = new List<object>(); |
||||
list.Add(list); |
||||
return list; |
||||
} |
||||
|
||||
public static void CollectionInitializerDictionary() |
||||
{ |
||||
InitializerTests.X(InitializerTests.Y(), new Dictionary<string, int> { |
||||
{ |
||||
"First", |
||||
1 |
||||
}, |
||||
{ |
||||
"Second", |
||||
2 |
||||
}, |
||||
{ |
||||
"Third", |
||||
3 |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public static void CollectionInitializerDictionaryWithEnumTypes() |
||||
{ |
||||
InitializerTests.X(InitializerTests.Y(), new Dictionary<MyEnum, MyEnum2> { |
||||
{ |
||||
MyEnum.a, |
||||
MyEnum2.c |
||||
}, |
||||
{ |
||||
MyEnum.b, |
||||
MyEnum2.d |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public static void NotACollectionInitializer() |
||||
{ |
||||
List<int> list = new List<int>(); |
||||
list.Add(1); |
||||
list.Add(2); |
||||
list.Add(3); |
||||
InitializerTests.X(InitializerTests.Y(), list); |
||||
} |
||||
|
||||
public static void ObjectInitializer() |
||||
{ |
||||
InitializerTests.X(InitializerTests.Y(), new Data { |
||||
a = MyEnum.a |
||||
}); |
||||
} |
||||
|
||||
public static void NotAnObjectInitializer() |
||||
{ |
||||
Data data = new Data(); |
||||
data.a = MyEnum.a; |
||||
InitializerTests.X(InitializerTests.Y(), data); |
||||
} |
||||
|
||||
public static void NotAnObjectInitializerWithEvent() |
||||
{ |
||||
Data data = new Data(); |
||||
data.TestEvent += delegate(object sender, EventArgs e) { |
||||
Console.WriteLine(); |
||||
}; |
||||
InitializerTests.X(InitializerTests.Y(), data); |
||||
} |
||||
|
||||
public static void ObjectInitializerAssignCollectionToField() |
||||
{ |
||||
InitializerTests.X(InitializerTests.Y(), new Data { |
||||
a = MyEnum.a, |
||||
FieldList = new List<MyEnum2> { |
||||
MyEnum2.c, |
||||
MyEnum2.d |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public static void ObjectInitializerAddToCollectionInField() |
||||
{ |
||||
InitializerTests.X(InitializerTests.Y(), new Data { |
||||
a = MyEnum.a, |
||||
FieldList = { |
||||
MyEnum2.c, |
||||
MyEnum2.d |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public static void ObjectInitializerAssignCollectionToProperty() |
||||
{ |
||||
InitializerTests.X(InitializerTests.Y(), new Data { |
||||
a = MyEnum.a, |
||||
PropertyList = new List<MyEnum2> { |
||||
MyEnum2.c, |
||||
MyEnum2.d |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public static void ObjectInitializerAddToCollectionInProperty() |
||||
{ |
||||
InitializerTests.X(InitializerTests.Y(), new Data { |
||||
a = MyEnum.a, |
||||
PropertyList = { |
||||
MyEnum2.c, |
||||
MyEnum2.d |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public static void ObjectInitializerWithInitializationOfNestedObjects() |
||||
{ |
||||
InitializerTests.X(InitializerTests.Y(), new Data { |
||||
MoreData = { |
||||
a = MyEnum.a, |
||||
MoreData = { |
||||
a = MyEnum.b |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
|
||||
private static int GetInt() |
||||
{ |
||||
return 1; |
||||
} |
||||
|
||||
private static string GetString() |
||||
{ |
||||
return "Test"; |
||||
} |
||||
|
||||
#if !LEGACY_CSC
|
||||
public static void SimpleDictInitializer() |
||||
{ |
||||
InitializerTests.X(InitializerTests.Y(), new Data { |
||||
MoreData = { |
||||
a = MyEnum.a, |
||||
[2] = null |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public static void MixedObjectAndDictInitializer() |
||||
{ |
||||
InitializerTests.X(InitializerTests.Y(), new Data { |
||||
MoreData = { |
||||
a = MyEnum.a, |
||||
[InitializerTests.GetInt()] = { |
||||
a = MyEnum.b, |
||||
FieldList = { |
||||
MyEnum2.c |
||||
}, |
||||
[InitializerTests.GetInt(), InitializerTests.GetString()] = new Data(), |
||||
[2] = null |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
#endif
|
||||
|
||||
public static void ObjectInitializerWithInitializationOfDeeplyNestedObjects() |
||||
{ |
||||
InitializerTests.X(InitializerTests.Y(), new Data { |
||||
a = MyEnum.b, |
||||
MoreData = { |
||||
a = MyEnum.a, |
||||
MoreData = { |
||||
MoreData = { |
||||
MoreData = { |
||||
MoreData = { |
||||
MoreData = { |
||||
MoreData = { |
||||
a = MyEnum.b |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public static void CollectionInitializerInsideObjectInitializers() |
||||
{ |
||||
InitializerTests.X(InitializerTests.Y(), new Data { |
||||
MoreData = new Data { |
||||
a = MyEnum.a, |
||||
b = MyEnum.b, |
||||
PropertyList = { |
||||
MyEnum2.c |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public static void NotAStructInitializer_DefaultConstructor() |
||||
{ |
||||
StructData structData = default(StructData); |
||||
structData.Field = 1; |
||||
structData.Property = 2; |
||||
InitializerTests.X(InitializerTests.Y(), structData); |
||||
} |
||||
|
||||
public static void StructInitializer_DefaultConstructor() |
||||
{ |
||||
InitializerTests.X(InitializerTests.Y(), new StructData { |
||||
Field = 1, |
||||
Property = 2 |
||||
}); |
||||
} |
||||
|
||||
public static void NotAStructInitializer_ExplicitConstructor() |
||||
{ |
||||
StructData structData = new StructData(0); |
||||
structData.Field = 1; |
||||
structData.Property = 2; |
||||
InitializerTests.X(InitializerTests.Y(), structData); |
||||
} |
||||
|
||||
public static void StructInitializer_ExplicitConstructor() |
||||
{ |
||||
InitializerTests.X(InitializerTests.Y(), new StructData(0) { |
||||
Field = 1, |
||||
Property = 2 |
||||
}); |
||||
} |
||||
|
||||
public static void StructInitializerWithInitializationOfNestedObjects() |
||||
{ |
||||
InitializerTests.X(InitializerTests.Y(), new StructData { |
||||
MoreData = { |
||||
a = MyEnum.a, |
||||
FieldList = { |
||||
MyEnum2.c, |
||||
MyEnum2.d |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public static void StructInitializerWithinObjectInitializer() |
||||
{ |
||||
InitializerTests.X(InitializerTests.Y(), new Data { |
||||
NestedStruct = new StructData(2) { |
||||
Field = 1, |
||||
Property = 2 |
||||
} |
||||
}); |
||||
} |
||||
|
||||
public static void Bug270_NestedInitialisers() |
||||
{ |
||||
NumberFormatInfo[] source = null; |
||||
|
||||
InitializerTests.TestCall(0, new Thread(InitializerTests.Bug270_NestedInitialisers) { |
||||
Priority = ThreadPriority.BelowNormal, |
||||
CurrentCulture = new CultureInfo(0) { |
||||
DateTimeFormat = new DateTimeFormatInfo { |
||||
ShortDatePattern = "ddmmyy" |
||||
}, |
||||
NumberFormat = (from format in source |
||||
where format.CurrencySymbol == "$" |
||||
select format).First() |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,450 @@
@@ -0,0 +1,450 @@
|
||||
// Copyright (c) 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.Reflection; |
||||
|
||||
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty |
||||
{ |
||||
public static class Switch |
||||
{ |
||||
public class SetProperty |
||||
{ |
||||
public readonly PropertyInfo Property; |
||||
|
||||
public int Set { |
||||
get; |
||||
set; |
||||
} |
||||
|
||||
public SetProperty(PropertyInfo property) |
||||
{ |
||||
this.Property = property; |
||||
} |
||||
} |
||||
|
||||
public enum State |
||||
{ |
||||
False = 0, |
||||
True = 1, |
||||
Null = 2 |
||||
} |
||||
|
||||
public static State SwitchOverNullableBool(bool? value) |
||||
{ |
||||
switch (value) { |
||||
case false: |
||||
return State.False; |
||||
case true: |
||||
return State.True; |
||||
case null: |
||||
return State.Null; |
||||
default: |
||||
throw new InvalidOperationException(); |
||||
} |
||||
} |
||||
|
||||
public static bool? SwitchOverNullableEnum(State? state) |
||||
{ |
||||
switch (state) { |
||||
case State.False: |
||||
return false; |
||||
case State.True: |
||||
return true; |
||||
case State.Null: |
||||
return null; |
||||
default: |
||||
throw new InvalidOperationException(); |
||||
} |
||||
} |
||||
|
||||
public static string SparseIntegerSwitch(int i) |
||||
{ |
||||
Console.WriteLine("SparseIntegerSwitch: " + i); |
||||
switch (i) { |
||||
case -10000000: |
||||
return "-10 mln"; |
||||
case -100: |
||||
return "-hundred"; |
||||
case -1: |
||||
return "-1"; |
||||
case 0: |
||||
return "0"; |
||||
case 1: |
||||
return "1"; |
||||
case 2: |
||||
return "2"; |
||||
case 4: |
||||
return "4"; |
||||
case 100: |
||||
return "hundred"; |
||||
case 10000: |
||||
return "ten thousand"; |
||||
case 10001: |
||||
return "ten thousand and one"; |
||||
case 2147483647: |
||||
return "int.MaxValue"; |
||||
default: |
||||
return "something else"; |
||||
} |
||||
} |
||||
|
||||
public static string SwitchOverNullableInt(int? i) |
||||
{ |
||||
switch (i) { |
||||
case null: |
||||
return "null"; |
||||
case 0: |
||||
return "zero"; |
||||
case 5: |
||||
return "five"; |
||||
case 10: |
||||
return "ten"; |
||||
default: |
||||
return "large"; |
||||
} |
||||
} |
||||
|
||||
public static string SwitchOverNullableIntNullCaseCombined(int? i) |
||||
{ |
||||
switch (i) { |
||||
case null: |
||||
case 0: |
||||
return "zero"; |
||||
case 5: |
||||
return "five"; |
||||
case 10: |
||||
return "ten"; |
||||
default: |
||||
return "large"; |
||||
} |
||||
} |
||||
|
||||
public static string SwitchOverNullableIntShifted(int? i) |
||||
{ |
||||
switch (i + 5) { |
||||
case null: |
||||
return "null"; |
||||
case 0: |
||||
return "zero"; |
||||
case 5: |
||||
return "five"; |
||||
case 10: |
||||
return "ten"; |
||||
default: |
||||
return "large"; |
||||
} |
||||
} |
||||
|
||||
public static string SwitchOverNullableIntShiftedNullCaseCombined(int? i) |
||||
{ |
||||
switch (i + 5) { |
||||
case null: |
||||
case 0: |
||||
return "zero"; |
||||
case 5: |
||||
return "five"; |
||||
case 10: |
||||
return "ten"; |
||||
default: |
||||
return "large"; |
||||
} |
||||
} |
||||
|
||||
public static string SwitchOverNullableIntNoNullCase(int? i) |
||||
{ |
||||
switch (i) { |
||||
case 0: |
||||
return "zero"; |
||||
case 5: |
||||
return "five"; |
||||
case 10: |
||||
return "ten"; |
||||
default: |
||||
return "other"; |
||||
} |
||||
} |
||||
|
||||
public static string SwitchOverNullableIntNoNullCaseShifted(int? i) |
||||
{ |
||||
switch (i + 5) { |
||||
case 0: |
||||
return "zero"; |
||||
case 5: |
||||
return "five"; |
||||
case 10: |
||||
return "ten"; |
||||
default: |
||||
return "other"; |
||||
} |
||||
} |
||||
|
||||
public static void SwitchOverInt(int i) |
||||
{ |
||||
switch (i) { |
||||
case 0: |
||||
Console.WriteLine("zero"); |
||||
break; |
||||
case 5: |
||||
Console.WriteLine("five"); |
||||
break; |
||||
case 10: |
||||
Console.WriteLine("ten"); |
||||
break; |
||||
case 15: |
||||
Console.WriteLine("fifteen"); |
||||
break; |
||||
case 20: |
||||
Console.WriteLine("twenty"); |
||||
break; |
||||
case 25: |
||||
Console.WriteLine("twenty-five"); |
||||
break; |
||||
case 30: |
||||
Console.WriteLine("thirty"); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
public static string ShortSwitchOverString(string text) |
||||
{ |
||||
Console.WriteLine("ShortSwitchOverString: " + text); |
||||
switch (text) { |
||||
case "First case": |
||||
return "Text1"; |
||||
case "Second case": |
||||
return "Text2"; |
||||
case "Third case": |
||||
return "Text3"; |
||||
default: |
||||
return "Default"; |
||||
} |
||||
} |
||||
|
||||
public static string ShortSwitchOverStringWithNullCase(string text) |
||||
{ |
||||
Console.WriteLine("ShortSwitchOverStringWithNullCase: " + text); |
||||
switch (text) { |
||||
case "First case": |
||||
return "Text1"; |
||||
case "Second case": |
||||
return "Text2"; |
||||
case null: |
||||
return "null"; |
||||
default: |
||||
return "Default"; |
||||
} |
||||
} |
||||
|
||||
public static string SwitchOverString1(string text) |
||||
{ |
||||
Console.WriteLine("SwitchOverString1: " + text); |
||||
switch (text) { |
||||
case "First case": |
||||
return "Text1"; |
||||
case "Second case": |
||||
case "2nd case": |
||||
return "Text2"; |
||||
case "Third case": |
||||
return "Text3"; |
||||
case "Fourth case": |
||||
return "Text4"; |
||||
case "Fifth case": |
||||
return "Text5"; |
||||
case "Sixth case": |
||||
return "Text6"; |
||||
case null: |
||||
return null; |
||||
default: |
||||
return "Default"; |
||||
} |
||||
} |
||||
|
||||
public static string SwitchOverString2() |
||||
{ |
||||
Console.WriteLine("SwitchOverString2:"); |
||||
switch (Environment.UserName) { |
||||
case "First case": |
||||
return "Text1"; |
||||
case "Second case": |
||||
return "Text2"; |
||||
case "Third case": |
||||
return "Text3"; |
||||
case "Fourth case": |
||||
return "Text4"; |
||||
case "Fifth case": |
||||
return "Text5"; |
||||
case "Sixth case": |
||||
return "Text6"; |
||||
case "Seventh case": |
||||
return "Text7"; |
||||
case "Eighth case": |
||||
return "Text8"; |
||||
case "Ninth case": |
||||
return "Text9"; |
||||
case "Tenth case": |
||||
return "Text10"; |
||||
case "Eleventh case": |
||||
return "Text11"; |
||||
default: |
||||
return "Default"; |
||||
} |
||||
} |
||||
|
||||
public static string SwitchOverBool(bool b) |
||||
{ |
||||
Console.WriteLine("SwitchOverBool: " + b.ToString()); |
||||
switch (b) { |
||||
case true: |
||||
return bool.TrueString; |
||||
case false: |
||||
return bool.FalseString; |
||||
default: |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
public static void SwitchInLoop(int i) |
||||
{ |
||||
Console.WriteLine("SwitchInLoop: " + i); |
||||
while (true) { |
||||
switch (i) { |
||||
case 1: |
||||
Console.WriteLine("one"); |
||||
break; |
||||
case 2: |
||||
Console.WriteLine("two"); |
||||
break; |
||||
//case 3:
|
||||
// Console.WriteLine("three");
|
||||
// continue;
|
||||
case 4: |
||||
Console.WriteLine("four"); |
||||
return; |
||||
default: |
||||
Console.WriteLine("default"); |
||||
Console.WriteLine("more code"); |
||||
return; |
||||
} |
||||
i++; |
||||
} |
||||
} |
||||
|
||||
public static void SwitchWithGoto(int i) |
||||
{ |
||||
Console.WriteLine("SwitchWithGoto: " + i); |
||||
switch (i) { |
||||
case 1: |
||||
Console.WriteLine("one"); |
||||
goto default; |
||||
case 2: |
||||
Console.WriteLine("two"); |
||||
goto case 3; |
||||
case 3: |
||||
Console.WriteLine("three"); |
||||
break; |
||||
case 4: |
||||
Console.WriteLine("four"); |
||||
return; |
||||
default: |
||||
Console.WriteLine("default"); |
||||
break; |
||||
} |
||||
Console.WriteLine("End of method"); |
||||
} |
||||
|
||||
private static SetProperty[] GetProperties() |
||||
{ |
||||
return new SetProperty[0]; |
||||
} |
||||
|
||||
public static void SwitchOnStringInForLoop() |
||||
{ |
||||
List<SetProperty> list = new List<SetProperty>(); |
||||
List<SetProperty> list2 = new List<SetProperty>(); |
||||
SetProperty[] properties = Switch.GetProperties(); |
||||
for (int i = 0; i < properties.Length; i++) { |
||||
SetProperty setProperty = properties[i]; |
||||
switch (setProperty.Property.Name) { |
||||
case "Name1": |
||||
setProperty.Set = 1; |
||||
list.Add(setProperty); |
||||
break; |
||||
case "Name2": |
||||
setProperty.Set = 2; |
||||
list.Add(setProperty); |
||||
break; |
||||
case "Name3": |
||||
setProperty.Set = 3; |
||||
list.Add(setProperty); |
||||
break; |
||||
case "Name4": |
||||
setProperty.Set = 4; |
||||
list.Add(setProperty); |
||||
break; |
||||
case "Name5": |
||||
case "Name6": |
||||
list.Add(setProperty); |
||||
break; |
||||
default: |
||||
list2.Add(setProperty); |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
public static void SwitchWithComplexCondition(string[] args) |
||||
{ |
||||
switch ((args.Length == 0) ? "dummy" : args[0]) { |
||||
case "a": |
||||
Console.WriteLine("a"); |
||||
break; |
||||
case "b": |
||||
Console.WriteLine("b"); |
||||
break; |
||||
case "c": |
||||
Console.WriteLine("c"); |
||||
break; |
||||
case "d": |
||||
Console.WriteLine("d"); |
||||
break; |
||||
} |
||||
Console.WriteLine("end"); |
||||
} |
||||
|
||||
public static void SwitchWithArray(string[] args) |
||||
{ |
||||
switch (args[0]) { |
||||
case "a": |
||||
Console.WriteLine("a"); |
||||
break; |
||||
case "b": |
||||
Console.WriteLine("b"); |
||||
break; |
||||
case "c": |
||||
Console.WriteLine("c"); |
||||
break; |
||||
case "d": |
||||
Console.WriteLine("d"); |
||||
break; |
||||
} |
||||
Console.WriteLine("end"); |
||||
} |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,329 @@
@@ -0,0 +1,329 @@
|
||||
// Copyright (c) 2017 Daniel Grunwald
|
||||
//
|
||||
// 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.Diagnostics; |
||||
using System.Linq; |
||||
using ICSharpCode.Decompiler.CSharp.Syntax; |
||||
using ICSharpCode.Decompiler.IL; |
||||
using ICSharpCode.Decompiler.Util; |
||||
|
||||
namespace ICSharpCode.Decompiler.CSharp |
||||
{ |
||||
/// <summary>
|
||||
/// Given a SyntaxTree that was output from the decompiler, constructs the list of sequence points.
|
||||
/// </summary>
|
||||
class SequencePointBuilder : DepthFirstAstVisitor |
||||
{ |
||||
struct StatePerSequencePoint |
||||
{ |
||||
/// <summary>
|
||||
/// Main AST node associated with this sequence point.
|
||||
/// </summary>
|
||||
internal readonly AstNode PrimaryNode; |
||||
|
||||
/// <summary>
|
||||
/// List of IL intervals that are associated with this sequence point.
|
||||
/// </summary>
|
||||
internal readonly List<Interval> Intervals; |
||||
|
||||
/// <summary>
|
||||
/// The function containing this sequence point.
|
||||
/// </summary>
|
||||
internal ILFunction Function; |
||||
|
||||
public StatePerSequencePoint(AstNode primaryNode) |
||||
{ |
||||
this.PrimaryNode = primaryNode; |
||||
this.Intervals = new List<Interval>(); |
||||
this.Function = null; |
||||
} |
||||
} |
||||
|
||||
readonly List<(ILFunction, SequencePoint)> sequencePoints = new List<(ILFunction, SequencePoint)>(); |
||||
readonly HashSet<ILInstruction> mappedInstructions = new HashSet<ILInstruction>(); |
||||
|
||||
// Stack holding information for outer statements.
|
||||
readonly Stack<StatePerSequencePoint> outerStates = new Stack<StatePerSequencePoint>(); |
||||
|
||||
// Collects information for the current sequence point.
|
||||
StatePerSequencePoint current; |
||||
|
||||
void VisitAsSequencePoint(AstNode node) |
||||
{ |
||||
if (node.IsNull) return; |
||||
StartSequencePoint(node); |
||||
node.AcceptVisitor(this); |
||||
EndSequencePoint(node.StartLocation, node.EndLocation); |
||||
} |
||||
|
||||
protected override void VisitChildren(AstNode node) |
||||
{ |
||||
base.VisitChildren(node); |
||||
AddToSequencePoint(node); |
||||
} |
||||
|
||||
public override void VisitBlockStatement(BlockStatement blockStatement) |
||||
{ |
||||
foreach (var stmt in blockStatement.Statements) { |
||||
VisitAsSequencePoint(stmt); |
||||
} |
||||
} |
||||
|
||||
public override void VisitForStatement(ForStatement forStatement) |
||||
{ |
||||
// Every element of a for-statement is it's own sequence point.
|
||||
foreach (var init in forStatement.Initializers) { |
||||
VisitAsSequencePoint(init); |
||||
} |
||||
VisitAsSequencePoint(forStatement.Condition); |
||||
foreach (var inc in forStatement.Iterators) { |
||||
VisitAsSequencePoint(inc); |
||||
} |
||||
VisitAsSequencePoint(forStatement.EmbeddedStatement); |
||||
} |
||||
|
||||
public override void VisitSwitchStatement(SwitchStatement switchStatement) |
||||
{ |
||||
StartSequencePoint(switchStatement); |
||||
switchStatement.Expression.AcceptVisitor(this); |
||||
foreach (var section in switchStatement.SwitchSections) { |
||||
// note: sections will not contribute to the current sequence point
|
||||
section.AcceptVisitor(this); |
||||
} |
||||
// add switch statement itself to sequence point
|
||||
// (call only after the sections are visited)
|
||||
AddToSequencePoint(switchStatement); |
||||
EndSequencePoint(switchStatement.StartLocation, switchStatement.RParToken.EndLocation); |
||||
} |
||||
|
||||
public override void VisitSwitchSection(Syntax.SwitchSection switchSection) |
||||
{ |
||||
// every statement in the switch section is its own sequence point
|
||||
foreach (var stmt in switchSection.Statements) { |
||||
VisitAsSequencePoint(stmt); |
||||
} |
||||
} |
||||
|
||||
public override void VisitLambdaExpression(LambdaExpression lambdaExpression) |
||||
{ |
||||
AddToSequencePoint(lambdaExpression); |
||||
VisitAsSequencePoint(lambdaExpression.Body); |
||||
} |
||||
|
||||
public override void VisitUsingStatement(UsingStatement usingStatement) |
||||
{ |
||||
StartSequencePoint(usingStatement); |
||||
usingStatement.ResourceAcquisition.AcceptVisitor(this); |
||||
VisitAsSequencePoint(usingStatement.EmbeddedStatement); |
||||
AddToSequencePoint(usingStatement); |
||||
EndSequencePoint(usingStatement.StartLocation, usingStatement.RParToken.EndLocation); |
||||
} |
||||
|
||||
public override void VisitForeachStatement(ForeachStatement foreachStatement) |
||||
{ |
||||
var foreachInfo = foreachStatement.Annotation<ForeachAnnotation>(); |
||||
if (foreachInfo == null) { |
||||
base.VisitForeachStatement(foreachStatement); |
||||
return; |
||||
} |
||||
// TODO : Add a sequence point on foreach token (mapped to nop before using instruction).
|
||||
StartSequencePoint(foreachStatement); |
||||
foreachStatement.InExpression.AcceptVisitor(this); |
||||
AddToSequencePoint(foreachInfo.GetEnumeratorCall); |
||||
EndSequencePoint(foreachStatement.InExpression.StartLocation, foreachStatement.InExpression.EndLocation); |
||||
StartSequencePoint(foreachStatement); |
||||
AddToSequencePoint(foreachInfo.MoveNextCall); |
||||
EndSequencePoint(foreachStatement.InToken.StartLocation, foreachStatement.InToken.EndLocation); |
||||
StartSequencePoint(foreachStatement); |
||||
AddToSequencePoint(foreachInfo.GetCurrentCall); |
||||
EndSequencePoint(foreachStatement.VariableType.StartLocation, foreachStatement.VariableNameToken.EndLocation); |
||||
VisitAsSequencePoint(foreachStatement.EmbeddedStatement); |
||||
} |
||||
|
||||
public override void VisitLockStatement(LockStatement lockStatement) |
||||
{ |
||||
StartSequencePoint(lockStatement); |
||||
lockStatement.Expression.AcceptVisitor(this); |
||||
VisitAsSequencePoint(lockStatement.EmbeddedStatement); |
||||
AddToSequencePoint(lockStatement); |
||||
EndSequencePoint(lockStatement.StartLocation, lockStatement.RParToken.EndLocation); |
||||
} |
||||
|
||||
public override void VisitIfElseStatement(IfElseStatement ifElseStatement) |
||||
{ |
||||
StartSequencePoint(ifElseStatement); |
||||
ifElseStatement.Condition.AcceptVisitor(this); |
||||
VisitAsSequencePoint(ifElseStatement.TrueStatement); |
||||
VisitAsSequencePoint(ifElseStatement.FalseStatement); |
||||
AddToSequencePoint(ifElseStatement); |
||||
EndSequencePoint(ifElseStatement.StartLocation, ifElseStatement.RParToken.EndLocation); |
||||
} |
||||
|
||||
public override void VisitWhileStatement(WhileStatement whileStatement) |
||||
{ |
||||
StartSequencePoint(whileStatement); |
||||
whileStatement.Condition.AcceptVisitor(this); |
||||
VisitAsSequencePoint(whileStatement.EmbeddedStatement); |
||||
AddToSequencePoint(whileStatement); |
||||
EndSequencePoint(whileStatement.StartLocation, whileStatement.RParToken.EndLocation); |
||||
} |
||||
|
||||
public override void VisitDoWhileStatement(DoWhileStatement doWhileStatement) |
||||
{ |
||||
StartSequencePoint(doWhileStatement); |
||||
VisitAsSequencePoint(doWhileStatement.EmbeddedStatement); |
||||
doWhileStatement.Condition.AcceptVisitor(this); |
||||
AddToSequencePoint(doWhileStatement); |
||||
EndSequencePoint(doWhileStatement.WhileToken.StartLocation, doWhileStatement.RParToken.EndLocation); |
||||
} |
||||
|
||||
public override void VisitFixedStatement(FixedStatement fixedStatement) |
||||
{ |
||||
foreach (var v in fixedStatement.Variables) { |
||||
VisitAsSequencePoint(v); |
||||
} |
||||
VisitAsSequencePoint(fixedStatement.EmbeddedStatement); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Start a new C# statement = new sequence point.
|
||||
/// </summary>
|
||||
void StartSequencePoint(AstNode primaryNode) |
||||
{ |
||||
outerStates.Push(current); |
||||
current = new StatePerSequencePoint(primaryNode); |
||||
} |
||||
|
||||
void EndSequencePoint(TextLocation startLocation, TextLocation endLocation) |
||||
{ |
||||
Debug.Assert(!startLocation.IsEmpty, "missing startLocation"); |
||||
Debug.Assert(!endLocation.IsEmpty, "missing endLocation"); |
||||
if (current.Intervals.Count > 0 && current.Function != null) { |
||||
// use LongSet to deduplicate and merge the intervals
|
||||
var longSet = new LongSet(current.Intervals.Select(i => new LongInterval(i.Start, i.End))); |
||||
Debug.Assert(!longSet.IsEmpty); |
||||
sequencePoints.Add((current.Function, new SequencePoint { |
||||
Offset = (int)longSet.Intervals[0].Start, |
||||
EndOffset = (int)longSet.Intervals[0].End, |
||||
StartLine = startLocation.Line, |
||||
StartColumn = startLocation.Column, |
||||
EndLine = endLocation.Line, |
||||
EndColumn = endLocation.Column |
||||
})); |
||||
} |
||||
current = outerStates.Pop(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Add the ILAst instruction associated with the AstNode to the sequence point.
|
||||
/// Also add all its ILAst sub-instructions (unless they were already added to another sequence point).
|
||||
/// </summary>
|
||||
void AddToSequencePoint(AstNode node) |
||||
{ |
||||
foreach (var inst in node.Annotations.OfType<ILInstruction>()) { |
||||
AddToSequencePoint(inst); |
||||
} |
||||
} |
||||
|
||||
void AddToSequencePoint(ILInstruction inst) |
||||
{ |
||||
if (!mappedInstructions.Add(inst)) { |
||||
// inst was already used by a nested sequence point within this sequence point
|
||||
return; |
||||
} |
||||
// Add the IL range associated with this instruction to the current sequence point.
|
||||
if (HasUsableILRange(inst) && current.Intervals != null) { |
||||
current.Intervals.Add(inst.ILRange); |
||||
var function = inst.Parent.Ancestors.OfType<ILFunction>().FirstOrDefault(); |
||||
Debug.Assert(current.Function == null || current.Function == function); |
||||
current.Function = function; |
||||
} |
||||
|
||||
// Do not add instructions of lambdas/delegates.
|
||||
if (inst is ILFunction) |
||||
return; |
||||
|
||||
// Also add the child IL instructions, unless they were already processed by
|
||||
// another C# expression.
|
||||
foreach (var child in inst.Children) { |
||||
AddToSequencePoint(child); |
||||
} |
||||
} |
||||
|
||||
internal static bool HasUsableILRange(ILInstruction inst) |
||||
{ |
||||
if (inst.ILRange.IsEmpty) |
||||
return false; |
||||
return !(inst is BlockContainer || inst is Block); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Called after the visitor is done to return the results.
|
||||
/// </summary>
|
||||
internal Dictionary<ILFunction, List<SequencePoint>> GetSequencePoints() |
||||
{ |
||||
var dict = new Dictionary<ILFunction, List<SequencePoint>>(); |
||||
foreach (var (function, sequencePoint) in this.sequencePoints) { |
||||
if (!dict.TryGetValue(function, out var list)) { |
||||
dict.Add(function, list = new List<SequencePoint>()); |
||||
} |
||||
list.Add(sequencePoint); |
||||
} |
||||
foreach (var (function, list) in dict.ToList()) { |
||||
// For each function, sort sequence points and fix overlaps+gaps
|
||||
var newList = new List<SequencePoint>(); |
||||
int pos = 0; |
||||
foreach (var sequencePoint in list.OrderBy(sp => sp.Offset).ThenBy(sp => sp.EndOffset)) { |
||||
if (sequencePoint.Offset < pos) { |
||||
// overlapping sequence point?
|
||||
// delete previous sequence points that are after sequencePoint.Offset
|
||||
while (newList.Count > 0 && newList.Last().EndOffset > pos) { |
||||
var last = newList.Last(); |
||||
if (last.Offset >= sequencePoint.Offset) { |
||||
newList.RemoveAt(newList.Count - 1); |
||||
} else { |
||||
last.EndOffset = sequencePoint.Offset; |
||||
newList[newList.Count - 1] = last; |
||||
} |
||||
} |
||||
} else if (sequencePoint.Offset > pos) { |
||||
// insert hidden sequence point in the gap.
|
||||
var hidden = new SequencePoint(); |
||||
hidden.Offset = pos; |
||||
hidden.EndOffset = sequencePoint.Offset; |
||||
hidden.SetHidden(); |
||||
newList.Add(hidden); |
||||
} |
||||
newList.Add(sequencePoint); |
||||
pos = sequencePoint.EndOffset; |
||||
} |
||||
if (pos < function.CecilMethod.Body.CodeSize) { |
||||
var hidden = new SequencePoint(); |
||||
hidden.Offset = pos; |
||||
hidden.EndOffset = function.CecilMethod.Body.CodeSize; |
||||
hidden.SetHidden(); |
||||
newList.Add(hidden); |
||||
} |
||||
dict[function] = newList; |
||||
} |
||||
return dict; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,81 @@
@@ -0,0 +1,81 @@
|
||||
// Copyright (c) 2017 Daniel Grunwald
|
||||
//
|
||||
// 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.ComponentModel; |
||||
using System.Runtime.CompilerServices; |
||||
|
||||
namespace ICSharpCode.Decompiler.IL |
||||
{ |
||||
public class ILAstWritingOptions : INotifyPropertyChanged |
||||
{ |
||||
private bool useLogicOperationSugar; |
||||
private bool useFieldSugar; |
||||
private bool showILRanges; |
||||
|
||||
/// <summary>
|
||||
/// Sugar for logic.not/and/or.
|
||||
/// </summary>
|
||||
public bool UseLogicOperationSugar { |
||||
get { return useLogicOperationSugar; } |
||||
set { |
||||
if (useLogicOperationSugar != value) { |
||||
useLogicOperationSugar = value; |
||||
OnPropertyChanged(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Sugar for ldfld/stfld.
|
||||
/// </summary>
|
||||
public bool UseFieldSugar { |
||||
get { return useFieldSugar; } |
||||
set { |
||||
if (useFieldSugar != value) { |
||||
useFieldSugar = value; |
||||
OnPropertyChanged(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Show IL ranges in ILAst output.
|
||||
/// </summary>
|
||||
public bool ShowILRanges { |
||||
get { return showILRanges; } |
||||
set { |
||||
if (showILRanges != value) { |
||||
showILRanges = value; |
||||
OnPropertyChanged(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) |
||||
{ |
||||
OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); |
||||
} |
||||
|
||||
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) |
||||
{ |
||||
PropertyChanged?.Invoke(this, e); |
||||
} |
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged; |
||||
} |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue