diff --git a/source2/Users/Matthijs ter Woord/Testing/MonoCecilToEcmaCil1/MonoCecilToEcmaCil1.csproj b/source2/Users/Matthijs ter Woord/Testing/MonoCecilToEcmaCil1/MonoCecilToEcmaCil1.csproj index 786b7470b..35b0d023d 100644 --- a/source2/Users/Matthijs ter Woord/Testing/MonoCecilToEcmaCil1/MonoCecilToEcmaCil1.csproj +++ b/source2/Users/Matthijs ter Woord/Testing/MonoCecilToEcmaCil1/MonoCecilToEcmaCil1.csproj @@ -78,16 +78,16 @@ - + - - - - - - - - + + + + + + + + diff --git a/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil.Tests/BaseTest.cs b/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil.Tests/BaseTest.cs index d32deca56..85af6a601 100644 --- a/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil.Tests/BaseTest.cs +++ b/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil.Tests/BaseTest.cs @@ -11,25 +11,24 @@ namespace ReflectionToEcmaCil.Tests { public class BaseTest { - protected void AssertCompilationSame(string refName, Type baseTYpe) + protected void AssertCompilationSame(string refName, Type baseType) { - //var xReader = new Reader(); - //var xResult = xReader.Execute(baseTYpe.Assembly.Location); - //string xActualOutput; - //using (var xStringWriter = new StringWriter()) - //{ - // using (var xXmlOut = XmlWriter.Create(xStringWriter)) - // { - // Dump.DumpTypes(xResult, xXmlOut); - // xXmlOut.Flush(); - // xStringWriter.Flush(); - // xActualOutput = xStringWriter.ToString(); - // } - //} + var xReader = new Reader(); + var xResult = xReader.Execute(baseType.Assembly.Location); + string xActualOutput; + using (var xStringWriter = new StringWriter()) + { + using (var xXmlOut = XmlWriter.Create(xStringWriter)) + { + Dump.DumpTypes(xResult, xXmlOut); + xXmlOut.Flush(); + xStringWriter.Flush(); + xActualOutput = xStringWriter.ToString(); + } + } - //var xExpectedOutput = ReadAllTextFromStream(typeof(BaseTest).Assembly.GetManifestResourceStream(typeof(BaseTest).Namespace + "." + refName + ".xml")); - //Assert.AreEqual(xExpectedOutput, xActualOutput); - Assert.Fail("Not implemented yet!"); + var xExpectedOutput = ReadAllTextFromStream(typeof(BaseTest).Assembly.GetManifestResourceStream(typeof(BaseTest).Namespace + "." + refName + ".xml")); + Assert.AreEqual(xExpectedOutput, xActualOutput); } private static string ReadAllTextFromStream(Stream aStream) diff --git a/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil.Tests/SimpleMethodsTest.cs b/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil.Tests/SimpleMethodsTest.cs index d8dc62258..1e91190ec 100644 --- a/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil.Tests/SimpleMethodsTest.cs +++ b/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil.Tests/SimpleMethodsTest.cs @@ -2,10 +2,17 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using NUnit.Framework; namespace ReflectionToEcmaCil.Tests { - public class SimpleMethodsTest: BaseTest + [TestFixture] + public class SimpleMethodsTestsTest : BaseTest { + [Test] + public void DoTest() + { + AssertCompilationSame("SimpleMethodsTests", typeof(SimpleMethodsTest.Program)); + } } } diff --git a/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil/Extensions.cs b/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil/Extensions.cs new file mode 100644 index 000000000..96e9244b3 --- /dev/null +++ b/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil/Extensions.cs @@ -0,0 +1,133 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Reflection; + +namespace ReflectionToEcmaCil +{ + public static class Extensions + { + public static string GetFullName(this MethodBase aMethod) + { + if (aMethod == null) + { + throw new ArgumentNullException("aMethod"); + } + var xBuilder = new StringBuilder(256); + var xParts = aMethod.ToString().Split(' '); + var xParts2 = xParts.Skip(1).ToArray(); + var xMethodInfo = aMethod as System.Reflection.MethodInfo; + if (xMethodInfo != null) + { + xBuilder.Append(GetFullName(xMethodInfo.ReturnType)); + } + else + { + var xCtor = aMethod as ConstructorInfo; + if (xCtor != null) + { + xBuilder.Append(typeof(void).FullName); + } + else + { + xBuilder.Append(xParts[0]); + } + } + xBuilder.Append(" "); + xBuilder.Append(GetFullName(aMethod.DeclaringType)); + xBuilder.Append("."); + xBuilder.Append(aMethod.Name); + if (aMethod.IsGenericMethod || aMethod.IsGenericMethodDefinition) + { + var xGenArgs = aMethod.GetGenericArguments(); + if (xGenArgs.Length > 0) + { + xBuilder.Append("<"); + for (int i = 0; i < xGenArgs.Length - 1; i++) + { + xBuilder.Append(GetFullName(xGenArgs[i])); + xBuilder.Append(", "); + } + xBuilder.Append(GetFullName(xGenArgs.Last())); + xBuilder.Append(">"); + } + } + xBuilder.Append("("); + var xParams = aMethod.GetParameters(); + for (var i = 0; i < xParams.Length; i++) + { + if (xParams[i].Name == "aThis" && i == 0) + { + continue; + } + xBuilder.Append(GetFullName(xParams[i].ParameterType)); + if (i < (xParams.Length - 1)) + { + xBuilder.Append(", "); + } + } + xBuilder.Append(")"); + return String.Intern(xBuilder.ToString()); + } + + private static string GetFullName(this Type aType) + { + if (aType.IsGenericParameter) + { + return aType.Name; + } + var xSB = new StringBuilder(); + if (aType.IsArray) + { + xSB.Append(aType.GetElementType().GetFullName()); + xSB.Append("["); + int xRank = aType.GetArrayRank(); + while (xRank > 1) + { + xSB.Append(","); + xRank--; + } + xSB.Append("]"); + return xSB.ToString(); + } + if (aType.IsByRef && aType.HasElementType) + { + return "&" + aType.GetElementType().GetFullName(); + } + if (aType.IsGenericType) + { + xSB.Append(aType.GetGenericTypeDefinition().FullName); + } + else + { + xSB.Append(aType.FullName); + } + if (aType.ContainsGenericParameters) + { + xSB.Append("<"); + var xArgs = aType.GetGenericArguments(); + for (int i = 0; i < xArgs.Length - 1; i++) + { + xSB.Append(GetFullName(xArgs[i])); + xSB.Append(", "); + } if (xArgs.Length == 0) { Console.Write(""); } + xSB.Append(GetFullName(xArgs.Last())); + xSB.Append(">"); + } + return xSB.ToString(); + } + + public static string GetFullName(this FieldInfo aField) + { + return aField.FieldType.GetFullName() + " " + aField.DeclaringType.GetFullName() + "." + aField.Name; + //var xSB = new StringBuilder(aField.FieldType.FullName.Length + 1 + aField.DeclaringType.FullName.Length + 1 + aField.Name); + //xSB.Append(aField.FieldType.FullName); + //xSB.Append(" "); + //xSB.Append(aField.DeclaringType.FullName); + //xSB.Append("."); + //xSB.Append(aField.Name); + //return String.Intern(xSB.ToString()); + } + } +} diff --git a/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil/ILStreamPositionReader.cs b/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil/ILStreamPositionReader.cs index 45832a9a1..87c91c0cd 100644 --- a/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil/ILStreamPositionReader.cs +++ b/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil/ILStreamPositionReader.cs @@ -7,17 +7,77 @@ namespace ReflectionToEcmaCil { public class ILStreamPositionReader { + private static readonly byte[] InstructionLengthsLow; + private static readonly byte[] InstructionLengthsHigh; + + static ILStreamPositionReader() + { + #region init InstructionLengthsLow + InstructionLengthsLow = new byte[256]{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 4, 8, 4, 8, 0, 0, 0, 4, 4, 4, 0, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, + 4, 4, 4, 4, 4, 4, 0, 0, 0, 4, 0, 4, 4, 4, 4, 4, + 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + #endregion + #region init InstructionLengthsHigh + InstructionLengthsHigh = new byte[256]{ + 0, 0, 0, 0, 0, 0, 4, 4, 0, 2, 2, 2, 2, 2, 2, 0, + 0, 0, 1, 0, 0, 4, 4, 0, 0, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + #endregion + } /// /// .Key contains stream index, .Value contains instruction (logical) index /// public static IEnumerable> GetIndexes(byte[] stream) { + int xCurrentIndex = 0; int xCurrentPosition = 0; yield return new KeyValuePair(0, 0); + while (xCurrentPosition < stream.Length) { - + var xOp = stream[xCurrentPosition]; + if (xOp == 0xFE) + { + xCurrentPosition++; + xOp = stream[xCurrentPosition]; + xCurrentPosition += InstructionLengthsHigh[xOp]; + } + else + { + xCurrentPosition += InstructionLengthsLow[xOp]; + } + xCurrentPosition++; + xCurrentIndex++; + yield return new KeyValuePair(xCurrentPosition, xCurrentIndex); } } } diff --git a/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil/Reader.ScanLog.cs b/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil/Reader.ScanLog.cs index 7d92b5f19..a80d54e27 100644 --- a/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil/Reader.ScanLog.cs +++ b/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil/Reader.ScanLog.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; +using System.Reflection; namespace ReflectionToEcmaCil { @@ -18,6 +19,103 @@ namespace ReflectionToEcmaCil } protected Dictionary> mLogMap; + public void EnableLogging(string aPathname) + { + mLogMap = new Dictionary>(); + mMapPathname = aPathname; + mLogEnabled = true; + } + + public void WriteScanMap() + { + if (mLogEnabled) + { + // Create bookmarks, but also a dictionary that + // we can find the items in + var xBookmarks = new Dictionary(); + int xBookmark = 0; + foreach (var xList in mLogMap) + { + foreach (var xItem in xList.Value) + { + if (!xBookmarks.ContainsKey(xItem.Item)) + { + xBookmarks.Add(xItem.Item, xBookmark); + xBookmark++; + } + } + } + using (mLogWriter = new StreamWriter(mMapPathname, false)) + { + mLogWriter.WriteLine(""); + foreach (var xList in mLogMap) + { + mLogWriter.WriteLine(""); + + // Emit bookmarks above source, so when clicking links user doesn't need + // to constantly scroll up. + foreach (var xItem in xList.Value) + { + mLogWriter.WriteLine(""); + } + + int xHref; + if (!xBookmarks.TryGetValue(xList.Key, out xHref)) + { + xHref = -1; + } + mLogWriter.Write(""); + if (xHref >= 0) + { + mLogWriter.WriteLine(""); + } + if (xList.Key == null) + { + mLogWriter.WriteLine("Unspecified Source"); + } + else + { + mLogWriter.WriteLine(LogItemText(xList.Key)); + } + if (xHref >= 0) + { + mLogWriter.Write(""); + } + mLogWriter.WriteLine(""); + + mLogWriter.WriteLine(""); + foreach (var xItem in xList.Value) + { + mLogWriter.Write("" + LogItemText(xItem.Item) + ""); + + mLogWriter.WriteLine(""); + mLogWriter.WriteLine("" + xItem.SrcType + ""); + mLogWriter.WriteLine(""); + } + mLogWriter.WriteLine(""); + } + mLogWriter.WriteLine(""); + } + } + } + + protected string LogItemText(object aItem) + { + if (aItem is MethodBase) + { + var x = (MethodBase)aItem; + return "Method: " + x.DeclaringType + "." + x.Name + "" + x.ToString(); + } + else if (aItem is Type) + { + var x = (Type)aItem; + return "Type: " + x.FullName; + } + else + { + return "Other: " + aItem.ToString(); + } + } private void LogMapPoint(object aSrc, string aSrcType, object aItem) { diff --git a/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil/Reader.Scanning.cs b/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil/Reader.Scanning.cs index 6c7cc5fcc..676816aed 100644 --- a/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil/Reader.Scanning.cs +++ b/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil/Reader.Scanning.cs @@ -231,5 +231,32 @@ namespace ReflectionToEcmaCil //} } } + + private void ScanArrayType(QueuedArrayType aArrayType, EcmaCil.ArrayTypeMeta aArrayMeta) + { + aArrayMeta.Dimensions = aArrayType.ArrayType.GetArrayRank(); + // todo: fix? + // foreach (ArrayDimension xDimension in aType.ArrayType.Dimensions) + //{ + // if (xDimension.LowerBound != 0 || xDimension.UpperBound != 0) + // { + // throw new Exception("Arrays with limited dimensions not supported"); + // } + //} + if (aArrayType.ArrayType.GetArrayRank() != 1) + { + throw new Exception("Multidimensional arrays not yet supported!"); + } + +#if DEBUG + var xSB = new StringBuilder(); + xSB.Append(aArrayMeta.ElementType.ToString()); + xSB.Append("["); + xSB.Append(new String(',', aArrayMeta.Dimensions - 1)); + xSB.Append("]"); + aArrayMeta.Data[EcmaCil.DataIds.DebugMetaId] = xSB.ToString(); +#endif + + } } } diff --git a/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil/Reader.cs b/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil/Reader.cs index 0303f7a1e..1cb2fc11e 100644 --- a/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil/Reader.cs +++ b/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil/Reader.cs @@ -61,12 +61,12 @@ namespace ReflectionToEcmaCil ScanMethod(xMethod, mMethods[xMethod]); continue; } - //if (xItem is QueuedArrayType) - //{ - // var xType = (QueuedArrayType)xItem; - // ScanArrayType(xType, mArrayTypes[xType]); - // continue; - //} + if (xItem is QueuedArrayType) + { + var xType = (QueuedArrayType)xItem; + ScanArrayType(xType, mArrayTypes[xType]); + continue; + } //if (xItem is QueuedPointerType) //{ // var xType = (QueuedPointerType)xItem; diff --git a/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil/ReflectionToEcmaCil.csproj b/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil/ReflectionToEcmaCil.csproj index af0b291b5..320b4eaa0 100644 --- a/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil/ReflectionToEcmaCil.csproj +++ b/source2/Users/Matthijs ter Woord/Testing/ReflectionToEcmaCil/ReflectionToEcmaCil.csproj @@ -61,8 +61,11 @@ 3.5 + + + diff --git a/source2/Users/Matthijs ter Woord/Testing/TestApp/Program.cs b/source2/Users/Matthijs ter Woord/Testing/TestApp/Program.cs index 9f71da71a..fca747057 100644 --- a/source2/Users/Matthijs ter Woord/Testing/TestApp/Program.cs +++ b/source2/Users/Matthijs ter Woord/Testing/TestApp/Program.cs @@ -5,6 +5,7 @@ using System.Text; using EcmaCil; using System.Xml; using System.Diagnostics; +using System.IO; namespace TestApp { @@ -12,17 +13,23 @@ namespace TestApp { public static void Main(string[] args) { - try + using (var xReader = new ReflectionToEcmaCil.Reader()) { - using (var xReader = new ReflectionToEcmaCil.Reader()) + try { + xReader.EnableLogging(Path.ChangeExtension(typeof(SimpleMethodsTest.Program).Assembly.Location, "html")); var xResult = xReader.Execute(typeof(SimpleMethodsTest.Program).Assembly.Location); - //xReader. + using (var xXmlOut = XmlWriter.Create(Path.ChangeExtension(typeof(SimpleMethodsTest.Program).Assembly.Location, "out"))) + { + Dump.DumpTypes(xResult, xXmlOut); + xXmlOut.Flush(); + } + } + catch (Exception E) + { + Console.WriteLine("Error: " + E.ToString()); + xReader.WriteScanMap(); } - } - catch (Exception E) - { - Console.WriteLine("Error: " + E.ToString()); } //using (var xReader = new MonoCecilToEcmaCil1.ReaderWithPlugSupport()) //{
"); + if (xHref >= 0) + { + mLogWriter.WriteLine(""); + } + if (xList.Key == null) + { + mLogWriter.WriteLine("Unspecified Source"); + } + else + { + mLogWriter.WriteLine(LogItemText(xList.Key)); + } + if (xHref >= 0) + { + mLogWriter.Write(""); + } + mLogWriter.WriteLine("