diff --git a/src/AddIns/BackendBindings/Boo/BooBinding.sln b/src/AddIns/BackendBindings/Boo/BooBinding.sln new file mode 100644 index 0000000000..8e83b8b057 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/BooBinding.sln @@ -0,0 +1,14 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# SharpDevelop 2.0.0.539 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRefactoryToBooConverter", "NRefactoryToBooConverter\Project\NRefactoryToBooConverter.csproj", "{DBCF20A1-BA13-4582-BFA9-74DE4D987B73}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRefactoryToBooConverter.Tests", "NRefactoryToBooConverter\Test\NRefactoryToBooConverter.Tests.csproj", "{C9DE556D-325C-4544-B29F-16A9EB7C9830}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRefactoryBooCompiler", "NRefactoryBooCompiler\NRefactoryBooCompiler.csproj", "{6AEB826B-DCB6-4440-8A81-5D77A1E4D36E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StandaloneConverter", "StandaloneConverter\StandaloneConverter.csproj", "{66338092-7611-40FC-B69C-B73A0528DA82}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BooBinding", "BooBinding\Project\BooBinding.csproj", "{4AC2D5F1-F671-480C-A075-6BF62B3721B2}" +EndProject +Global +EndGlobal diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/BooBinding.addin b/src/AddIns/BackendBindings/Boo/BooBinding/Project/BooBinding.addin new file mode 100644 index 0000000000..41b65901a5 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/BooBinding.addin @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/BooBinding.csproj b/src/AddIns/BackendBindings/Boo/BooBinding/Project/BooBinding.csproj new file mode 100644 index 0000000000..55d9ea0786 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/BooBinding.csproj @@ -0,0 +1,94 @@ + + + Library + Grunwald.BooBinding + BooBinding + Debug + AnyCPU + {4AC2D5F1-F671-480C-A075-6BF62B3721B2} + False + False + False + Auto + 4194304 + AnyCPU + 4096 + 4 + false + ..\..\..\..\..\..\AddIns\AddIns\BackendBindings\BooBinding\ + + + False + DEBUG;TRACE + true + Full + True + + + True + TRACE + False + None + False + + + + + + ..\..\RequiredLibraries\Boo.Lang.Compiler.dll + False + + + ..\..\RequiredLibraries\Boo.Lang.dll + False + + + ..\..\RequiredLibraries\Boo.Lang.Parser.dll + False + + + + + + Never + + + + + + + + + + + + + + + Always + + + Always + + + Always + + + Always + + + + {2748AD25-9C63-4E12-877B-4DCE96FBED54} + ICSharpCode.SharpDevelop + + + {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C} + ICSharpCode.Core + + + {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D} + ICSharpCode.TextEditor + + + + \ No newline at end of file diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Resources/Boo.xshd b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Resources/Boo.xshd new file mode 100644 index 0000000000..59fbdfcc32 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Resources/Boo.xshd @@ -0,0 +1,304 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + &<>~!@%^*()-+=|\#/{}[]:;"' , .? + + + """ + """ + + + + # + + + + // + + + + /* + */ + + + + " + " + + + + """ + """ + + + + ' + ' + + + + /@!/@ + / + + + ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &<>~!@%^*()-+=|\#/{}[]:;"' , .? + + + /* + */ + + + + + + &<>~!@%^*()-+=|\#/{}[]:;"' , .? + + + /* + */ + + + + + + &<>~!@%^*()-+=|\#/{}[]:;"' , .? + + + ${ + } + + + + + + + + diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/AssemblyInfo.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/AssemblyInfo.cs new file mode 100644 index 0000000000..e0ee20a70e --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/AssemblyInfo.cs @@ -0,0 +1,32 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following +// attributes. +// +// change them to the information which is associated with the assembly +// you compile. + +[assembly: AssemblyTitle("BooBinding")] +[assembly: AssemblyDescription("Boo language binding for #develop")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("www.icsharpcode.net")] +[assembly: AssemblyProduct("SharpDevelop")] +[assembly: AssemblyCopyright("(c) 2005 Daniel Grunwald")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// You can specify all values by your own or you can build default build and revision +// numbers with the '*' character (the default): + +[assembly: AssemblyVersion("2.0.0.1")] + +// The following attributes specify the key for the sign of your assembly. See the +// .NET Framework documentation for more information about signing. +// This is not required, if you don't want signing let these attributes like they're. +[assembly: AssemblyDelaySign(false)] +[assembly: AssemblyKeyFile("")] diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/BooAmbience.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/BooAmbience.cs new file mode 100644 index 0000000000..232e71967f --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/BooAmbience.cs @@ -0,0 +1,560 @@ +// +// 2002-2005 AlphaSierraPapa +// GNU General Public License +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using System.Text; +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Dom; + +namespace Grunwald.BooBinding +{ + public class BooAmbience : AbstractAmbience + { + // Fields + static Dictionary reverseTypeConversionTable = new Dictionary(); + static Dictionary typeConversionTable = new Dictionary(); + + public readonly static BooAmbience Instance = new BooAmbience(); + + /// + /// Gets a dictionary with boo's short names as keys and + /// the fully qualified type names as values. + /// + public static Dictionary ReverseTypeConversionTable { + get { + return reverseTypeConversionTable; + } + } + + /// + /// Gets a dictionary with the fully qualified type names as keys and + /// boo's short names as values. + /// + public static Dictionary TypeConversionTable { + get { + return typeConversionTable; + } + } + + static BooAmbience() + { + typeConversionTable.Add("System.Void", "void"); + typeConversionTable.Add("System.Object", "object"); + typeConversionTable.Add("System.Boolean", "bool"); + typeConversionTable.Add("System.Byte", "byte"); + typeConversionTable.Add("System.SByte", "sbyte"); + typeConversionTable.Add("System.Char", "char"); + typeConversionTable.Add("System.Int16", "short"); + typeConversionTable.Add("System.Int32", "int"); + typeConversionTable.Add("System.Int64", "long"); + typeConversionTable.Add("System.UInt16", "ushort"); + typeConversionTable.Add("System.UInt32", "uint"); + typeConversionTable.Add("System.UInt64", "ulong"); + typeConversionTable.Add("System.Single", "single"); + typeConversionTable.Add("System.Double", "double"); + typeConversionTable.Add("System.Decimal", "decimal"); + typeConversionTable.Add("System.String", "string"); + typeConversionTable.Add("System.DateTime", "date"); + typeConversionTable.Add("System.TimeSpan", "timespan"); + typeConversionTable.Add("System.Type", "type"); + typeConversionTable.Add("System.Array", "array"); + typeConversionTable.Add("System.Text.RegularExpressions.Regex", "regex"); + foreach (KeyValuePair pair in typeConversionTable) { + reverseTypeConversionTable.Add(pair.Value, pair.Key); + } + } + + public override string GetIntrinsicTypeName(string typeName) + { + if (typeConversionTable.ContainsKey(typeName)) + return typeConversionTable[typeName]; + else + return typeName; + } + + public static string GetFullTypeName(string shortName) + { + if (reverseTypeConversionTable.ContainsKey(shortName)) + return reverseTypeConversionTable[shortName]; + else + return shortName; + } + + public static IEnumerable> BooSpecialTypes { + get { + return typeConversionTable; + } + } + + // Methods + + bool ModifierIsSet(ModifierEnum modifier, ModifierEnum query) + { + return (modifier & query) == query; + } + + public override string Convert(ModifierEnum modifier) + { + if (ShowAccessibility) { + if (ModifierIsSet(modifier, ModifierEnum.Public)) { + return "public "; + } else if (ModifierIsSet(modifier, ModifierEnum.Private)) { + return "private "; + } else if (ModifierIsSet(modifier, ModifierEnum.ProtectedAndInternal)) { + return "protected internal "; + } else if (ModifierIsSet(modifier, ModifierEnum.ProtectedOrInternal)) { + return "internal protected "; + } else if (ModifierIsSet(modifier, ModifierEnum.Internal)) { + return "internal "; + } else if (ModifierIsSet(modifier, ModifierEnum.Protected)) { + return "protected "; + } + } + return string.Empty; + } + + string GetModifier(IDecoration decoration) + { + string ret = ""; + + if (IncludeHTMLMarkup) { + ret += ""; + } + if (decoration.IsStatic) { + ret += "static "; + } else if (decoration.IsSealed) { + ret += "final "; + } else if (decoration.IsOverride) { + ret += "override "; + } else if (decoration.IsNew) { + ret += "new "; + } + if (IncludeHTMLMarkup) { + ret += ""; + } + return ret; + } + + + public override string Convert(IClass c) + { + StringBuilder builder = new StringBuilder(); + + builder.Append(Convert(c.Modifiers)); + + if (IncludeHTMLMarkup) { + builder.Append(""); + } + + if (ShowModifiers) { + if (c.IsSealed) { + switch (c.ClassType) { + case ClassType.Delegate: + case ClassType.Struct: + case ClassType.Enum: + break; + + default: + builder.Append("final "); + break; + } + } else if (c.IsAbstract && c.ClassType != ClassType.Interface) { + builder.Append("abstract "); + } + } + + if (IncludeHTMLMarkup) { + builder.Append(""); + } + + if (ShowModifiers) { + switch (c.ClassType) { + case ClassType.Delegate: + builder.Append("callable"); + break; + case ClassType.Class: + case ClassType.Module: + builder.Append("class"); + break; + case ClassType.Struct: + builder.Append("struct"); + break; + case ClassType.Interface: + builder.Append("interface"); + break; + case ClassType.Enum: + builder.Append("enum"); + break; + } + builder.Append(' '); + } + + if (IncludeHTMLMarkup) { + builder.Append(""); + } + + if (UseFullyQualifiedMemberNames) { + builder.Append(c.FullyQualifiedName); + } else { + builder.Append(c.Name); + } + + if (IncludeHTMLMarkup) { + builder.Append(""); + } + if (c.TypeParameters.Count > 0) { + builder.Append("[of "); + for (int i = 0; i < c.TypeParameters.Count; ++i) { + if (i > 0) builder.Append(", "); + builder.Append(c.TypeParameters[i].Name); + } + builder.Append(']'); + } + + if (ShowReturnType && c.ClassType == ClassType.Delegate) { + builder.Append(" ("); + if (IncludeHTMLMarkup) builder.Append("
"); + + foreach(IMethod m in c.Methods) { + if (m.Name != "Invoke") continue; + + for (int i = 0; i < m.Parameters.Count; ++i) { + if (IncludeHTMLMarkup) builder.Append("   "); + + builder.Append(Convert(m.Parameters[i])); + if (i + 1 < m.Parameters.Count) builder.Append(", "); + + if (IncludeHTMLMarkup) builder.Append("
"); + } + } + builder.Append(')'); + + foreach(IMethod m in c.Methods) { + if (m.Name != "Invoke") continue; + + builder.Append(" as "); + builder.Append(Convert(m.ReturnType)); + } + + } else if (ShowInheritanceList) { + if (c.BaseTypes.Count > 0) { + builder.Append("("); + for (int i = 0; i < c.BaseTypes.Count; ++i) { + builder.Append(c.BaseTypes[i]); + if (i + 1 < c.BaseTypes.Count) { + builder.Append(", "); + } + } + builder.Append(")"); + } + } + + if (IncludeBodies) { + builder.Append(":\n"); + } + + return builder.ToString(); + } + + public override string ConvertEnd(IClass c) + { + return ""; + } + + public override string Convert(IField field) + { + StringBuilder builder = new StringBuilder(); + + builder.Append(Convert(field.Modifiers)); + + if (IncludeHTMLMarkup) { + builder.Append(""); + } + + if (ShowModifiers) { + if (field.IsConst) { + builder.Append("static final "); + } else if (field.IsStatic) { + builder.Append("static "); + } + + if (field.IsReadonly) { + builder.Append("final "); + } + } + + if (IncludeHTMLMarkup) { + builder.Append(""); + } + + if (IncludeHTMLMarkup) { + builder.Append(""); + } + + if (UseFullyQualifiedMemberNames) { + builder.Append(field.FullyQualifiedName); + } else { + builder.Append(field.Name); + } + + if (IncludeHTMLMarkup) { + builder.Append(""); + } + + if (field.ReturnType != null && ShowReturnType) { + builder.Append(" as "); + builder.Append(Convert(field.ReturnType)); + } + + return builder.ToString(); + } + + public override string Convert(IProperty property) + { + StringBuilder builder = new StringBuilder(); + + builder.Append(Convert(property.Modifiers)); + + if (ShowModifiers) { + builder.Append(GetModifier(property)); + } + + if (property.IsIndexer) { + builder.Append("self"); + } else { + if (IncludeHTMLMarkup) { + builder.Append(""); + } + if (UseFullyQualifiedMemberNames) { + builder.Append(property.FullyQualifiedName); + } else { + builder.Append(property.Name); + } + if (IncludeHTMLMarkup) { + builder.Append(""); + } + } + + if (property.Parameters.Count > 0) { + builder.Append('['); + if (IncludeHTMLMarkup) builder.Append("
"); + + for (int i = 0; i < property.Parameters.Count; ++i) { + if (IncludeHTMLMarkup) builder.Append("   "); + builder.Append(Convert(property.Parameters[i])); + if (i + 1 < property.Parameters.Count) { + builder.Append(", "); + } + if (IncludeHTMLMarkup) builder.Append("
"); + } + + builder.Append(']'); + } + + if (property.ReturnType != null && ShowReturnType) { + builder.Append(" as "); + builder.Append(Convert(property.ReturnType)); + } + + if (IncludeBodies) { + builder.Append(":"); + + if (property.CanGet) { + builder.Append(" get"); + } + if (property.CanSet) { + builder.Append(" set"); + } + } + + return builder.ToString(); + } + + public override string Convert(IEvent e) + { + StringBuilder builder = new StringBuilder(); + + builder.Append(Convert(e.Modifiers)); + + if (ShowModifiers) { + builder.Append(GetModifier(e)); + } + + builder.Append("event "); + + if (IncludeHTMLMarkup) { + builder.Append(""); + } + + if (UseFullyQualifiedMemberNames) { + builder.Append(e.FullyQualifiedName); + } else { + builder.Append(e.Name); + } + + if (IncludeHTMLMarkup) { + builder.Append(""); + } + + if (e.ReturnType != null && ShowReturnType) { + builder.Append(" as "); + builder.Append(Convert(e.ReturnType)); + } + + return builder.ToString(); + } + + public override string Convert(IMethod m) + { + StringBuilder builder = new StringBuilder(); + builder.Append(Convert(m.Modifiers)); + + if (ShowModifiers) { + builder.Append(GetModifier(m)); + } + + builder.Append("def "); + + if (IncludeHTMLMarkup) { + builder.Append(""); + } + + if (m.IsConstructor) { + builder.Append("constructor"); + } else { + if (UseFullyQualifiedMemberNames) { + builder.Append(m.FullyQualifiedName); + } else { + builder.Append(m.Name); + } + } + + if (IncludeHTMLMarkup) { + builder.Append(""); + } + + if (m.TypeParameters.Count > 0) { + builder.Append("[of "); + for (int i = 0; i < m.TypeParameters.Count; ++i) { + if (i > 0) builder.Append(", "); + builder.Append(m.TypeParameters[i].Name); + } + builder.Append(']'); + } + + builder.Append("("); + if (IncludeHTMLMarkup) builder.Append("
"); + + for (int i = 0; i < m.Parameters.Count; ++i) { + if (IncludeHTMLMarkup) builder.Append("   "); + builder.Append(Convert(m.Parameters[i])); + if (i + 1 < m.Parameters.Count) { + builder.Append(", "); + } + if (IncludeHTMLMarkup) builder.Append("
"); + } + + builder.Append(')'); + + if (m.ReturnType != null && ShowReturnType) { + builder.Append(" as "); + builder.Append(Convert(m.ReturnType)); + } + + return builder.ToString(); + } + + public override string ConvertEnd(IMethod m) + { + return ""; + } + + public override string Convert(IReturnType returnType) + { + if (returnType == null) { + return String.Empty; + } + StringBuilder builder = new StringBuilder(); + UnpackNestedType(builder, returnType); + return builder.ToString(); + } + + void UnpackNestedType(StringBuilder builder, IReturnType returnType) + { + ArrayReturnType art = returnType as ArrayReturnType; + if (art != null) { + builder.Append('('); + UnpackNestedType(builder, art.ElementType); + for (int i = 1; i < art.ArrayDimensions; ++i) { + builder.Append(','); + } + builder.Append(')'); + } else if (returnType is ConstructedReturnType) { + ConstructedReturnType rt = (ConstructedReturnType)returnType; + UnpackNestedType(builder, rt.BaseType); + builder.Append("[of "); + for (int i = 0; i < rt.TypeArguments.Count; ++i) { + if (i > 0) builder.Append(", "); + builder.Append(Convert(rt.TypeArguments[i])); + } + builder.Append(']'); + } else { + string fullName = returnType.FullyQualifiedName; + if (fullName != null && typeConversionTable.ContainsKey(fullName)) { + builder.Append(typeConversionTable[fullName].ToString()); + } else { + if (UseFullyQualifiedNames) { + builder.Append(fullName); + } else { + builder.Append(returnType.Name); + } + } + } + } + + public override string Convert(IParameter param) + { + StringBuilder builder = new StringBuilder(); + + if (IncludeHTMLMarkup) { + builder.Append(""); + } + + if (param.IsRef) { + builder.Append("ref "); + } else if (param.IsOut) { + builder.Append("ref "); + } else if (param.IsParams) { + builder.Append("*"); + } + + if (IncludeHTMLMarkup) { + builder.Append(""); + } + + if (ShowParameterNames) { + builder.Append(param.Name); + builder.Append(" as "); + } + + builder.Append(Convert(param.ReturnType)); + + return builder.ToString(); + } + + public override string WrapAttribute(string attribute) + { + return "[" + attribute + "]"; + } + + public override string WrapComment(string comment) + { + return "// " + comment; + } + } +} diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/BooLanguageBinding.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/BooLanguageBinding.cs new file mode 100644 index 0000000000..5a546893e2 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/BooLanguageBinding.cs @@ -0,0 +1,73 @@ +// +// 2002-2005 AlphaSierraPapa +// GNU General Public License +// +// $Revision$ +// + +using System; +using System.IO; +using System.Diagnostics; +using System.Collections; +using System.Reflection; +using System.Resources; +using System.Windows.Forms; +using System.Xml; +using System.CodeDom.Compiler; +using System.Threading; +using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.SharpDevelop.Internal.Templates; +using ICSharpCode.SharpDevelop.Gui; +using ICSharpCode.Core; + +namespace Grunwald.BooBinding +{ + public class BooLanguageBinding : ILanguageBinding + { + public const string LanguageName = "Boo"; + + public string Language { + get { + return LanguageName; + } + } + + #region routines for single file compilation + public bool CanCompile(string fileName) + { + string ext = Path.GetExtension(fileName); + if (ext == null) + return false; + return string.Equals(ext, ".BOO", StringComparison.InvariantCultureIgnoreCase); + } + + public string GetCompiledOutputName(string fileName) + { + return Path.ChangeExtension(fileName, ".exe"); + } + + public CompilerResults CompileFile(string fileName) + { + throw new NotImplementedException(); + } + + public void Execute(string fileName, bool debug) + { + throw new NotImplementedException(); // only needed for single-file compilation + } + #endregion + + public IProject LoadProject(string fileName, string projectName) + { + return new BooProject(fileName, projectName); + } + + public IProject CreateProject(ProjectCreateInformation info, XmlElement projectOptions) + { + BooProject p = new BooProject(info); + if (projectOptions != null) + p.ImportOptions(projectOptions.Attributes); + return p; + } + } +} diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/BooProject.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/BooProject.cs new file mode 100644 index 0000000000..d7c5caf28c --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/BooProject.cs @@ -0,0 +1,45 @@ +// +// 2002-2005 AlphaSierraPapa +// GNU General Public License +// +// $Revision$ +// + +using System; +using System.ComponentModel; +using ICSharpCode.SharpDevelop.Internal.Templates; +using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.Core; + +namespace Grunwald.BooBinding +{ + public class BooProject : MSBuildProject + { + public BooProject(string fileName, string projectName) + { + this.Name = projectName; + Language = "Boo"; + SetupProject(fileName); + IdGuid = BaseConfiguration["ProjectGuid"]; + } + + public BooProject(ProjectCreateInformation info) + { + Language = "Boo"; + Create(info); + imports.Add("$(BooBinPath)\\MsBuild.Boo.Targets"); + } + + public override bool CanCompile(string fileName) + { + return new BooLanguageBinding().CanCompile(fileName); + } + + [Browsable(false)] + public override IAmbience Ambience { + get { + return BooAmbience.Instance; + } + } + } +} diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooParser.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooParser.cs new file mode 100644 index 0000000000..42f4f8c00b --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooParser.cs @@ -0,0 +1,128 @@ +// +// 2002-2005 AlphaSierraPapa +// GNU General Public License +// +// $Revision$ +// + +using System; +using System.IO; +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.SharpDevelop.Dom; +using Boo.Lang.Compiler; +using Boo.Lang.Compiler.IO; +using Boo.Lang.Compiler.Pipelines; +using Boo.Lang.Compiler.Steps; +using Boo.Lang.Parser; + +namespace Grunwald.BooBinding.CodeCompletion +{ + public class BooParser : IParser + { + ///IParser Interface + string[] lexerTags; + + public string[] LexerTags { + get { + return lexerTags; + } + set { + lexerTags = value; + } + } + + public IExpressionFinder CreateExpressionFinder(string fileName) + { + return new ExpressionFinder(fileName); + } + + public bool CanParse(string fileName) + { + return string.Equals(Path.GetExtension(fileName), ".boo", StringComparison.InvariantCultureIgnoreCase); + } + + public bool CanParse(IProject project) + { + return project.Language == BooLanguageBinding.LanguageName; + } + + public ICompilationUnit Parse(IProjectContent projectContent, string fileName) + { + string content; + using (StreamReader reader = new StreamReader(fileName)) { + content = reader.ReadToEnd(); + } + return Parse(projectContent, fileName, content); + } + + public ICompilationUnit Parse(IProjectContent projectContent, string fileName, string fileContent) + { + LoggingService.Debug("Parse " + fileName); + int lineCount = 1; + foreach (char c in fileContent) { + if (c == '\n') { + lineCount++; + } + } + int[] lineLength = new int[lineCount]; + int length = 0; + int i = 0; + foreach (char c in fileContent) { + if (c == '\n') { + lineLength[i] = length; + i += 1; + length = 0; + } else if (c != '\r') { + length += 1; + } + } + lineLength[i] = length; + BooCompiler compiler = new BooCompiler(); + compiler.Parameters.Input.Add(new StringInput(fileName, fileContent)); + return Parse(projectContent, fileName, lineLength, compiler); + } + + private ICompilationUnit Parse(IProjectContent projectContent, string fileName, int[] lineLength, BooCompiler compiler) + { + compiler.Parameters.OutputWriter = new StringWriter(); + compiler.Parameters.TraceSwitch.Level = System.Diagnostics.TraceLevel.Warning; + + Compile compilePipe = new Compile(); + BooParsingStep parsingStep = (BooParsingStep)compilePipe[0]; + parsingStep.TabSize = 1; + + ConvertVisitor visitor = new ConvertVisitor(lineLength, projectContent); + visitor.Cu.FileName = fileName; + + // Remove unneccessary compiler steps + int num = 1 + compilePipe.Find(typeof(NormalizeTypeAndMemberDefinitions)); + compilePipe[num] = visitor; + while (compilePipe.Count > num + 1) + compilePipe.RemoveAt(compilePipe.Count - 1); + num = compilePipe.Find(typeof(TransformCallableDefinitions)); + compilePipe.RemoveAt(num); + + for (int i = 0; i < compilePipe.Count; i++) { + Console.WriteLine(compilePipe[i]); + } + + compilePipe.BreakOnErrors = false; + compiler.Parameters.Pipeline = compilePipe; + + try { + compiler.Run(); + // somehow the SD parser thread goes into an endless loop if this flag is not set + visitor.Cu.ErrorsDuringCompile = true; //context.Errors.Count > 0 + } catch (Exception ex) { + MessageService.ShowError(ex); + } + return visitor.Cu; + } + + public IResolver CreateResolver() + { + return new BooResolver(); + } + } +} diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooResolver.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooResolver.cs new file mode 100644 index 0000000000..7140a79315 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooResolver.cs @@ -0,0 +1,181 @@ +// +// 2002-2005 AlphaSierraPapa +// GNU General Public License +// +// $Revision$ +// + +using System; +using System.Collections; +using System.Collections.Generic; +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Dom; +using Boo.Lang.Compiler; +using AST = Boo.Lang.Compiler.Ast; +using Boo.Lang.Compiler.IO; +using Boo.Lang.Compiler.Steps; +using NRResolver = ICSharpCode.SharpDevelop.Dom.NRefactoryResolver.NRefactoryResolver; + +namespace Grunwald.BooBinding.CodeCompletion +{ + public class BooResolver : IResolver + { + #region Fields and properties + ICompilationUnit cu; + IProjectContent pc; + int caretLine; + int caretColumn; + IClass callingClass; + IMember callingMember; + + public IClass CallingClass { + get { + return callingClass; + } + } + + public IMember CallingMember { + get { + return callingMember; + } + } + + public int CaretLine { + get { + return caretLine; + } + } + + public int CaretColumn { + get { + return caretColumn; + } + } + + public IProjectContent ProjectContent { + get { + return pc; + } + } + + public ICompilationUnit CompilationUnit { + get { + return cu; + } + } + #endregion + + #region Initialization + bool Initialize(string fileName, int caretLine, int caretColumn) + { + ParseInformation parseInfo = ParserService.GetParseInformation(fileName); + if (parseInfo == null) { + return false; + } + this.cu = parseInfo.MostRecentCompilationUnit; + this.pc = cu.ProjectContent; + this.caretLine = caretLine; + this.caretColumn = caretColumn; + this.callingClass = cu.GetInnermostClass(caretLine, caretColumn); + if (callingClass == null) { + if (cu.Classes.Count == 0) return false; + callingClass = cu.Classes[cu.Classes.Count - 1]; + if (!callingClass.Region.IsEmpty) { + if (callingClass.Region.BeginLine > caretLine) + return false; + } + } + callingMember = ResolveCurrentMember(); + return true; + } + + IMember ResolveCurrentMember() + { + LoggingService.DebugFormatted("Getting current method... caretLine = {0}, caretColumn = {1}", caretLine, caretColumn); + if (callingClass == null) return null; + IMember best = null; + int line = 0; + foreach (IMember m in callingClass.Methods) { + if (m.Region.BeginLine <= caretLine && m.Region.BeginLine > line) { + line = m.Region.BeginLine; + best = m; + } + } + foreach (IMember m in callingClass.Properties) { + if (m.Region.BeginLine <= caretLine && m.Region.BeginLine > line) { + line = m.Region.BeginLine; + best = m; + } + } + if (callingClass.Region.IsEmpty) { + foreach (IMember m in callingClass.Methods) { + if (best == null || best.Region.EndLine < caretLine) + return m; + } + } + return best; + } + #endregion + + #region Resolve + public ResolveResult Resolve(ExpressionResult expressionResult, + int caretLineNumber, int caretColumn, + string fileName, string fileContent) + { + if (!Initialize(fileName, caretLineNumber, caretColumn)) + return null; + AST.Expression expr = Boo.Lang.Parser.BooParser.ParseExpression("expression", expressionResult.Expression); + if (expr is AST.IntegerLiteralExpression) + return null; // no CC for "5." + ResolveVisitor visitor = new ResolveVisitor(this); + visitor.Visit(expr); + return visitor.ResolveResult; + } + #endregion + + #region CtrlSpace + IClass GetPrimitiveClass(string systemType, string newName) + { + IClass c = pc.GetClass(systemType); + if (c == null) { + LoggingService.Warn("Could not find " + systemType); + return null; + } + DefaultClass c2 = new DefaultClass(c.CompilationUnit, newName); + c2.ClassType = c.ClassType; + c2.Modifiers = c.Modifiers; + c2.Documentation = c.Documentation; + c2.BaseTypes.AddRange(c.BaseTypes); + c2.Methods.AddRange(c.Methods); + c2.Fields.AddRange(c.Fields); + c2.Properties.AddRange(c.Properties); + c2.Events.AddRange(c.Events); + return c2; + } + + public ArrayList CtrlSpace(int caretLine, int caretColumn, string fileName, string fileContent) + { + if (!Initialize(fileName, caretLine, caretColumn)) + return null; + ArrayList result = GetImportedNamespaceContents(); + + NRResolver.AddContentsFromCalling(result, callingClass, callingMember); + + return result; + } + + // used by ctrl+space and resolve visitor (resolve identifier) + public ArrayList GetImportedNamespaceContents() + { + ArrayList list = new ArrayList(); + IClass c; + foreach (KeyValuePair pair in BooAmbience.TypeConversionTable) { + c = GetPrimitiveClass(pair.Key, pair.Value); + if (c != null) list.Add(c); + } + NRResolver.AddImportedNamespaceContents(list, cu, callingClass); + return list; + } + #endregion + } +} diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/CompletionBinding.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/CompletionBinding.cs new file mode 100644 index 0000000000..3cef8aa611 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/CompletionBinding.cs @@ -0,0 +1,51 @@ +// +// 2002-2005 AlphaSierraPapa +// GNU General Public License +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using System.Globalization; + +using ICSharpCode.Core; +using ICSharpCode.TextEditor.Gui.CompletionWindow; +using ICSharpCode.TextEditor.Document; +using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; + +namespace Grunwald.BooBinding.CodeCompletion +{ + public class CompletionBinding : DefaultCodeCompletionBinding + { + public CompletionBinding() + { + this.EnableXmlCommentCompletion = false; + } + + bool IsInComment(SharpDevelopTextAreaControl editor) + { + ExpressionFinder ef = new ExpressionFinder(editor.FileName); + int cursor = editor.ActiveTextAreaControl.Caret.Offset - 1; + return ef.SimplifyCode(editor.Document.GetText(0, cursor + 1), cursor) == null; + } + + public override bool HandleKeyword(SharpDevelopTextAreaControl editor, string word) + { + switch (word.ToLower(CultureInfo.InvariantCulture)) { + case "import": + editor.ShowCompletionWindow(new CodeCompletionDataProvider(new ExpressionResult("Global", ExpressionContext.Type)), ' '); + return true; + case "as": + case "isa": + if (IsInComment(editor)) return false; + editor.ShowCompletionWindow(new CtrlSpaceCompletionDataProvider(ExpressionContext.Type), ' '); + return true; + default: + return base.HandleKeyword(editor, word); + } + } + } +} diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ConvertVisitor.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ConvertVisitor.cs new file mode 100644 index 0000000000..0eb747c704 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ConvertVisitor.cs @@ -0,0 +1,393 @@ +// +// 2002-2005 AlphaSierraPapa +// GNU General Public License +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Dom; +using Boo.Lang.Compiler; +using AST = Boo.Lang.Compiler.Ast; +using Boo.Lang.Compiler.IO; +using Boo.Lang.Compiler.Steps; + +namespace Grunwald.BooBinding.CodeCompletion +{ + public class ConvertVisitor : AbstractVisitorCompilerStep + { + int[] _lineLength; + + public ConvertVisitor(int[] _lineLength, IProjectContent pc) + { + this._lineLength = _lineLength; + this._cu = new DefaultCompilationUnit(pc); + } + + DefaultCompilationUnit _cu; + + public DefaultCompilationUnit Cu { + get { + return _cu; + } + } + + Stack _currentClass = new Stack(); + bool _firstModule = true; + + public override void Run() + { + LoggingService.Debug("RUN"); + try { + Visit(CompileUnit); + } catch (Exception ex) { + MessageService.ShowError(ex); + } + } + + private ModifierEnum GetModifier(AST.TypeMember m) + { + ModifierEnum r = ModifierEnum.None; + if (m.IsPublic) r |= ModifierEnum.Public; + if (m.IsProtected) r |= ModifierEnum.Protected; + if (m.IsPrivate) r |= ModifierEnum.Private; + if (m.IsInternal) r |= ModifierEnum.Internal; + + if (m.IsStatic) r |= ModifierEnum.Static; + if (m is AST.Field) { + if (m.IsFinal) r |= ModifierEnum.Readonly; + } else { + if (!m.IsFinal) r |= ModifierEnum.Virtual; + } + if (m.IsAbstract) r |= ModifierEnum.Abstract; + if (m.IsOverride) r |= ModifierEnum.Override; + return r; + } + + private int GetLineEnd(int line) + { + if (_lineLength == null || line < 1 || line > _lineLength.Length) + return 0; + else + return _lineLength[line - 1] + 1; + } + + private DomRegion GetRegion(AST.Node m) + { + AST.LexicalInfo l = m.LexicalInfo; + if (l.Line < 0) + return DomRegion.Empty; + else + return new DomRegion(l.Line, 0 /*l.Column*/, l.Line, GetLineEnd(l.Line)); + } + + private DomRegion GetClientRegion(AST.Node m) + { + AST.LexicalInfo l = m.LexicalInfo; + if (l.Line < 0) + return DomRegion.Empty; + AST.SourceLocation l2; + if (m is AST.Method) { + l2 = ((AST.Method)m).Body.EndSourceLocation; + } else if (m is AST.Property) { + AST.Property p = (AST.Property)m; + if (p.Getter != null && p.Getter.Body != null) { + l2 = p.Getter.Body.EndSourceLocation; + if (p.Setter != null && p.Setter.Body != null) { + if (p.Setter.Body.EndSourceLocation.Line > l2.Line) + l2 = p.Setter.Body.EndSourceLocation; + } + } else if (p.Setter != null && p.Setter.Body != null) { + l2 = p.Setter.Body.EndSourceLocation; + } else { + l2 = p.EndSourceLocation; + } + } else { + l2 = m.EndSourceLocation; + } + if (l2 == null || l2.Line < 0 || l.Line == l2.Line) + return DomRegion.Empty; + // TODO: use l.Column / l2.Column when the tab-bug has been fixed + return new DomRegion(l.Line, GetLineEnd(l.Line), l2.Line, GetLineEnd(l2.Line)); + } + + public override void OnImport(AST.Import p) + { + DefaultUsing u = new DefaultUsing(_cu.ProjectContent); + if (p.Alias == null) + u.Usings.Add(p.Namespace); + else + u.Aliases[p.Alias.Name] = new GetClassReturnType(_cu.ProjectContent, p.Namespace, 0); + _cu.Usings.Add(u); + } + + private IClass OuterClass { + get { + if (_currentClass.Count > 0) + return _currentClass.Peek(); + else + return null; + } + } + + void ConvertTemplates(AST.Node node, DefaultClass c) + { + c.TypeParameters = DefaultTypeParameter.EmptyTypeParameterList; + } + + void ConvertTemplates(AST.Node node, DefaultMethod m) + { + m.TypeParameters = DefaultTypeParameter.EmptyTypeParameterList; + } + + void ConvertAttributes(AST.Node node, AbstractDecoration c) + { + c.Attributes = DefaultAttribute.EmptyAttributeList; + c.Documentation = node.Documentation; + } + + void ConvertParameters(AST.ParameterDeclarationCollection parameters, DefaultMethod m) + { + if (parameters == null || parameters.Count == 0) { + m.Parameters = DefaultParameter.EmptyParameterList; + } else { + AddParameters(parameters, m.Parameters); + } + } + void ConvertParameters(AST.ParameterDeclarationCollection parameters, DefaultProperty p) + { + if (parameters == null || parameters.Count == 0) { + p.Parameters = DefaultParameter.EmptyParameterList; + } else { + AddParameters(parameters, p.Parameters); + } + } + void AddParameters(AST.ParameterDeclarationCollection parameters, IList output) + { + DefaultParameter p = null; + foreach (AST.ParameterDeclaration par in parameters) { + p = new DefaultParameter(par.Name, CreateReturnType(par.Type), GetRegion(par)); + if (par.IsByRef) p.Modifiers |= ParameterModifiers.Ref; + output.Add(p); + } + if (parameters.VariableNumber) { + p.Modifiers |= ParameterModifiers.Params; + } + } + + IReturnType CreateReturnType(AST.TypeReference reference, IMethod method) + { + IClass c = OuterClass; + if (c == null) { + return CreateReturnType(reference, new DefaultClass(_cu, "___DummyClass"), method, 1, 1, _cu.ProjectContent, true); + } else { + return CreateReturnType(reference, c, method, c.Region.BeginLine + 1, 1, _cu.ProjectContent, true); + } + } + public static IReturnType CreateReturnType(AST.TypeReference reference, IClass callingClass, + IMember callingMember, int caretLine, int caretColumn, + IProjectContent projectContent, + bool useLazyReturnType) + { + if (reference == null) { + LoggingService.Warn("inferred return type!"); + return ReflectionReturnType.Object; + } + if (reference is AST.ArrayTypeReference) { + AST.ArrayTypeReference arr = (AST.ArrayTypeReference)reference; + return new ArrayReturnType(CreateReturnType(arr.ElementType, callingClass, callingMember, + caretLine, caretColumn, projectContent, useLazyReturnType), + (int)arr.Rank.Value); + } else if (reference is AST.SimpleTypeReference) { + string name = ((AST.SimpleTypeReference)reference).Name; + if (BooAmbience.ReverseTypeConversionTable.ContainsKey(name)) + return new GetClassReturnType(ProjectContentRegistry.Mscorlib, BooAmbience.ReverseTypeConversionTable[name], 0); + return new SearchClassReturnType(projectContent, callingClass, caretLine, caretColumn, + name, 0); + } else if (reference is AST.CallableTypeReference) { + return new AnonymousMethodReturnType(); + } else { + throw new NotSupportedException("unknown reference type: " + reference.ToString()); + } + } + IReturnType CreateReturnType(AST.TypeReference reference) + { + return CreateReturnType(reference, null); + } + IReturnType CreateReturnType(Type type) + { + return ReflectionReturnType.CreatePrimitive(type); + } + // TODO: Type inference + IReturnType CreateReturnType(AST.Field field) + { + return CreateReturnType(field.Type); + } + IReturnType CreateReturnType(AST.Method node, IMethod method) + { + return CreateReturnType(node.ReturnType, method); + } + IReturnType CreateReturnType(AST.Property property) + { + return CreateReturnType(property.Type); + } + + public override void OnCallableDefinition(AST.CallableDefinition node) + { + LoggingService.Debug("OnCallableDefinition: " + node.FullName); + DomRegion region = GetRegion(node); + DefaultClass c = new DefaultClass(_cu, ClassType.Delegate, GetModifier(node), region, OuterClass); + ConvertAttributes(node, c); + c.BaseTypes.Add(ReflectionReturnType.CreatePrimitive(typeof(Delegate))); + c.FullyQualifiedName = node.FullName; + if (_currentClass.Count > 0) { + OuterClass.InnerClasses.Add(c); + } else { + _cu.Classes.Add(c); + } + _currentClass.Push(c); // necessary for CreateReturnType + ConvertTemplates(node, c); + IReturnType returnType = CreateReturnType(node.ReturnType); + DefaultMethod invokeMethod = new DefaultMethod("Invoke", returnType, ModifierEnum.Public, DomRegion.Empty, DomRegion.Empty, c); + ConvertParameters(node.Parameters, invokeMethod); + c.Methods.Add(invokeMethod); + invokeMethod = new DefaultMethod("BeginInvoke", CreateReturnType(typeof(IAsyncResult)), ModifierEnum.Public, DomRegion.Empty, DomRegion.Empty, c); + ConvertParameters(node.Parameters, invokeMethod); + invokeMethod.Parameters.Add(new DefaultParameter("callback", CreateReturnType(typeof(AsyncCallback)), DomRegion.Empty)); + invokeMethod.Parameters.Add(new DefaultParameter("object", ReflectionReturnType.Object, DomRegion.Empty)); + c.Methods.Add(invokeMethod); + invokeMethod = new DefaultMethod("EndInvoke", returnType, ModifierEnum.Public, DomRegion.Empty, DomRegion.Empty, c); + invokeMethod.Parameters.Add(new DefaultParameter("result", CreateReturnType(typeof(IAsyncResult)), DomRegion.Empty)); + c.Methods.Add(invokeMethod); + _currentClass.Pop(); + } + + public override bool EnterClassDefinition(AST.ClassDefinition node) + { + EnterTypeDefinition(node, ClassType.Class); + return base.EnterClassDefinition(node); + } + + public override bool EnterInterfaceDefinition(AST.InterfaceDefinition node) + { + EnterTypeDefinition(node, ClassType.Interface); + return base.EnterInterfaceDefinition(node); + } + + public override bool EnterEnumDefinition(AST.EnumDefinition node) + { + EnterTypeDefinition(node, ClassType.Enum); + return base.EnterEnumDefinition(node); + } + + public override bool EnterModule(AST.Module node) + { + if (_firstModule) EnterTypeDefinition(node, ClassType.Class); + _firstModule = false; + return base.EnterModule(node); + } + + private void EnterTypeDefinition(AST.TypeDefinition node, ClassType classType) + { + LoggingService.Debug("Enter " + node.GetType().Name + " (" + node.FullName + ")"); + DomRegion region = GetClientRegion(node); + DefaultClass c = new DefaultClass(_cu, classType, GetModifier(node), region, OuterClass); + c.FullyQualifiedName = node.FullName; + if (_currentClass.Count > 0) + _currentClass.Peek().InnerClasses.Add(c); + else + _cu.Classes.Add(c); + _currentClass.Push(c); + ConvertAttributes(node, c); + ConvertTemplates(node, c); + if (node.BaseTypes != null) { + foreach (AST.TypeReference r in node.BaseTypes) { + c.BaseTypes.Add(CreateReturnType(r)); + } + } + } + + public override void LeaveClassDefinition(AST.ClassDefinition node) + { + LeaveTypeDefinition(node); + base.LeaveClassDefinition(node); + } + + public override void LeaveInterfaceDefinition(AST.InterfaceDefinition node) + { + LeaveTypeDefinition(node); + base.LeaveInterfaceDefinition(node); + } + + public override void LeaveEnumDefinition(AST.EnumDefinition node) + { + LeaveTypeDefinition(node); + base.LeaveEnumDefinition(node); + } + + public override void LeaveModule(AST.Module node) + { + if (_currentClass.Count != 0) LeaveTypeDefinition(node); + base.LeaveModule(node); + } + + private void LeaveTypeDefinition(AST.TypeDefinition node) + { + DefaultClass c = _currentClass.Pop(); + LoggingService.Debug("Leave "+node.GetType().Name+" "+node.FullName+" (Class = "+c.FullyQualifiedName+")"); + } + + public override void OnMethod(AST.Method node) + { + LoggingService.Debug("Method: " + node.FullName); + DefaultMethod method = new DefaultMethod(node.Name, null, GetModifier(node), GetRegion(node), GetClientRegion(node), OuterClass); + ConvertAttributes(node, method); + ConvertTemplates(node, method); + // return type must be assign AFTER ConvertTemplates + method.ReturnType = CreateReturnType(node, method); + ConvertParameters(node.Parameters, method); + _currentClass.Peek().Methods.Add(method); + } + + public override void OnConstructor(AST.Constructor node) + { + if (node.Body.Statements.Count == 0) return; + Constructor ctor = new Constructor(GetModifier(node), GetRegion(node), GetClientRegion(node), OuterClass); + ConvertAttributes(node, ctor); + ConvertParameters(node.Parameters, ctor); + _currentClass.Peek().Methods.Add(ctor); + } + + public override void OnEnumMember(AST.EnumMember node) + { + DefaultField field = new DefaultField(OuterClass.DefaultReturnType, node.Name, ModifierEnum.Const | ModifierEnum.Public, GetRegion(node), OuterClass); + ConvertAttributes(node, field); + OuterClass.Fields.Add(field); + } + + public override void OnField(AST.Field node) + { + DefaultField field = new DefaultField(CreateReturnType(node), node.Name, GetModifier(node), GetRegion(node), OuterClass); + ConvertAttributes(node, field); + OuterClass.Fields.Add(field); + } + + public override void OnEvent(AST.Event node) + { + DomRegion region = GetRegion(node); + DefaultEvent e = new DefaultEvent(node.Name, CreateReturnType(node.Type), GetModifier(node), region, region, OuterClass); + ConvertAttributes(node, e); + OuterClass.Events.Add(e); + } + + public override void OnProperty(AST.Property node) + { + DefaultProperty property = new DefaultProperty(node.Name, CreateReturnType(node), GetModifier(node), GetRegion(node), GetClientRegion(node), OuterClass); + ConvertAttributes(node, property); + ConvertParameters(node.Parameters, property); + OuterClass.Properties.Add(property); + } + } +} diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ExpressionFinder.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ExpressionFinder.cs new file mode 100644 index 0000000000..ae6f58843a --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ExpressionFinder.cs @@ -0,0 +1,359 @@ +// +// 2002-2005 AlphaSierraPapa +// GNU General Public License +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using System.Text; +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Dom; + +namespace Grunwald.BooBinding.CodeCompletion +{ + public class ExpressionFinder : IExpressionFinder + { + string fileName; + + public ExpressionFinder(string fileName) + { + this.fileName = fileName; + } + + #region RemoveLastPart + /// + /// Removes the last part of the expression. + /// + /// + /// "arr[i]" => "arr" + /// "obj.Field" => "obj" + /// "obj.Method(args,...)" => "obj.Method" + /// + public string RemoveLastPart(string expression) + { + throw new NotImplementedException(); + } + #endregion + + #region Find Expression + // The expression finder can find an expression in a text + // inText is the full source code, offset the cursor position + + // example: "_var = 'bla'\n_var^\nprint _var" + // where ^ is the cursor position + // in that simple case the expression finder should return 'n_var'. + + // but also complex expressions like + // 'filename.Substring(filename.IndexOf("var="))' + // should be returned if the cursor is after the last ). + + // implementation note: the text after offset is irrelevant, so + // every operation on the string aborts after reaching offset + + const string _closingBrackets = "}])"; + const string _openingBrackets = "{[("; + + public ExpressionResult FindExpression(string inText, int offset) + { + if (inText == null) return new ExpressionResult(null); + // OK, first try a kind of "quick find" + int i = offset + 1; + const string forbidden = "\"\'/#)]}"; + const string finish = "([{=+*<,:"; + int start = -1; + while (i > 0) { + i -= 1; + char c = inText[i]; + if (finish.IndexOf(c) >= 0) { + start = i + 1; + break; + } + if (forbidden.IndexOf(c) >= 0) { + LoggingService.Debug("Quickfind failed: got " + c); + break; + } + if (char.IsWhiteSpace(c)) { + if (i > 6 && inText.Substring(i - 6, 6) == "import") { + i -= 7; // include 'import' in the expression + } + start = i + 1; + break; + } + if (start >= 0) { + if (CheckString(inText, start, "/#\"\'", "\r\n")) { + return GetExpression(inText, start, offset + 1); + } + } + } + + inText = SimplifyCode(inText, offset); + if (inText == null) { + LoggingService.Debug("SimplifyCode returned null (cursor is in comment/string???)"); + return new ExpressionResult(null); + } + // inText now has no comments or string literals, but the same meaning in + // terms of the type system + // Now go back until a finish-character or a whitespace character + Stack bracketStack = new Stack(); + i = inText.Length; + while (i > 0) { + i -= 1; + char c = inText[i]; + if (bracketStack.Count == 0 && (finish.IndexOf(c) >= 0 || Char.IsWhiteSpace(c))) { + return GetExpression(inText, i + 1, inText.Length); + } + int bracket = _closingBrackets.IndexOf(c); + if (bracket >= 0) { + bracketStack.Push(bracket); + } + bracket = _openingBrackets.IndexOf(c); + if (bracket >= 0) { + while (bracketStack.Count > 0 && bracketStack.Pop() > bracket); + } + } + return new ExpressionResult(null); + } + + bool CheckString(string text, int offset, string forbidden, string finish) + { + int i = offset; + while (i > 0) { + i -= 1; + char c = text[i]; + if (forbidden.IndexOf(c) >= 0) return false; + if (finish.IndexOf(c) >= 0) return true; + } + return true; + } + + ExpressionResult GetExpression(string inText, int start, int end) + { + if (start == end) return new ExpressionResult(null); + StringBuilder b = new StringBuilder(); + bool wasSpace = true; + int i = start; + while (i < end) { + char c = inText[i]; + if (Char.IsWhiteSpace(c)) { + if (!wasSpace) b.Append(' '); + wasSpace = true; + } else { + wasSpace = false; + b.Append(c); + } + i += 1; + } + return new ExpressionResult(b.ToString()); + } + // TODO: We could need some unit tests for this. + #endregion + + #region Find Full Expression + public ExpressionResult FindFullExpression(string inText, int offset) + { + ExpressionResult result = FindExpression(inText, offset); + if (result.Expression == null) + return result; + StringBuilder b = new StringBuilder(result.Expression); + ResetStateMachine(); + int state = -1; + // state = -1 : accepting current identifier + // state >= 0 : accepting brackets/parenthesis + Stack bracketStack = new Stack(); + for (int i = offset + 1; i < inText.Length; i++) { + char c = inText[i]; + if (state == -1) { + if (char.IsLetterOrDigit(c) || c == '_') { + // continue reading identifier + } else { + state = 0; + } + } + if (state >= 0) { + state = FeedStateMachine(state, c); + if (IsInNormalCode(state)) { + int bracket = _openingBrackets.IndexOf(c); + if (bracket >= 0) { + bracketStack.Push(bracket); + } else { + if (bracketStack.Count == 0) { + result.Expression = b.ToString(); + return result; + } + } + bracket = _closingBrackets.IndexOf(c); + if (bracket >= 0) { + while (bracketStack.Count > 0 && bracketStack.Pop() > bracket); + } + } + } + b.Append(c); + } + return new ExpressionResult(null); + } + #endregion + + #region State Machine / SimplifyCode + static readonly int[] inputTable; + + static ExpressionFinder() + { + inputTable = new int[128]; + for (int i = 0; i < inputTable.Length; i++) { + inputTable[i] = _elseIndex; + } + inputTable[ 34] = 0; // " + inputTable[ 39] = 1; // ' + inputTable[ 92] = 2; // \ + inputTable[ 10] = 3; // \n + inputTable[ 13] = 3; // \r + inputTable[ 36] = 4; // $ + inputTable[123] = 5; // { + inputTable[125] = 6; // } + inputTable[ 35] = 7; // # + inputTable[ 47] = 8; // / + inputTable[ 42] = 9; // * + } + + const int _elseIndex = 10; + + static readonly + int[][] _stateTable = { // " ' \ \n $ { } # / * else + /* 0: in Code */ new int[] { 1 , 7 , 0 , 0 , 0 , 0 , 0 , 13 , 12 , 0 , 0 }, + /* 1: after " */ new int[] { 2 , 6 , 10 , 0 , 8 , 6 , 6 , 6 , 6 , 6 , 6 }, + /* 2: after "" */ new int[] { 3 , 7 , 0 , 0 , 0 , 0 , 0 , 13 , 12 , 0 , 0 }, + /* 3: in """ */ new int[] { 4 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 }, + /* 4: in """, " */ new int[] { 5 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 }, + /* 5: in """, "" */ new int[] { 0 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 }, + /* 6: in "-string */ new int[] { 0 , 6 , 10 , 0 , 8 , 6 , 6 , 6 , 6 , 6 , 6 }, + /* 7: in '-string */ new int[] { 7 , 0 , 11 , 0 , 7 , 7 , 7 , 7 , 7 , 7 , 7 }, + /* 8: after $ in " */ new int[] { 0 , 6 , 10 , 0 , 8 , 9 , 6 , 6 , 6 , 6 , 6 }, + /* 9: in "{ */ new int[] { 9 , 9 , 9 , 9 , 9 , 9 , 6 , 9 , 9 , 9 , 9 }, + /* 10: after \ in " */ new int[] { 6 , 6 , 6 , 0 , 6 , 6 , 6 , 6 , 6 , 6 , 6 }, + /* 11: after \ in ' */ new int[] { 7 , 7 , 7 , 0 , 7 , 7 , 7 , 7 , 7 , 7 , 7 }, + /* 12: after / */ new int[] { 1 , 7 , 0 , 0 , 0 , 0 , 0 , 0 , 13 ,-14 , 0 }, + /* 13: line comment */ new int[] { 13 , 13 , 13 , 0 , 13 , 13 , 13 , 13 , 13 , 13 , 13 }, + /* 14: block comment*/ new int[] { 14 , 14 , 14 , 14 , 14 , 14 , 14 , 14 , 14 , 15 , 14 }, + /* 15: after * in bc*/ new int[] { 14 , 14 , 14 , 14 , 14 , 14 , 14 , 14 ,-15 , 15 , 14 } + }; + + static bool IsInNormalCode(int state) + { + return state == 0 || state == 2 || state == 12; + } + + int commentblocks; + + void ResetStateMachine() + { + commentblocks = 0; + } + + int FeedStateMachine(int oldState, char c) + { + int charNum = (int)c; + int input; + if (charNum < inputTable.Length) { + input = inputTable[charNum]; + } else { + input = _elseIndex; + } + int action = _stateTable[oldState][input]; + if (action == -14) { + // enter block comment + commentblocks += 1; + return 14; + } else if (action == -15) { + // leave block comment + commentblocks -= 1; + if (commentblocks == 0) + return 0; + else + return 14; + } + return action; + } + + /// This method makes boo source code "simpler" by removing all comments + /// and replacing all string litarals through string.Empty. + /// Regular expressions literals are replaced with the simple regex /a/ + public string SimplifyCode(string inText, int offset) + { + StringBuilder result = new StringBuilder(); + StringBuilder inStringResult = new StringBuilder(" "); + int state = 0; + ResetStateMachine(); + int i = -1; + while (i < offset) { + i += 1; + char c = inText[i]; + int action = FeedStateMachine(state, c); + if (action == 9) { + // enter inner string expression (${...}) + if (state == 9) + inStringResult.Append(c); + else + inStringResult.Length = 1; + state = action; + } else if (action == 0 || action == 12) { + // go to normal code + if (action == 12) { + // after / could be a regular expression, do a special check for that + int regexEnd = SkipRegularExpression(inText, i, offset); + if (regexEnd > 0) { + i = regexEnd; + result.Append("/a"); + } else if (regexEnd == -1) { + // cursor is in regex + return null; + } + } + if (state == 2 || (state >= 6 && state <= 11)) + result.Append("string.Empty"); + if (IsInNormalCode(state)) + result.Append(c); + state = action; + } else { + state = action; + } + } + if (IsInNormalCode(state)) { + // cursor is in normal code + return result.ToString(); + } else if (state == 9) { + // cursor is in inner string expression (${...}) + return inStringResult.ToString(); + } else { + // cursor is in comment/string + return null; + } + } + + /// Skips the regular expression in inText at position pos. Returns end position of the ending / if + /// successful or 0 is no regular expression was found at the location. + /// Return -1 if maxOffset is inside the regular expression. + int SkipRegularExpression(string inText, int pos, int maxOffset) + { + bool containsWhitespace; + if (pos > 0) { + containsWhitespace = (inText[pos - 1] == '@'); + } else { + containsWhitespace = false; + } + if (pos == maxOffset) return -1; // cursor is after / -> cursor inside regex + if (inText[pos + 1] == '/') return 0; // double // is comment, no regex + int i = pos; + while (i < maxOffset) { + i += 1; + if (!containsWhitespace && Char.IsWhiteSpace(inText, i)) + return 0; // this is no regex + if (inText[i] == '/') + return i; + } + return -1; // maxOffset inside regex + } + #endregion + } +} diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ResolveVisitor.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ResolveVisitor.cs new file mode 100644 index 0000000000..507dc29cc0 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ResolveVisitor.cs @@ -0,0 +1,484 @@ +// +// 2002-2005 AlphaSierraPapa +// GNU General Public License +// +// $Revision$ +// + +using System; +using System.Collections; +using System.Collections.Generic; +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Dom; +using Boo.Lang.Compiler.Ast; + +namespace Grunwald.BooBinding.CodeCompletion +{ + public class ResolveVisitor : DepthFirstVisitor + { + #region Field + Constructor + BooResolver resolver; + ResolveResult resolveResult; + IClass callingClass; + IProjectContent projectContent; + ICompilationUnit cu; + + public ResolveVisitor(BooResolver resolver) + { + this.resolver = resolver; + this.callingClass = resolver.CallingClass; + this.projectContent = resolver.ProjectContent; + this.cu = resolver.CompilationUnit; + } + + public ResolveResult ResolveResult { + get { + return resolveResult; + } + } + #endregion + + #region Make Result + void MakeResult(IReturnType type) + { + if (type == null) + resolveResult = null; + else + resolveResult = new ResolveResult(callingClass, resolver.CallingMember, type); + } + + void MakeLiteralResult(string fullTypeName) + { + resolveResult = new ResolveResult(callingClass, resolver.CallingMember, + new GetClassReturnType(projectContent, fullTypeName, 0)); + } + + void MakeResult(IMember member) + { + IField field = member as IField; + if (field != null && (field.IsLocalVariable || field.IsParameter)) { + resolveResult = new LocalResolveResult(resolver.CallingMember, field); + } else if (member != null) { + resolveResult = new MemberResolveResult(callingClass, resolver.CallingMember, member); + } else { + resolveResult = null; + } + } + + void MakeTypeResult(IClass c) + { + resolveResult = new TypeResolveResult(callingClass, resolver.CallingMember, c); + } + + void MakeTypeResult(IReturnType rt) + { + resolveResult = new TypeResolveResult(callingClass, resolver.CallingMember, rt); + } + + void MakeMethodResult(IReturnType type, string methodName) + { + resolveResult = new MethodResolveResult(callingClass, resolver.CallingMember, type, methodName); + } + + void MakeNamespaceResult(string namespaceName) + { + resolveResult = new NamespaceResolveResult(callingClass, resolver.CallingMember, namespaceName); + } + + static bool IsSameName(string name1, string name2) + { + // boo is currently always case sensitive + return name1 == name2; + } + #endregion + + #region Resolve Identifier + public override void OnReferenceExpression(ReferenceExpression node) + { + string identifier = node.Name; + bool wasResolved = ResolveIdentifier(identifier); + if (wasResolved && resolveResult is TypeResolveResult) { + return; + } + // was not resolved or was resolved as local, member etc. + ResolveResult oldResult = resolveResult; + resolveResult = null; + // Try to resolve as type: + IReturnType t = projectContent.SearchType(identifier, 0, callingClass, cu, resolver.CaretLine, resolver.CaretColumn); + if (t != null) { + MakeTypeResult(t); + } else { + if (callingClass != null) { + if (resolver.CallingMember is IMethod) { + foreach (ITypeParameter typeParameter in (resolver.CallingMember as IMethod).TypeParameters) { + if (IsSameName(identifier, typeParameter.Name)) { + MakeTypeResult(new GenericReturnType(typeParameter)); + return; + } + } + } + foreach (ITypeParameter typeParameter in callingClass.TypeParameters) { + if (IsSameName(identifier, typeParameter.Name)) { + MakeTypeResult(new GenericReturnType(typeParameter)); + return; + } + } + } + } + if (!wasResolved) + return; // return type result, if existant + if (resolveResult == null) { + resolveResult = oldResult; + } else { + // TODO: return type or mixed dependant on context! + resolveResult = new MixedResolveResult(oldResult, resolveResult); + } + } + + bool ResolveIdentifier(string identifier) + { + resolveResult = null; + if (resolver.CallingMember != null) { + // TODO: Search local variables + + IMethodOrProperty method = resolver.CallingMember as IMethodOrProperty; + if (method != null) { + foreach (IParameter p in method.Parameters) { + if (IsSameName(p.Name, identifier)) { + MakeResult(new DefaultField.ParameterField(p.ReturnType, p.Name, p.Region, callingClass)); + return true; + } + } + if (method is IProperty && IsSameName(identifier, "value")) { + if (((IProperty)method).SetterRegion.IsInside(resolver.CaretLine, resolver.CaretColumn)) { + MakeResult(new DefaultField.ParameterField(method.ReturnType, "value", method.Region, callingClass)); + return true; + } + } + } + } + if (callingClass == null) + return false; + if (ResolveMember(callingClass.DefaultReturnType, identifier)) + return true; + + string namespaceName = projectContent.SearchNamespace(identifier, callingClass, cu, resolver.CaretLine, resolver.CaretColumn); + if (namespaceName != null && namespaceName.Length > 0) { + MakeNamespaceResult(namespaceName); + return true; + } + + // Boo can import classes: + foreach (IUsing @using in cu.Usings) { + foreach (string import in @using.Usings) { + IClass c = projectContent.GetClass(import); + if (c != null) { + if (ResolveMember(c.DefaultReturnType, identifier)) + return true; + } + } + } + // Boo can import modules: + foreach (object o in resolver.GetImportedNamespaceContents()) { + IClass c = o as IClass; + if (c != null && IsSameName(identifier, c.Name)) { + MakeTypeResult(c); + return true; + } + IMember member = o as IMember; + if (member != null && IsSameName(identifier, member.Name)) { + if (member is IMethod) { + MakeMethodResult(member.DeclaringType.DefaultReturnType, member.Name); + } else { + MakeResult(member); + } + return true; + } + } + return false; + } + #endregion + + #region Resolve Member + public override void OnMemberReferenceExpression(MemberReferenceExpression node) + { + resolveResult = null; + node.Target.Accept(this); + if (resolveResult is NamespaceResolveResult) { + string namespaceName = (resolveResult as NamespaceResolveResult).Name; + string combinedName; + if (namespaceName.Length == 0) + combinedName = node.Name; + else + combinedName = namespaceName + "." + node.Name; + if (projectContent.NamespaceExists(combinedName)) { + MakeNamespaceResult(combinedName); + return; + } + IClass c = projectContent.GetClass(combinedName); + if (c != null) { + MakeTypeResult(c); + return; + } + // go through the members of the modules in that namespace + foreach (object o in projectContent.GetNamespaceContents(namespaceName)) { + IMember member = o as IMember; + if (member != null && IsSameName(member.Name, node.Name)) { + if (member is IMethod) { + MakeMethodResult(member.DeclaringType.DefaultReturnType, member.Name); + } else { + MakeResult(member); + } + break; + } + } + } else { + if (resolveResult != null) { + ResolveMember(resolveResult.ResolvedType, node.Name); + } + } + } + + bool ResolveMember(IReturnType type, string memberName) + { + if (type == null) + return false; + bool isClassInInheritanceTree = false; + if (callingClass != null) + isClassInInheritanceTree = callingClass.IsTypeInInheritanceTree(type.GetUnderlyingClass()); + foreach (IProperty p in type.GetProperties()) { + if (IsSameName(p.Name, memberName)) { + MakeResult(p); + return true; + } + } + foreach (IField f in type.GetFields()) { + if (IsSameName(f.Name, memberName)) { + MakeResult(f); + return true; + } + } + foreach (IEvent e in type.GetEvents()) { + if (IsSameName(e.Name, memberName)) { + MakeResult(e); + return true; + } + } + foreach (IMethod m in type.GetMethods()) { + if (IsSameName(m.Name, memberName)) { + MakeMethodResult(type, memberName); + return true; + } + } + return false; + } + #endregion + + #region Resolve Method Invocation + public override void OnMethodInvocationExpression(MethodInvocationExpression node) + { + resolveResult = null; + node.Target.Accept(this); + if (resolveResult == null) + return; + if (resolveResult is MethodResolveResult) { + // normal method call + string methodName = ((MethodResolveResult)resolveResult).Name; + IReturnType containingType = ((MethodResolveResult)resolveResult).ContainingType; + + List methods = new List(); + bool isClassInInheritanceTree = false; + if (callingClass != null) + isClassInInheritanceTree = callingClass.IsTypeInInheritanceTree(containingType.GetUnderlyingClass()); + + foreach (IMethod m in containingType.GetMethods()) { + if (IsSameName(m.Name, methodName) + && m.IsAccessible(callingClass, isClassInInheritanceTree) + ) { + methods.Add(m); + } + } + ResolveInvocation(methods, node.Arguments); + } else if (resolveResult is TypeResolveResult || resolveResult is MixedResolveResult) { + TypeResolveResult trr = resolveResult as TypeResolveResult; + if (trr == null) + trr = (resolveResult as MixedResolveResult).TypeResult; + if (trr != null && trr.ResolvedClass != null) { + List methods = new List(); + bool isClassInInheritanceTree = false; + if (callingClass != null) + isClassInInheritanceTree = callingClass.IsTypeInInheritanceTree(trr.ResolvedClass); + + foreach (IMethod m in trr.ResolvedClass.Methods) { + if (m.IsConstructor && !m.IsStatic + && m.IsAccessible(callingClass, isClassInInheritanceTree)) + { + methods.Add(m); + } + } + ResolveInvocation(methods, node.Arguments); + } else { + resolveResult = null; + } + } else if (resolveResult.ResolvedType != null) { + // maybe event or callable call or call on System.Type -> constructor by reflection + IClass c = resolveResult.ResolvedType.GetUnderlyingClass(); + if (c != null) { + if (c.ClassType == ClassType.Delegate) { + // find the delegate's invoke method + IMethod invoke = c.Methods.Find(delegate(IMethod innerMethod) { return innerMethod.Name == "Invoke"; }); + if (invoke != null) { + resolveResult.ResolvedType = invoke.ReturnType; + } + } else if (c.FullyQualifiedName == "System.Type") { + resolveResult.ResolvedType = ReflectionReturnType.Object; + } else { + resolveResult = null; + } + } else { + resolveResult = null; + } + } else { + resolveResult = null; + } + } + + void ResolveInvocation(List methods, ExpressionCollection arguments) + { + resolveResult = null; + if (methods.Count == 0) { + return; + } + // MemberLookupHelper does type argument inference and type substitution for us + IReturnType[] types = new IReturnType[arguments.Count]; + for (int i = 0; i < types.Length; ++i) { + arguments[i].Accept(this); + types[i] = (resolveResult != null) ? resolveResult.ResolvedType : null; + resolveResult = null; + } + MakeResult(MemberLookupHelper.FindOverload(methods, new IReturnType[0], types)); + } + #endregion + + #region Resolve Slice Expression + public override void OnSlicingExpression(SlicingExpression node) + { + resolveResult = null; + } + #endregion + + protected override void OnError(Node node, Exception error) + { + MessageService.ShowError(error, "ResolveVisitor: error processing " + node); + } + + public override void OnCallableBlockExpression(CallableBlockExpression node) + { + MakeResult(new AnonymousMethodReturnType()); + } + + public override void OnCallableTypeReference(CallableTypeReference node) + { + MakeTypeResult(ConvertType(node)); + } + + public override void OnRELiteralExpression(RELiteralExpression node) + { + MakeLiteralResult("System.Text.RegularExpressions.Regex"); + } + + public override void OnCharLiteralExpression(CharLiteralExpression node) + { + MakeLiteralResult("System.Char"); + } + + public override void OnArrayLiteralExpression(ArrayLiteralExpression node) + { + // TODO: get real array type + MakeLiteralResult("System.Array"); + } + + public override void OnAsExpression(AsExpression node) + { + MakeResult(ConvertType(node.Type)); + } + + public override void OnCastExpression(CastExpression node) + { + MakeResult(ConvertType(node.Type)); + } + + public override void OnBoolLiteralExpression(BoolLiteralExpression node) + { + MakeResult(ReflectionReturnType.Bool); + } + + public override void OnDoubleLiteralExpression(DoubleLiteralExpression node) + { + if (node.IsSingle) + MakeLiteralResult("System.Single"); + else + MakeLiteralResult("System.Double"); + } + + public override void OnListLiteralExpression(ListLiteralExpression node) + { + MakeLiteralResult("Boo.Lang.List"); + } + + public override void OnHashLiteralExpression(HashLiteralExpression node) + { + MakeLiteralResult("Boo.Lang.Hash"); + } + + public override void OnIntegerLiteralExpression(IntegerLiteralExpression node) + { + if (node.IsLong) + MakeLiteralResult("System.Int64"); + else + MakeResult(ReflectionReturnType.Int); + } + + public override void OnNullLiteralExpression(NullLiteralExpression node) + { + MakeResult(NullReturnType.Instance); + } + + public override void OnSelfLiteralExpression(SelfLiteralExpression node) + { + MakeResult(callingClass.DefaultReturnType); + } + + public override void OnSuperLiteralExpression(SuperLiteralExpression node) + { + MakeResult(callingClass.BaseType); + } + + public override void OnSimpleTypeReference(SimpleTypeReference node) + { + MakeTypeResult(ConvertType(node)); + } + + public override void OnStringLiteralExpression(StringLiteralExpression node) + { + MakeResult(ReflectionReturnType.String); + } + + public override void OnTimeSpanLiteralExpression(TimeSpanLiteralExpression node) + { + MakeLiteralResult("System.TimeSpan"); + } + + public override void OnTypeofExpression(TypeofExpression node) + { + MakeLiteralResult("System.Type"); + } + + IReturnType ConvertType(TypeReference typeRef) + { + return ConvertVisitor.CreateReturnType(typeRef, callingClass, resolver.CallingMember, + resolver.CaretLine, resolver.CaretColumn, + projectContent, false); + } + } +} diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Templates/ConsoleProject.xpt b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Templates/ConsoleProject.xpt new file mode 100644 index 0000000000..317a100834 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Templates/ConsoleProject.xpt @@ -0,0 +1,38 @@ + + diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Templates/FormsProject.xpt b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Templates/FormsProject.xpt new file mode 100644 index 0000000000..da0c8403ad --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Templates/FormsProject.xpt @@ -0,0 +1,96 @@ + + diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Templates/Library.xpt b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Templates/Library.xpt new file mode 100644 index 0000000000..3634404633 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Templates/Library.xpt @@ -0,0 +1,73 @@ + + diff --git a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/AssemblyInfo.cs b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/AssemblyInfo.cs new file mode 100644 index 0000000000..9792e3e822 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/AssemblyInfo.cs @@ -0,0 +1,50 @@ +#region license +// Copyright (c) 2005, Daniel Grunwald (daniel@danielgrunwald.de) +// All rights reserved. +// +// NRefactoryToBoo is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// NRefactoryToBoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with NRefactoryToBoo; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#endregion + +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following +// attributes. +// +// change them to the information which is associated with the assembly +// you compile. + +[assembly: AssemblyTitle("NRefactoryToBooConverter")] +[assembly: AssemblyDescription("Converts from NRefactory AST (C#, VB) to Boo AST")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Daniel Grunwald")] +[assembly: AssemblyProduct("BooBinding")] +[assembly: AssemblyCopyright("(C) 2005, Daniel Grunwald")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// You can specify all values by your own or you can build default build and revision +// numbers with the '*' character (the default): +[assembly: AssemblyVersion(NRefactoryToBooConverter.VersionInfo.VersionNumber)] + +namespace NRefactoryToBooConverter { + public static class VersionInfo { + public const string VersionNumber = "0.1.*"; + } +} diff --git a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/BooPrinterVisitorWithComments.cs b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/BooPrinterVisitorWithComments.cs new file mode 100644 index 0000000000..5153eb94bf --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/BooPrinterVisitorWithComments.cs @@ -0,0 +1,202 @@ +#region license +// Copyright (c) 2005, Daniel Grunwald (daniel@danielgrunwald.de) +// All rights reserved. +// +// NRefactoryToBoo is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// NRefactoryToBoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with NRefactoryToBoo; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#endregion + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using Boo.Lang.Compiler; +using Boo.Lang.Compiler.Ast; +using Boo.Lang.Compiler.Ast.Visitors; +using ICSharpCode.NRefactory.Parser; + +namespace NRefactoryToBooConverter +{ + public class BooPrinterVisitorWithComments : BooPrinterVisitor, ISpecialVisitor + { + IEnumerator enumerator; + bool available; // true when more specials are available + + public BooPrinterVisitorWithComments(IEnumerable specials, TextWriter writer) + : base(writer) + { + if (specials == null) throw new ArgumentNullException("specials"); + enumerator = specials.GetEnumerator(); + available = enumerator.MoveNext(); + } + + void AcceptPoint(LexicalInfo lex) + { + if (lex != null && lex.IsValid) { + AcceptPoint(lex.Line, lex.Column); + } + } + + void AcceptPoint(SourceLocation loc) + { + if (loc != null && loc.IsValid) { + AcceptPoint(loc.Line, loc.Column); + } + } + + /// + /// Writes all specials up to the specified location. + /// + void AcceptPoint(int line, int column) + { + while (available) { + Point b = enumerator.Current.StartPosition; + if (b.Y < line || (b.Y == line && b.X <= column)) { + WriteCurrent(); + } else { + break; + } + } + } + + void WriteCurrent() + { + enumerator.Current.AcceptVisitor(this, null); + available = enumerator.MoveNext(); + } + + /// + /// Outputs all missing specials to the writer. + /// + public void Finish() + { + while (available) { + WriteCurrent(); + } + } + + Node currentDocuNode; + bool isInEndMode = false; + + public override bool Visit(Node node) + { + if (node == null) return base.Visit(node); + currentDocuNode = node; + AcceptPoint(node.LexicalInfo); + currentDocuNode = null; + bool result = base.Visit(node); + isInEndMode = true; + AcceptPoint(node.EndSourceLocation); + isInEndMode = false; + oldIndentation = _indent; + return result; + } + + #region ICSharpCode.NRefactory.Parser.ISpecialVisitor interface implementation + int oldIndentation; + + struct DelayedSpecial { + public readonly int Indentation; + public readonly string Format; + public readonly object[] Args; + public DelayedSpecial(int indentation, string Format, object[] Args) { + this.Indentation = indentation; + this.Format = Format; + this.Args = Args; + } + } + + List delayedSpecials = new List(); + + bool writingDelayedSpecials; + + public override void WriteLine() + { + if (_disableNewLine == 0) { + base.WriteLine(); + if (!writingDelayedSpecials) { + writingDelayedSpecials = true; + int tmp = _indent; + foreach (DelayedSpecial special in delayedSpecials) { + _indent = special.Indentation; + WriteLine(special.Format, special.Args); + } + delayedSpecials.Clear(); + writingDelayedSpecials = false; + _indent = tmp; + } + oldIndentation = _indent; + } + } + + void WriteSpecialText(bool writeInline, string format, params object[] args) + { + // write comment in it's own line + if (_needsIndenting || writeInline) { + int tmp = _indent; + if (isInEndMode) { + _indent = oldIndentation; + } + if (writeInline && !_needsIndenting) { + WriteIndented(format, args); + } else { + WriteLine(format, args); + } + if (isInEndMode) { + _indent = tmp; + } + } else { + // comment is in the middle of line + // put it after the next line + delayedSpecials.Add(new DelayedSpecial(isInEndMode ? oldIndentation : _indent, format, args)); + } + } + + object ISpecialVisitor.Visit(ISpecial special, object data) + { + throw new NotImplementedException(); + } + + object ISpecialVisitor.Visit(BlankLine special, object data) + { + WriteSpecialText(false, ""); + return null; + } + + object ISpecialVisitor.Visit(Comment special, object data) + { + switch (special.CommentType) { + case CommentType.Documentation: + if (currentDocuNode == null) + goto default; + currentDocuNode.Documentation += special.CommentText; + break; + case CommentType.Block: + WriteSpecialText(true, "/*{0}*/", special.CommentText); + break; + default: + WriteSpecialText(false, "//{0}", special.CommentText); + break; + } + return null; + } + + object ISpecialVisitor.Visit(PreProcessingDirective special, object data) + { + WriteSpecialText(false, "{0} {1}", special.Cmd, special.Arg); + return null; + } + #endregion + } +} diff --git a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ConvertVisitor.cs b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ConvertVisitor.cs new file mode 100644 index 0000000000..198bb578e5 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ConvertVisitor.cs @@ -0,0 +1,283 @@ +#region license +// Copyright (c) 2005, Daniel Grunwald (daniel@danielgrunwald.de) +// All rights reserved. +// +// NRefactoryToBoo is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// NRefactoryToBoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with NRefactoryToBoo; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#endregion + +using System; +using System.Collections.Generic; +using System.Drawing; +using ICSharpCode.NRefactory.Parser; +using ICSharpCode.NRefactory.Parser.AST; +using Boo.Lang.Compiler; +using B = Boo.Lang.Compiler.Ast; + +namespace NRefactoryToBooConverter +{ + public partial class ConvertVisitor : IASTVisitor + { + string fileName; + CompilerErrorCollection errors; + CompilerWarningCollection warnings; + StringComparer nameComparer; + ConverterSettings settings; + + B.Module module; + + public ConvertVisitor(ConverterSettings settings) + { + this.settings = settings; + this.fileName = settings.FileName; + this.errors = settings.Errors; + this.warnings = settings.Warnings; + this.nameComparer = settings.NameComparer; + } + + int generatedNameNumber; + + string GenerateName() + { + return settings.NameGenerationPrefix + (++generatedNameNumber).ToString(System.Globalization.NumberFormatInfo.InvariantInfo); + } + + B.LexicalInfo lastLexicalInfo; + + B.LexicalInfo GetLexicalInfo(INode node) + { + if (node == null) + return new B.LexicalInfo(fileName); + Point point = node.StartLocation; + if (!point.IsEmpty) { + lastLexicalInfo = new B.LexicalInfo(fileName, point.Y, point.X); + } + if (lastLexicalInfo == null) { + lastLexicalInfo = new B.LexicalInfo(fileName); + } + return lastLexicalInfo; + } + + void AddError(B.LexicalInfo lex, string errorMessage) + { + errors.Add(new CompilerError(lex, errorMessage)); + } + + void AddError(INode node, string errorMessage) + { + AddError(GetLexicalInfo(node), errorMessage); + } + + void AddWarning(B.LexicalInfo lex, string warningMessage) + { + warnings.Add(new CompilerWarning(warningMessage)); + } + + void AddWarning(INode node, string warningMessage) + { + AddWarning(GetLexicalInfo(node), warningMessage); + } + + B.SourceLocation GetEndLocation(INode node) + { + return GetLocation(node.EndLocation); + } + + B.SourceLocation GetLocation(Point point) + { + return new B.SourceLocation(point.Y, point.X); + } + + B.TypeMemberModifiers ConvertModifier(AttributedNode node, B.TypeMemberModifiers defaultVisibility) + { + Modifier m = node.Modifier; + B.TypeMemberModifiers r = B.TypeMemberModifiers.None; + if ((m & Modifier.Private) != 0) + r |= B.TypeMemberModifiers.Private; + if ((m & Modifier.Internal) != 0) + r |= B.TypeMemberModifiers.Internal; + if ((m & Modifier.Public) != 0) + r |= B.TypeMemberModifiers.Public; + if ((m & Modifier.Protected) != 0) + r |= B.TypeMemberModifiers.Protected; + if (r == B.TypeMemberModifiers.None) + r = defaultVisibility; + + if ((m & Modifier.Abstract) != 0) + r |= B.TypeMemberModifiers.Abstract; + if ((m & Modifier.Virtual) != 0) + r |= B.TypeMemberModifiers.Virtual; + if ((m & Modifier.Sealed) != 0) + r |= B.TypeMemberModifiers.Final; + if ((m & Modifier.Static) != 0) { + r |= B.TypeMemberModifiers.Static; + } else if (currentType != null && currentType.IsStatic) { + if (!(node is TypeDeclaration)) + r |= B.TypeMemberModifiers.Static; + } else { + if ((m & (Modifier.Abstract | Modifier.Virtual | Modifier.Override)) == 0) { + if (node is MethodDeclaration || node is PropertyDeclaration) + r |= B.TypeMemberModifiers.Final; + } + } + if ((m & Modifier.Override) != 0) + r |= B.TypeMemberModifiers.Override; + if ((m & Modifier.Readonly) != 0 && !(node is PropertyDeclaration)) { + // allow readonly on VB properties only + AddWarning(node, "readonly modifier is ignored"); + } + if ((m & Modifier.Const) != 0) + r |= B.TypeMemberModifiers.Final; + if ((m & Modifier.New) != 0) { + AddError(node, "shadowing is not supported"); + } + if ((m & Modifier.Partial) != 0) { + AddError(node, "Partial types are not supported"); + } + if ((m & Modifier.Extern) != 0) { + AddError(node, "Extern modifier is not supported"); + } + if ((m & Modifier.Volatile) != 0) { + AddError(node, "Volatile modifier is not supported"); + } + if ((m & Modifier.Unsafe) != 0) { + AddError(node, "Unsafe modifier is not supported"); + } + if ((m & Modifier.Overloads) != 0) { + // not necessary in Boo + } + if ((m & Modifier.WithEvents) != 0) { + // not necessary in Boo + } + if ((m & Modifier.Default) != 0) { + ParametrizedNode parametrizedNode = node as ParametrizedNode; + string name = null; + if (node is IndexerDeclaration) { + name = DefaultIndexerName; + } else if (parametrizedNode != null) { + name = parametrizedNode.Name; + } else { + AddError(node, "Default modifier is not supported on this member."); + } + if (name != null) { + currentType.Attributes.Add(MakeAttribute("System.Reflection.DefaultMember", new B.StringLiteralExpression(name))); + } + } + if ((m & Modifier.Narrowing) != 0) { + AddError(node, "Narrowing modifier is not supported"); + } + if ((m & Modifier.Widening) != 0) { + AddError(node, "Widening modifier is not supported"); + } + return r; + } + + B.Attribute MakeAttribute(string name, params B.Expression[] arguments) + { + B.Attribute a = new B.Attribute(lastLexicalInfo, name); + foreach (B.Expression arg in arguments) { + a.Arguments.Add(arg); + } + return a; + } + + void ConvertTypeReferences(List input, B.TypeReferenceCollection output) + { + foreach (TypeReference t in input) { + B.TypeReference r = ConvertTypeReference(t); + if (r != null) { + output.Add(r); + } + } + } + + Dictionary intrinsicTypeDictionary; + + class BooTypeSystemServices : Boo.Lang.Compiler.TypeSystem.TypeSystemServices + { + public System.Collections.Hashtable Primitives { + get { + return _primitives; + } + } + } + + string GetIntrinsicTypeName(string typeName) + { + if (settings.SimplifyTypeNames) { + if (intrinsicTypeDictionary == null) { + intrinsicTypeDictionary = new Dictionary(); + foreach (System.Collections.DictionaryEntry entry in new BooTypeSystemServices().Primitives) { + try { + intrinsicTypeDictionary.Add(((Boo.Lang.Compiler.TypeSystem.IEntity)entry.Value).FullName, (string)entry.Key); + } catch (ArgumentException) {} + } + } + string result; + if (intrinsicTypeDictionary.TryGetValue(typeName, out result)) + return result; + } + return typeName; + } + + B.TypeReference ConvertTypeReference(TypeReference t) + { + if (t == null || t.IsNull) + return null; + B.TypeReference r = new B.SimpleTypeReference(GetLexicalInfo(t), GetIntrinsicTypeName(t.SystemType)); + if (t.GenericTypes.Count > 0) { + AddError(t, "Consuming generics is not supported by boo."); + } + if (t.IsArrayType) { + for (int i = t.RankSpecifier.Length - 1; i >= 0; --i) { + r = new B.ArrayTypeReference(GetLexicalInfo(t), r, new B.IntegerLiteralExpression(t.RankSpecifier[i] + 1)); + } + } + if (t.PointerNestingLevel != 0) { + AddError(t, "Pointers are not supported by boo."); + } + return r; + } + + B.TypeReference ConvertTypeReference(B.Expression expr) + { + B.TypeofExpression te = expr as B.TypeofExpression; + if (te != null) + return te.Type; + if (expr is B.ReferenceExpression) { + return new B.SimpleTypeReference(expr.ToCodeString()); + } + AddError(expr.LexicalInfo, "Expected type, but found expression."); + return null; + } + + /// + /// Convert TypeReference and wrap it into an TypeofExpression. + /// + B.TypeofExpression WrapTypeReference(TypeReference t) + { + return new B.TypeofExpression(GetLexicalInfo(t), ConvertTypeReference(t)); + } + + public object Visit(TypeReference typeReference, object data) + { + return ConvertTypeReference(typeReference); + } + + public object Visit(InnerClassTypeReference typeReference, object data) + { + return ConvertTypeReference(typeReference); + } + } +} diff --git a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ConvertVisitorExpressions.cs b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ConvertVisitorExpressions.cs new file mode 100644 index 0000000000..6670223aa7 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ConvertVisitorExpressions.cs @@ -0,0 +1,519 @@ +#region license +// Copyright (c) 2005, Daniel Grunwald (daniel@danielgrunwald.de) +// All rights reserved. +// +// NRefactoryToBoo is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// NRefactoryToBoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with NRefactoryToBoo; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#endregion + +using System; +using System.Collections; +using System.Collections.Generic; +using ICSharpCode.NRefactory.Parser; +using ICSharpCode.NRefactory.Parser.AST; +using Boo.Lang.Compiler; +using B = Boo.Lang.Compiler.Ast; + +namespace NRefactoryToBooConverter +{ + partial class ConvertVisitor + { + void ConvertExpressions(IEnumerable input, B.ExpressionCollection output) + { + foreach (Expression e in input) { + B.Expression expr = ConvertExpression(e); + if (expr != null) { + output.Add(expr); + } + } + } + + B.Expression ConvertExpression(Expression expr) + { + if (expr.IsNull) + return null; + return (B.Expression)expr.AcceptVisitor(this, null); + } + + B.ReferenceExpression MakeReferenceExpression(string fullName) + { + string[] parts = fullName.Split('.'); + B.ReferenceExpression r = new B.ReferenceExpression(lastLexicalInfo, parts[0]); + for (int i = 1; i < parts.Length; i++) + r = new B.MemberReferenceExpression(lastLexicalInfo, r, parts[i]); + return r; + } + + B.MethodInvocationExpression MakeMethodCall(string fullName, params B.Expression[] arguments) + { + return new B.MethodInvocationExpression(MakeReferenceExpression(fullName), arguments); + } + + public object Visit(PrimitiveExpression pe, object data) + { + object val = pe.Value; + if (val == null) { + return new B.NullLiteralExpression(GetLexicalInfo(pe)); + } + if (val is string) { + return new B.StringLiteralExpression(GetLexicalInfo(pe), (string)val); + } + if (val is char) { + return new B.CharLiteralExpression(GetLexicalInfo(pe), ((char)val).ToString()); + } + if (val is bool) { + return new B.BoolLiteralExpression(GetLexicalInfo(pe), (bool)val); + } + if (val is byte) { + AddWarning(pe, "Converting byte literal to int literal"); + return new B.IntegerLiteralExpression(GetLexicalInfo(pe), (byte)val, false); + } + if (val is short) { + AddWarning(pe, "Converting short literal to int literal"); + return new B.IntegerLiteralExpression(GetLexicalInfo(pe), (short)val, false); + } + if (val is int) { + return new B.IntegerLiteralExpression(GetLexicalInfo(pe), (int)val, false); + } + if (val is long) { + return new B.IntegerLiteralExpression(GetLexicalInfo(pe), (long)val, true); + } + if (val is sbyte) { + AddWarning(pe, "Converting sbyte literal to int literal"); + return new B.IntegerLiteralExpression(GetLexicalInfo(pe), (sbyte)val, false); + } + if (val is ushort) { + AddWarning(pe, "Converting ushort literal to int literal"); + return new B.IntegerLiteralExpression(GetLexicalInfo(pe), (ushort)val, false); + } + if (val is uint) { + AddWarning(pe, "Converting uint literal to int/long literal"); + return new B.IntegerLiteralExpression(GetLexicalInfo(pe), (uint)val); + } + if (val is ulong) { + AddWarning(pe, "Converting ulong literal to long literal"); + return new B.IntegerLiteralExpression(GetLexicalInfo(pe), (long)((ulong)val), true); + } + if (val is float) { + return new B.DoubleLiteralExpression(GetLexicalInfo(pe), (float)val, true); + } + if (val is double) { + return new B.DoubleLiteralExpression(GetLexicalInfo(pe), (double)val, false); + } + AddError(pe, "Unknown primitive literal of type " + val.GetType().FullName); + return null; + } + + public object Visit(IdentifierExpression identifierExpression, object data) + { + return new B.ReferenceExpression(GetLexicalInfo(identifierExpression), identifierExpression.Identifier); + } + + public object Visit(FieldReferenceExpression fre, object data) + { + B.Expression target = null; + if (fre.TargetObject is TypeReferenceExpression) { + // not typeof, so this is something like int.Parse() + TypeReference typeRef = ((TypeReferenceExpression)fre.TargetObject).TypeReference; + if (!typeRef.IsArrayType) + target = MakeReferenceExpression(typeRef.SystemType); + } + if (target == null) { + target = (B.Expression)fre.TargetObject.AcceptVisitor(this, data); + if (target == null) return null; + } + return new B.MemberReferenceExpression(GetLexicalInfo(fre), target, fre.FieldName); + } + + public object Visit(ClassReferenceExpression classReferenceExpression, object data) + { + // VB's MyClass.Method references methods in the CURRENT class, ignoring overrides!!! + // that is supported neither by C# nor Boo. + // Most of the time, "Me"="self" should also do the job. + AddWarning(classReferenceExpression, "Class reference is not supported, replaced with self reference."); + return new B.SelfLiteralExpression(GetLexicalInfo(classReferenceExpression)); + } + + B.BinaryOperatorType ConvertOperator(AssignmentOperatorType op, out bool isInPlace) + { + isInPlace = true; + switch (op) { + case AssignmentOperatorType.Add: + return B.BinaryOperatorType.InPlaceAddition; + case AssignmentOperatorType.Assign: + return B.BinaryOperatorType.Assign; + case AssignmentOperatorType.BitwiseAnd: + return B.BinaryOperatorType.InPlaceBitwiseAnd; + case AssignmentOperatorType.BitwiseOr: + return B.BinaryOperatorType.InPlaceBitwiseOr; + case AssignmentOperatorType.ConcatString: + return B.BinaryOperatorType.InPlaceAddition; + case AssignmentOperatorType.Divide: + return B.BinaryOperatorType.InPlaceDivision; + case AssignmentOperatorType.DivideInteger: + return B.BinaryOperatorType.InPlaceDivision; + case AssignmentOperatorType.ExclusiveOr: + return B.BinaryOperatorType.InPlaceExclusiveOr; + case AssignmentOperatorType.Modulus: + isInPlace = false; + return B.BinaryOperatorType.Modulus; + case AssignmentOperatorType.Multiply: + return B.BinaryOperatorType.InPlaceMultiply; + case AssignmentOperatorType.Power: + isInPlace = false; + return B.BinaryOperatorType.Exponentiation; + case AssignmentOperatorType.ShiftLeft: + return B.BinaryOperatorType.InPlaceShiftLeft; + case AssignmentOperatorType.ShiftRight: + return B.BinaryOperatorType.InPlaceShiftRight; + case AssignmentOperatorType.Subtract: + return B.BinaryOperatorType.InPlaceSubtraction; + default: + return B.BinaryOperatorType.None; + } + } + + public object Visit(AssignmentExpression assignmentExpression, object data) + { + B.Expression left = ConvertExpression(assignmentExpression.Left); + B.Expression right = ConvertExpression(assignmentExpression.Right); + bool isInPlace; + B.BinaryOperatorType op = ConvertOperator(assignmentExpression.Op, out isInPlace); + if (op == B.BinaryOperatorType.None) { + AddError(assignmentExpression, "Unknown operator."); + return null; + } + if (!isInPlace) { + // convert L = R to L = L OP R + right = new B.BinaryExpression(GetLexicalInfo(assignmentExpression), op, left, right); + op = B.BinaryOperatorType.Assign; + } + return new B.BinaryExpression(GetLexicalInfo(assignmentExpression), op, left, right); + } + + B.BinaryOperatorType ConvertOperator(BinaryOperatorType op) + { + switch (op) { + case BinaryOperatorType.Add: + return B.BinaryOperatorType.Addition; + //case BinaryOperatorType.AsCast: special case: converted to AsExpression + case BinaryOperatorType.BitwiseAnd: + return B.BinaryOperatorType.BitwiseAnd; + case BinaryOperatorType.BitwiseOr: + return B.BinaryOperatorType.BitwiseOr; + case BinaryOperatorType.Concat: + return B.BinaryOperatorType.Addition; + case BinaryOperatorType.Divide: + return B.BinaryOperatorType.Division; + case BinaryOperatorType.DivideInteger: + return B.BinaryOperatorType.Division; + case BinaryOperatorType.Equality: + return B.BinaryOperatorType.Equality; + case BinaryOperatorType.ExclusiveOr: + return B.BinaryOperatorType.ExclusiveOr; + case BinaryOperatorType.GreaterThan: + return B.BinaryOperatorType.GreaterThan; + case BinaryOperatorType.GreaterThanOrEqual: + return B.BinaryOperatorType.GreaterThanOrEqual; + case BinaryOperatorType.InEquality: + return B.BinaryOperatorType.Inequality; + case BinaryOperatorType.LessThan: + return B.BinaryOperatorType.LessThan; + case BinaryOperatorType.LessThanOrEqual: + return B.BinaryOperatorType.LessThanOrEqual; + case BinaryOperatorType.Like: + return B.BinaryOperatorType.Match; + case BinaryOperatorType.LogicalAnd: + return B.BinaryOperatorType.And; + case BinaryOperatorType.LogicalOr: + return B.BinaryOperatorType.Or; + case BinaryOperatorType.Modulus: + return B.BinaryOperatorType.Modulus; + case BinaryOperatorType.Multiply: + return B.BinaryOperatorType.Multiply; + case BinaryOperatorType.Power: + return B.BinaryOperatorType.Exponentiation; + case BinaryOperatorType.ReferenceEquality: + return B.BinaryOperatorType.ReferenceEquality; + case BinaryOperatorType.ReferenceInequality: + return B.BinaryOperatorType.ReferenceInequality; + case BinaryOperatorType.ShiftLeft: + return B.BinaryOperatorType.ShiftLeft; + case BinaryOperatorType.ShiftRight: + return B.BinaryOperatorType.ShiftRight; + case BinaryOperatorType.Subtract: + return B.BinaryOperatorType.Subtraction; + case BinaryOperatorType.TypeCheck: + return B.BinaryOperatorType.TypeTest; + default: + return B.BinaryOperatorType.None; + } + } + + + B.UnaryOperatorType ConvertOperator(UnaryOperatorType op) + { + switch (op) { + case UnaryOperatorType.BitNot: + return B.UnaryOperatorType.OnesComplement; + case UnaryOperatorType.Not: + return B.UnaryOperatorType.LogicalNot; + case UnaryOperatorType.Decrement: + return B.UnaryOperatorType.Decrement; + case UnaryOperatorType.Increment: + return B.UnaryOperatorType.Increment; + case UnaryOperatorType.Minus: + return B.UnaryOperatorType.UnaryNegation; + case UnaryOperatorType.PostDecrement: + return B.UnaryOperatorType.PostDecrement; + case UnaryOperatorType.PostIncrement: + return B.UnaryOperatorType.PostIncrement; + default: + return B.UnaryOperatorType.None; + } + } + + public object Visit(BinaryOperatorExpression binaryOperatorExpression, object data) + { + B.Expression left = ConvertExpression(binaryOperatorExpression.Left); + B.Expression right = ConvertExpression(binaryOperatorExpression.Right); + B.BinaryOperatorType op = ConvertOperator(binaryOperatorExpression.Op); + if (op == B.BinaryOperatorType.None) { + if (binaryOperatorExpression.Op == BinaryOperatorType.AsCast) { + return new B.AsExpression(GetLexicalInfo(binaryOperatorExpression), left, ConvertTypeReference(right)); + } else { + AddError(binaryOperatorExpression, "Unknown operator."); + return null; + } + } +// if (binaryOperatorExpression.Op == BinaryOperatorType.DivideInteger) { +// AddWarning(binaryOperatorExpression, "Integer division converted to normal division."); +// } + return new B.BinaryExpression(GetLexicalInfo(binaryOperatorExpression), op, left, right); + } + + public object Visit(UnaryOperatorExpression unaryOperatorExpression, object data) + { + B.Expression expr = ConvertExpression(unaryOperatorExpression.Expression); + if (unaryOperatorExpression.Op == UnaryOperatorType.Plus) + return expr; + B.UnaryOperatorType op = ConvertOperator(unaryOperatorExpression.Op); + if (op == B.UnaryOperatorType.None) { + AddError(unaryOperatorExpression, "Unknown operator."); + return null; + } + return new B.UnaryExpression(GetLexicalInfo(unaryOperatorExpression), op, expr); + } + + public object Visit(ParenthesizedExpression parenthesizedExpression, object data) + { + return ConvertExpression(parenthesizedExpression.Expression); + } + + public object Visit(InvocationExpression ie, object data) + { + if (ie.TypeArguments != null && ie.TypeArguments.Count > 0) { + AddError(ie, "Generic method calls are not supported."); + } + B.Expression e = ConvertExpression(ie.TargetObject); + if (e == null) + return null; + if (settings.IsVisualBasic && ie.TargetObject is IdentifierExpression && currentStatement != null) { + VariableResolver resolver = new VariableResolver(nameComparer); + TypeReference typeRef = resolver.FindType((ie.TargetObject as IdentifierExpression).Identifier, currentStatement); + if (typeRef != null && typeRef.IsArrayType) { + // Visual Basic: indexer expression + B.SlicingExpression s = new B.SlicingExpression(GetLexicalInfo(ie)); + s.Target = e; + foreach (Expression expr in ie.Arguments) { + s.Indices.Add(new B.Slice(ConvertExpression(expr))); + } + return s; + } + } + B.MethodInvocationExpression r = new B.MethodInvocationExpression(GetLexicalInfo(ie), e); + foreach (Expression expr in ie.Arguments) { + e = ConvertExpression(expr); + if (e != null) { + r.Arguments.Add(e); + } + } + return r; + } + + public object Visit(ObjectCreateExpression objectCreateExpression, object data) + { + TypeReference t = objectCreateExpression.CreateType; + if (t.IsArrayType) { + throw new ApplicationException("ObjectCreateExpression cannot be called with an ArrayType"); + } + // HACK: Tricking out event handlers + if (t.SystemType.EndsWith("EventHandler") && objectCreateExpression.Parameters.Count == 1) + return ConvertExpression((Expression)objectCreateExpression.Parameters[0]); + + B.MethodInvocationExpression mie = new B.MethodInvocationExpression(GetLexicalInfo(objectCreateExpression), MakeReferenceExpression(t.SystemType)); + ConvertExpressions(objectCreateExpression.Parameters, mie.Arguments); + return mie; + } + + public object Visit(TypeReferenceExpression typeReferenceExpression, object data) + { + return WrapTypeReference(typeReferenceExpression.TypeReference); + } + + public object Visit(SizeOfExpression sizeOfExpression, object data) + { + AddError(sizeOfExpression, "sizeof is not supported."); + return null; + } + + public object Visit(DefaultValueExpression defaultValueExpression, object data) + { + AddError(defaultValueExpression, "default() is not supported."); + return null; + } + + public object Visit(TypeOfExpression typeOfExpression, object data) + { + return new B.TypeofExpression(GetLexicalInfo(typeOfExpression), ConvertTypeReference(typeOfExpression.TypeReference)); + } + + public object Visit(TypeOfIsExpression typeOfIsExpression, object data) + { + return new B.BinaryExpression(GetLexicalInfo(typeOfIsExpression), B.BinaryOperatorType.TypeTest, + ConvertExpression(typeOfIsExpression.Expression), + WrapTypeReference(typeOfIsExpression.TypeReference)); + } + + public object Visit(AddressOfExpression addressOfExpression, object data) + { + // Boo can reference methods directly + return ConvertExpression(addressOfExpression.Expression); + } + + public object Visit(PointerReferenceExpression pointerReferenceExpression, object data) + { + AddError(pointerReferenceExpression, "Pointers are not supported."); + return null; + } + + public object Visit(CastExpression castExpression, object data) + { + return new B.CastExpression(GetLexicalInfo(castExpression), + ConvertTypeReference(castExpression.CastTo), + ConvertExpression(castExpression.Expression)); + } + + public object Visit(StackAllocExpression stackAllocExpression, object data) + { + AddError(stackAllocExpression, "StackAlloc is not supported."); + return null; + } + + public object Visit(ThisReferenceExpression thisReferenceExpression, object data) + { + return new B.SelfLiteralExpression(GetLexicalInfo(thisReferenceExpression)); + } + + public object Visit(BaseReferenceExpression baseReferenceExpression, object data) + { + return new B.SuperLiteralExpression(GetLexicalInfo(baseReferenceExpression)); + } + + public object Visit(DirectionExpression directionExpression, object data) + { + // boo does not need to specify the direction when calling out/ref methods + return ConvertExpression(directionExpression.Expression); + } + + public object Visit(ArrayCreateExpression arrayCreateExpression, object data) + { + if (!arrayCreateExpression.ArrayInitializer.IsNull) { + return arrayCreateExpression.ArrayInitializer.AcceptVisitor(this, data); + } + ArrayCreationParameter acp = (ArrayCreationParameter)arrayCreateExpression.Parameters[0]; + string builtInName = (acp.Expressions.Count == 1) ? "array" : "matrix"; + B.MethodInvocationExpression mie = new B.MethodInvocationExpression(GetLexicalInfo(arrayCreateExpression), + MakeReferenceExpression(builtInName)); + if (arrayCreateExpression.Parameters.Count > 1) { + arrayCreateExpression.CreateType.RankSpecifier = new int[arrayCreateExpression.Parameters.Count - 1]; + mie.Arguments.Add(WrapTypeReference(arrayCreateExpression.CreateType)); + } else { + mie.Arguments.Add(MakeReferenceExpression(arrayCreateExpression.CreateType.SystemType)); + } + if (acp.Expressions.Count == 1) { + mie.Arguments.Add(ConvertExpression((Expression)acp.Expressions[0])); + } else { + B.ArrayLiteralExpression dims = new B.ArrayLiteralExpression(GetLexicalInfo(acp)); + ConvertExpressions(acp.Expressions, dims.Items); + mie.Arguments.Add(dims); + } + return mie; + } + + public object Visit(ArrayCreationParameter arrayCreationParameter, object data) + { + throw new ApplicationException("Visited ArrayCreationParameter."); + } + + public object Visit(ArrayInitializerExpression aie, object data) + { + B.ArrayLiteralExpression dims = new B.ArrayLiteralExpression(GetLexicalInfo(aie)); + ConvertExpressions(aie.CreateExpressions, dims.Items); + return dims; + } + + public object Visit(IndexerExpression indexerExpression, object data) + { + B.SlicingExpression s = new B.SlicingExpression(GetLexicalInfo(indexerExpression)); + s.Target = ConvertExpression(indexerExpression.TargetObject); + foreach (Expression expr in indexerExpression.Indices) { + s.Indices.Add(new B.Slice(ConvertExpression(expr))); + } + return s; + } + + public object Visit(AnonymousMethodExpression anonymousMethodExpression, object data) + { + B.CallableBlockExpression cbe = new B.CallableBlockExpression(GetLexicalInfo(anonymousMethodExpression)); + cbe.EndSourceLocation = GetLocation(anonymousMethodExpression.EndLocation); + cbe.Body = ConvertBlock(anonymousMethodExpression.Body); + ConvertParameters(anonymousMethodExpression.Parameters, cbe.Parameters); + return cbe; + } + + public object Visit(ConditionalExpression conditionalExpression, object data) + { + B.TernaryExpression te = new B.TernaryExpression(GetLexicalInfo(conditionalExpression)); + te.Condition = ConvertExpression(conditionalExpression.Condition); + te.TrueValue = ConvertExpression(conditionalExpression.TrueExpression); + te.FalseValue = ConvertExpression(conditionalExpression.FalseExpression); + return te; + } + + public object Visit(CheckedExpression checkedExpression, object data) + { + AddError(checkedExpression, "Using 'checked' inside an expression is not supported by boo, " + + "use the checked {} block instead."); + return null; + } + + public object Visit(UncheckedExpression uncheckedExpression, object data) + { + AddError(uncheckedExpression, "Using 'unchecked' inside an expression is not supported by boo, " + + "use the unchecked {} block instead."); + return null; + } + } +} diff --git a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ConvertVisitorGlobal.cs b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ConvertVisitorGlobal.cs new file mode 100644 index 0000000000..de2b31eabf --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ConvertVisitorGlobal.cs @@ -0,0 +1,221 @@ +#region license +// Copyright (c) 2005, Daniel Grunwald (daniel@danielgrunwald.de) +// All rights reserved. +// +// NRefactoryToBoo is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// NRefactoryToBoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with NRefactoryToBoo; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#endregion + +using System; +using System.Collections.Generic; +using ICSharpCode.NRefactory.Parser; +using ICSharpCode.NRefactory.Parser.AST; +using Boo.Lang.Compiler; +using B = Boo.Lang.Compiler.Ast; + +namespace NRefactoryToBooConverter +{ + partial class ConvertVisitor + { + public object Visit(INode node, object data) + { + AddError(node, "Visited INode: " + node); + return null; + } + + public object Visit(CompilationUnit compilationUnit, object data) + { + module = new B.Module(); + module.LexicalInfo = new B.LexicalInfo(fileName, 1, 1); + compilationUnit.AcceptChildren(this, data); + if (entryPointMethod != null) { + bool allMembersAreStatic = true; + foreach (B.TypeMember member in entryPointMethod.DeclaringType.Members) { + allMembersAreStatic &= member.IsStatic; + } + if (allMembersAreStatic) { + entryPointMethod.DeclaringType.Attributes.Add(MakeAttribute(("module"))); + } else { + lastLexicalInfo = entryPointMethod.LexicalInfo; + B.Expression expr = MakeReferenceExpression(entryPointMethod.DeclaringType.Name + ".Main"); + B.MethodInvocationExpression mie = new B.MethodInvocationExpression(lastLexicalInfo, expr); + if (entryPointMethod.Parameters.Count > 0) { + mie.Arguments.Add(MakeReferenceExpression("argv")); + } + B.SimpleTypeReference ret = entryPointMethod.ReturnType as B.SimpleTypeReference; + if (ret.Name == "void" || ret.Name == "System.Void") + module.Globals.Add(new B.ExpressionStatement(mie)); + else + module.Globals.Add(new B.ReturnStatement(lastLexicalInfo, mie, null)); + } + } + B.Module tmp = module; + module = null; + return tmp; + } + + public object Visit(NamespaceDeclaration namespaceDeclaration, object data) + { + if (module.Namespace != null) { + AddError(namespaceDeclaration, "Only one namespace declaration per file is supported."); + return null; + } + module.Namespace = new B.NamespaceDeclaration(GetLexicalInfo(namespaceDeclaration)); + module.Namespace.Name = namespaceDeclaration.Name; + return namespaceDeclaration.AcceptChildren(this, data); + } + + public object Visit(UsingDeclaration usingDeclaration, object data) + { + foreach (Using u in usingDeclaration.Usings) { + Visit(u, data); + } + return null; + } + + public object Visit(Using @using, object data) + { + B.Import import; + if (@using.IsAlias) { + import = new B.Import(@using.Alias.Type, null, new B.ReferenceExpression(@using.Name)); + import.LexicalInfo = GetLexicalInfo(@using); + } else { + import = new B.Import(GetLexicalInfo(@using), @using.Name); + } + module.Imports.Add(import); + return import; + } + + B.TypeDefinition currentType; + + public object Visit(TypeDeclaration typeDeclaration, object data) + { + if (typeDeclaration.Templates.Count > 0) { + AddError(typeDeclaration, "Generic type definitions are not supported."); + } + B.TypeDefinition oldType = currentType; + B.TypeDefinition typeDef; + switch (typeDeclaration.Type) { + case ClassType.Class: + typeDef = new B.ClassDefinition(GetLexicalInfo(typeDeclaration)); + break; + case ClassType.Interface: + typeDef = new B.InterfaceDefinition(GetLexicalInfo(typeDeclaration)); + break; + case ClassType.Enum: + typeDef = new B.EnumDefinition(GetLexicalInfo(typeDeclaration)); + break; + case ClassType.Struct: + typeDef = new B.StructDefinition(GetLexicalInfo(typeDeclaration)); + break; + case ClassType.Module: + typeDef = new B.ClassDefinition(GetLexicalInfo(typeDeclaration)); + typeDeclaration.Modifier |= Modifier.Static; + break; + default: + AddError(typeDeclaration, "Unknown class type."); + return null; + } + if (currentType != null) + typeDef.Modifiers = ConvertModifier(typeDeclaration, B.TypeMemberModifiers.Private); + else + typeDef.Modifiers = ConvertModifier(typeDeclaration, B.TypeMemberModifiers.Internal); + typeDef.Name = typeDeclaration.Name; + typeDef.EndSourceLocation = GetLocation(typeDeclaration.EndLocation); + ConvertAttributes(typeDeclaration.Attributes, typeDef.Attributes); + ConvertTypeReferences(typeDeclaration.BaseTypes, typeDef.BaseTypes); + + if (currentType != null) + currentType.Members.Add(typeDef); + else + module.Members.Add(typeDef); + currentType = typeDef; + typeDeclaration.AcceptChildren(this, data); + currentType = oldType; + return typeDef; + } + + public object Visit(DelegateDeclaration delegateDeclaration, object data) + { + B.CallableDefinition cd = new B.CallableDefinition(GetLexicalInfo(delegateDeclaration)); + cd.Name = delegateDeclaration.Name; + ConvertAttributes(delegateDeclaration.Attributes, cd.Attributes); + cd.Modifiers = ConvertModifier(delegateDeclaration, B.TypeMemberModifiers.Private); + ConvertParameters(delegateDeclaration.Parameters, cd.Parameters); + cd.ReturnType = ConvertTypeReference(delegateDeclaration.ReturnType); + if (currentType != null) + currentType.Members.Add(cd); + else + module.Members.Add(cd); + return cd; + } + + void ConvertAttributes(List sections, B.AttributeCollection col) + { + foreach (AttributeSection s in sections) { + if (s.AttributeTarget.Length > 0) { + AddError(s, "Attribute target not supported"); + continue; + } + foreach (ICSharpCode.NRefactory.Parser.AST.Attribute a in s.Attributes) { + col.Add((B.Attribute)Visit(a, null)); + } + } + } + + public object Visit(ICSharpCode.NRefactory.Parser.AST.Attribute a, object data) + { + B.Attribute att = new B.Attribute(GetLexicalInfo(a), a.Name); + att.EndSourceLocation = GetLocation(a.EndLocation); + ConvertExpressions(a.PositionalArguments, att.Arguments); + foreach (NamedArgumentExpression nae in a.NamedArguments) { + B.Expression expr = ConvertExpression(nae.Expression); + if (expr != null) { + att.NamedArguments.Add(new B.ExpressionPair(new B.ReferenceExpression(nae.Name), expr)); + } + } + return att; + } + + public object Visit(AttributeSection s, object data) + { + if (s.AttributeTarget.ToLower() == "assembly") { + foreach (ICSharpCode.NRefactory.Parser.AST.Attribute a in s.Attributes) { + module.AssemblyAttributes.Add((B.Attribute)Visit(a, null)); + } + } else { + AddError(s, "Attribute must have the target 'assembly'"); + } + return null; + } + + // Some classes are handled by their parent (NamedArgumentExpression by Attribute etc.) + // so we don't need to implement Visit for them. + public object Visit(TemplateDefinition templateDefinition, object data) + { + throw new ApplicationException("Visited TemplateDefinition."); + } + + public object Visit(NamedArgumentExpression namedArgumentExpression, object data) + { + throw new ApplicationException("Visited NamedArgumentExpression."); + } + + public object Visit(OptionDeclaration optionDeclaration, object data) + { + AddError(optionDeclaration, "Option statement is not supported."); + return null; + } + } +} diff --git a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ConvertVisitorStatements.cs b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ConvertVisitorStatements.cs new file mode 100644 index 0000000000..ec0ec8d6cf --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ConvertVisitorStatements.cs @@ -0,0 +1,686 @@ +#region license +// Copyright (c) 2005, Daniel Grunwald (daniel@danielgrunwald.de) +// All rights reserved. +// +// NRefactoryToBoo is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// NRefactoryToBoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with NRefactoryToBoo; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#endregion + +using System; +using System.Collections; +using System.Collections.Generic; +using ICSharpCode.NRefactory.Parser; +using ICSharpCode.NRefactory.Parser.AST; +using Boo.Lang.Compiler; +using B = Boo.Lang.Compiler.Ast; + +namespace NRefactoryToBooConverter +{ + partial class ConvertVisitor + { + void ConvertStatements(IEnumerable statements, B.Block b) + { + foreach (Statement n in statements) { + AddToBlock(n, b); + } + } + + Statement currentStatement; + + object ConvertStatementInternal(Statement stmt) + { + Statement oldStatement = currentStatement; + currentStatement = stmt; + try { + return stmt.AcceptVisitor(this, null); + } finally { + currentStatement = oldStatement; + } + } + + void AddToBlock(Statement n, B.Block b) + { + object result = ConvertStatementInternal(n); + if (result is ArrayList) { + foreach (B.Statement stmt in (ArrayList)result) { + b.Add(stmt); + } + } else { + B.Statement stmt = (B.Statement)result; + if (stmt != null) { + b.Add(stmt); + } + } + } + + ArrayList ConvertStatements(IEnumerable statements) + { + ArrayList r = new ArrayList(); + foreach (Statement n in statements) { + object result = ConvertStatementInternal(n); + if (result is ArrayList) { + r.AddRange((ArrayList)result); + } else if (result != null) { + r.Add(result); + } + } + return r; + } + + B.Block ConvertBlock(Statement statement) + { + if (statement == null || statement.IsNull) + return null; + ArrayList statements = new ArrayList(1); + statements.Add(statement); + return ConvertBlock(statements); + } + + B.Block ConvertBlock(BlockStatement block) + { + B.Block b = new B.Block(GetLexicalInfo(block)); + b.EndSourceLocation = GetLocation(block.EndLocation); + ConvertStatements(block.Children, b); + return b; + } + + B.Block ConvertBlock(ArrayList statements) + { + if (statements.Count == 1) { + if (statements[0] is BlockStatement) + return ConvertBlock(statements[0] as BlockStatement); + } + B.Block b = new B.Block(); + ConvertStatements(statements, b); + return b; + } + + public object Visit(BlockStatement blockStatement, object data) + { + return ConvertBlock(blockStatement); + } + + B.MacroStatement CreateMacro(INode node, string name, Statement embedded, params Expression[] arguments) + { + B.MacroStatement macro = new B.MacroStatement(GetLexicalInfo(node)); + macro.Name = name; + ConvertExpressions(arguments, macro.Arguments); + if (embedded is BlockStatement) { + macro.Block = ConvertBlock((BlockStatement)embedded); + } else { + macro.Block = new B.Block(); + macro.Block.Add((B.Statement)embedded.AcceptVisitor(this, null)); + } + return macro; + } + + public object Visit(FixedStatement fixedStatement, object data) + { + AddError(fixedStatement, "FixedStatement is not supported."); + return null; + } + + public object Visit(UnsafeStatement unsafeStatement, object data) + { + AddError(unsafeStatement, "UnsafeStatement is not supported."); + return null; + } + + public object Visit(CheckedStatement checkedStatement, object data) + { + return CreateMacro(checkedStatement, "checked", checkedStatement.Block); + } + + public object Visit(UncheckedStatement uncheckedStatement, object data) + { + return CreateMacro(uncheckedStatement, "unchecked", uncheckedStatement.Block); + } + + public object Visit(ExitStatement exitStatement, object data) + { + if (exitStatement.ExitType == ExitType.Function || exitStatement.ExitType == ExitType.Sub || exitStatement.ExitType == ExitType.Property) { + AddWarning(exitStatement, "ExitStatement is converted to 'return'"); + return new B.ReturnStatement(GetLexicalInfo(exitStatement)); + } else { + AddWarning(exitStatement, "ExitStatement is converted to 'break'"); + return new B.BreakStatement(GetLexicalInfo(exitStatement)); + } + } + + /// + /// Make a loop: + /// $initializers + /// goto ___converterGeneratedName# + /// while true: + /// $iterators + /// :___converterGeneratedName# + /// break $conditionType $condition + /// $body + /// + ArrayList MakeManualLoop(INode node, ArrayList initializers, B.StatementModifierType conditionType, Expression condition, ArrayList iterators, Statement body) + { + // we use this "while true" form because "continue" may not skip the iterator. + + ArrayList list = ConvertStatements(initializers); + B.LabelStatement labelStatement = MakeLabel(GenerateName()); + B.GotoStatement gotoStatement = new B.GotoStatement(); + gotoStatement.Label = new B.ReferenceExpression(labelStatement.Name); + list.Add(gotoStatement); + + B.WhileStatement w = new B.WhileStatement(GetLexicalInfo(node)); + w.Condition = new B.BoolLiteralExpression(true); + list.Add(w); + w.Block = ConvertBlock(iterators); + B.BreakStatement breakStatement = new B.BreakStatement(); + breakStatement.Modifier = new B.StatementModifier(conditionType, ConvertExpression(condition)); + w.Block.Add(labelStatement); + w.Block.Add(breakStatement); + foreach (B.Statement st in ConvertBlock(body).Statements) { + w.Block.Add(st); + } + return list; + } + + ArrayList MakeManualLoop(ForNextStatement forNextStatement) + { + Expression var = new IdentifierExpression(forNextStatement.VariableName); + ArrayList initializers = new ArrayList(1); + initializers.Add(new StatementExpression(new AssignmentExpression(var, AssignmentOperatorType.Assign, forNextStatement.Start))); + ArrayList iterators = new ArrayList(1); + Expression step = forNextStatement.Step; + if (step == null || step.IsNull) + step = new PrimitiveExpression(1, "1"); + iterators.Add(new StatementExpression(new AssignmentExpression(var, AssignmentOperatorType.Add, step))); + PrimitiveExpression stepPE = step as PrimitiveExpression; + if (stepPE == null || !(stepPE.Value is int)) { + AddError(forNextStatement, "Step must be an integer literal"); + return null; + } + BinaryOperatorType conditionOperator; + if ((int)stepPE.Value < 0) { + conditionOperator = BinaryOperatorType.GreaterThanOrEqual;// counting down + } else { + conditionOperator = BinaryOperatorType.LessThanOrEqual;// counting up + } + Expression condition = new BinaryOperatorExpression(var, conditionOperator, forNextStatement.End); + return MakeManualLoop(forNextStatement, initializers, B.StatementModifierType.Unless, condition, iterators, forNextStatement.EmbeddedStatement); + } + + public object Visit(ForNextStatement forNextStatement, object data) + { + if (forNextStatement.TypeReference.IsNull) + return MakeManualLoop(forNextStatement); + B.ForStatement fs = new B.ForStatement(GetLexicalInfo(forNextStatement)); + fs.Block = ConvertBlock(forNextStatement.EmbeddedStatement); + fs.Declarations.Add(new B.Declaration(forNextStatement.VariableName, null)); + B.Expression start = ConvertExpression(forNextStatement.Start); + Expression end = forNextStatement.End; + if (forNextStatement.Step == null || forNextStatement.Step.IsNull) { + // range only goes to end - 1, so increment end + end = Expression.AddInteger(end, 1); + fs.Iterator = MakeMethodCall("range", start, ConvertExpression(end)); + } else { + PrimitiveExpression stepPE = forNextStatement.Step as PrimitiveExpression; + if (stepPE == null || !(stepPE.Value is int)) { + AddError(forNextStatement, "Step must be an integer literal"); + } else { + if ((int)stepPE.Value < 0) + end = Expression.AddInteger(end, -1); + else + end = Expression.AddInteger(end, 1); + } + fs.Iterator = MakeMethodCall("range", start, ConvertExpression(end), ConvertExpression(forNextStatement.Step)); + } + return fs; + } + + public object Visit(ForStatement forStatement, object data) + { + return MakeManualLoop(forStatement, forStatement.Initializers, B.StatementModifierType.Unless, + forStatement.Condition, forStatement.Iterator, forStatement.EmbeddedStatement); + } + + public object Visit(DoLoopStatement doLoopStatement, object data) + { + bool frontCondition = doLoopStatement.ConditionPosition != ConditionPosition.End; + bool negateCondition = doLoopStatement.ConditionType == ConditionType.Until; + if (frontCondition && negateCondition) { + // VB: Do Unless * : ** : Loop + B.UnlessStatement u = new B.UnlessStatement(GetLexicalInfo(doLoopStatement)); + u.Condition = ConvertExpression(doLoopStatement.Condition); + u.Block = ConvertBlock(doLoopStatement.EmbeddedStatement); + return u; + } + // While and Do loop + B.WhileStatement w = new B.WhileStatement(GetLexicalInfo(doLoopStatement)); + if (frontCondition) + w.Condition = ConvertExpression(doLoopStatement.Condition); + else + w.Condition = new B.BoolLiteralExpression(true); + w.Block = ConvertBlock(doLoopStatement.EmbeddedStatement); + if (!frontCondition) { + B.BreakStatement breakStatement = new B.BreakStatement(); + breakStatement.Modifier = new B.StatementModifier(negateCondition ? B.StatementModifierType.If : B.StatementModifierType.Unless, + ConvertExpression(doLoopStatement.Condition)); + w.Block.Add(breakStatement); + } + return w; + } + + public object Visit(ForeachStatement foreachStatement, object data) + { + B.ForStatement fs = new B.ForStatement(GetLexicalInfo(foreachStatement)); + fs.EndSourceLocation = GetLocation(foreachStatement.EndLocation); + fs.Iterator = ConvertExpression(foreachStatement.Expression); + fs.Declarations.Add(new B.Declaration(foreachStatement.VariableName, ConvertTypeReference(foreachStatement.TypeReference))); + fs.Block = ConvertBlock(foreachStatement.EmbeddedStatement); + return fs; + } + + public object Visit(AddHandlerStatement addHandlerStatement, object data) + { + return new B.BinaryExpression(GetLexicalInfo(addHandlerStatement), + B.BinaryOperatorType.InPlaceAddition, + ConvertExpression(addHandlerStatement.EventExpression), + ConvertExpression(addHandlerStatement.HandlerExpression)); + } + + public object Visit(RemoveHandlerStatement removeHandlerStatement, object data) + { + return new B.BinaryExpression(GetLexicalInfo(removeHandlerStatement), + B.BinaryOperatorType.InPlaceSubtraction, + ConvertExpression(removeHandlerStatement.EventExpression), + ConvertExpression(removeHandlerStatement.HandlerExpression)); + } + + public object Visit(RaiseEventStatement raiseEventStatement, object data) + { + B.MethodInvocationExpression mie = new B.MethodInvocationExpression(GetLexicalInfo(raiseEventStatement)); + mie.Target = new B.ReferenceExpression(raiseEventStatement.EventName); + ConvertExpressions(raiseEventStatement.Arguments, mie.Arguments); + return mie; + } + + public object Visit(EraseStatement eraseStatement, object data) + { + ArrayList statements = new ArrayList(); + foreach (Expression expr in eraseStatement.Expressions) { + B.Expression e = ConvertExpression(expr); + e = new B.BinaryExpression(B.BinaryOperatorType.Assign, e, new B.NullLiteralExpression()); + statements.Add(new B.ExpressionStatement(e)); + } + return statements; + } + + public object Visit(ReDimStatement reDimStatement, object data) + { + // Redim [Preserve] a(newBounds) + // without preserve: + // a = array(Type, newBounds) + // with preserve: + // ??1 = array(Type, newBounds) + // Array.Copy(a, ??1, System.Math.Min(a.Length, ??1.Length)) + // a = ??1 + ArrayList list = new ArrayList(); + foreach (InvocationExpression o in reDimStatement.ReDimClauses) { + if (o.TypeArguments != null && o.TypeArguments.Count > 0) { + AddError(o, "Type parameter are not allowed here."); + } + IdentifierExpression identifier = o.TargetObject as IdentifierExpression; + if (identifier == null) { + AddError(o, "Sorry, that expression is too complex to be resolved by the converter."); + } else { + // first we need to find out the array type + VariableResolver resolver = new VariableResolver(nameComparer); + TypeReference r = resolver.FindType(identifier.Identifier, reDimStatement); + if (r == null) { + AddError(o, "The name '" + identifier.Identifier + "' could not be resolved by the converter."); + } else if (!r.IsArrayType) { + AddError(o, identifier.Identifier + " is not an array."); + } else { + r = r.Clone(); + ArrayList bounds = new ArrayList(o.Arguments); + for (int i = 0; i < bounds.Count; i++) { + bounds[i] = Expression.AddInteger((Expression)bounds[i], 1); + } + ArrayList acps = new ArrayList(); + acps.Add(new ArrayCreationParameter(bounds)); + for (int i = 1; i < r.RankSpecifier.Length; i++) { + acps.Add(new ArrayCreationParameter(r.RankSpecifier[i])); + } + r.RankSpecifier = null; + ArrayCreateExpression ace = new ArrayCreateExpression(r, acps); + ace.StartLocation = o.StartLocation; + B.Expression expr = new B.ReferenceExpression(GetLexicalInfo(identifier), identifier.Identifier); + expr = new B.BinaryExpression(GetLexicalInfo(reDimStatement), B.BinaryOperatorType.Assign, expr, ConvertExpression(ace)); + list.Add(new B.ExpressionStatement(expr)); + } + } + } + return list; + } + + public object Visit(StatementExpression statementExpression, object data) + { + B.ExpressionStatement st = new B.ExpressionStatement(GetLexicalInfo(statementExpression)); + st.Expression = ConvertExpression(statementExpression.Expression); + return st; + } + + public object Visit(LocalVariableDeclaration lvd, object data) + { + ArrayList list = new ArrayList(); + for (int i = 0; i < lvd.Variables.Count; i++) { + B.DeclarationStatement varDecl = new B.DeclarationStatement(GetLexicalInfo(lvd)); + varDecl.Declaration = new B.Declaration(GetLexicalInfo(lvd.Variables[i]), lvd.Variables[i].Name, ConvertTypeReference(lvd.GetTypeForVariable(i))); + varDecl.Initializer = ConvertExpression(lvd.Variables[i].Initializer); + list.Add(varDecl); + } + return list; + } + + public object Visit(EmptyStatement emptyStatement, object data) + { + return null; + } + + public object Visit(ReturnStatement returnStatement, object data) + { + return new B.ReturnStatement(GetLexicalInfo(returnStatement), ConvertExpression(returnStatement.Expression), null); + } + + public object Visit(YieldStatement yieldStatement, object data) + { + ReturnStatement rs = yieldStatement.Statement as ReturnStatement; + if (rs == null) + return new B.ReturnStatement(GetLexicalInfo(yieldStatement)); + return new B.YieldStatement(GetLexicalInfo(yieldStatement), ConvertExpression(rs.Expression)); + } + + public object Visit(ThrowStatement throwStatement, object data) + { + return new B.RaiseStatement(GetLexicalInfo(throwStatement), ConvertExpression(throwStatement.Expression), null); + } + + public object Visit(IfElseStatement ifElseStatement, object data) + { + B.IfStatement ifs = new B.IfStatement(GetLexicalInfo(ifElseStatement)); + ifs.EndSourceLocation = GetLocation(ifElseStatement.EndLocation); + ifs.Condition = ConvertExpression(ifElseStatement.Condition); + ifs.TrueBlock = ConvertBlock(ifElseStatement.TrueStatement); + if (ifElseStatement.HasElseIfSections) { + // TODO: implement elseif + AddError(ifElseStatement, "ElseIfSections are not supported (because Daniel was lazy)"); + } + if (ifElseStatement.HasElseStatements) { + ifs.FalseBlock = ConvertBlock(ifElseStatement.FalseStatement); + } + return ifs; + } + + public object Visit(ElseIfSection elseIfSection, object data) + { + throw new ApplicationException("ElseIfSection visited"); + } + + B.LabelStatement MakeLabel(string name) + { + return new B.LabelStatement(lastLexicalInfo, name); + } + + public object Visit(LabelStatement labelStatement, object data) + { + return new B.LabelStatement(GetLexicalInfo(labelStatement), labelStatement.Label); + } + + public object Visit(GotoStatement gotoStatement, object data) + { + return new B.GotoStatement(GetLexicalInfo(gotoStatement), new B.ReferenceExpression(gotoStatement.Label)); + } + + public object Visit(StopStatement stopStatement, object data) + { + return new B.ExpressionStatement(MakeMethodCall("System.Diagnostics.Debugger.Break")); + } + + public object Visit(EndStatement endStatement, object data) + { + return new B.ExpressionStatement(MakeMethodCall("System.Environment.Exit", new B.IntegerLiteralExpression(0))); + } + + public object Visit(BreakStatement breakStatement, object data) + { + return new B.BreakStatement(GetLexicalInfo(breakStatement)); + } + + public object Visit(ContinueStatement continueStatement, object data) + { + return new B.ContinueStatement(GetLexicalInfo(continueStatement)); + } + + public object Visit(LockStatement lockStatement, object data) + { + return CreateMacro(lockStatement, "lock", lockStatement.EmbeddedStatement, lockStatement.LockExpression); + } + + public object Visit(UsingStatement usingStatement, object data) + { + LocalVariableDeclaration varDecl = usingStatement.ResourceAcquisition as LocalVariableDeclaration; + Expression expr; + if (varDecl != null) { + if (varDecl.Variables.Count != 1) { + AddError(usingStatement, "Only one variable can be used with the using statement."); + return null; + } + expr = new AssignmentExpression(new IdentifierExpression(varDecl.Variables[0].Name), + AssignmentOperatorType.Assign, + varDecl.Variables[0].Initializer); + } else { + StatementExpression se = usingStatement.ResourceAcquisition as StatementExpression; + if (se == null) { + AddError(usingStatement, "Expected: VariableDeclaration or StatementExpression"); + return null; + } + expr = se.Expression; + } + return CreateMacro(usingStatement, "using", usingStatement.EmbeddedStatement, expr); + } + + public object Visit(WithStatement withStatement, object data) + { + return CreateMacro(withStatement, "with", withStatement.Body, withStatement.Expression); + } + + public object Visit(OnErrorStatement onErrorStatement, object data) + { + AddError(onErrorStatement, "old VB-style exception handling is not supported."); + return null; + } + + public object Visit(ErrorStatement errorStatement, object data) + { + AddError(errorStatement, "old VB-style exception handling is not supported."); + return null; + } + + public object Visit(ResumeStatement resumeStatement, object data) + { + AddError(resumeStatement, "old VB-style exception handling is not supported."); + return null; + } + + public object Visit(TryCatchStatement tryCatchStatement, object data) + { + B.TryStatement t = new B.TryStatement(GetLexicalInfo(tryCatchStatement)); + t.EndSourceLocation = GetLocation(tryCatchStatement.EndLocation); + t.ProtectedBlock = ConvertBlock(tryCatchStatement.StatementBlock); + t.EnsureBlock = ConvertBlock(tryCatchStatement.FinallyBlock); + foreach (CatchClause clause in tryCatchStatement.CatchClauses) { + B.ExceptionHandler handler = new B.ExceptionHandler(GetLexicalInfo(clause)); + handler.Block = ConvertBlock(clause.StatementBlock); + B.TypeReference typeRef = ConvertTypeReference(clause.TypeReference); + string name = clause.VariableName; + if (typeRef != null) { + if (name == null || name.Length == 0) + name = GenerateName(); + handler.Declaration = new B.Declaration(name, typeRef); + } else { + if (name != null && name.Length > 0) + handler.Declaration = new B.Declaration(name, null); + } + t.ExceptionHandlers.Add(handler); + } + return t; + } + + public object Visit(CatchClause catchClause, object data) + { + throw new ApplicationException("CatchClause visited."); + } + + B.Statement GetLastStatement(B.Block block) + { + if (block == null || block.Statements.Count == 0) + return null; + return block.Statements[block.Statements.Count - 1]; + } + + string currentSwitchTempName; + + public object Visit(SwitchStatement switchStatement, object data) + { + // We have a problem: given is still not implemented in boo. + // So here's the if / else workaround: + string oldSwitchTempName = currentSwitchTempName; + currentSwitchTempName = GenerateName(); + ArrayList l = new ArrayList(3); + B.BinaryExpression init = new B.BinaryExpression(B.BinaryOperatorType.Assign, + new B.ReferenceExpression(currentSwitchTempName), + ConvertExpression(switchStatement.SwitchExpression)); + l.Add(new B.ExpressionStatement(init)); + B.IfStatement first = null; + B.IfStatement current = null; + B.BreakStatement bs; + for (int i = 0; i < switchStatement.SwitchSections.Count; i++) { + current = (B.IfStatement)((INode)switchStatement.SwitchSections[i]).AcceptVisitor(this, current); + if (i == 0) { + first = current; + } + bs = GetLastStatement(current.TrueBlock) as B.BreakStatement; + if (bs != null) + bs.ReplaceBy(null); + } + bs = GetLastStatement(current.FalseBlock) as B.BreakStatement; + if (bs != null) + bs.ReplaceBy(null); + + l.Add(first); + + string endSwitchName = currentSwitchTempName + "_end"; + first.Accept(new ReplaceBreakStatementsVisitor(endSwitchName)); + + FindUnneededLabelsVisitor fulv = new FindUnneededLabelsVisitor(currentSwitchTempName + "_", nameComparer); + first.Accept(fulv); + + if (fulv.NeededLabels.Contains(endSwitchName)) { + l.Add(MakeLabel(endSwitchName)); + } + + fulv.RemoveLabels(); // remove "goto case" labels that aren't needed + currentSwitchTempName = oldSwitchTempName; + return l; + } + + public object Visit(SwitchSection switchSection, object data) + { + B.IfStatement surroundingIf = (B.IfStatement)data; + bool isDefault = false; + ArrayList conditions = new ArrayList(); + ArrayList labels = new ArrayList(); + foreach (CaseLabel caseLabel in switchSection.SwitchLabels) { + if (caseLabel.IsDefault) { + isDefault = true; + } else { + if (caseLabel.BinaryOperatorType != BinaryOperatorType.None) { + AddError(caseLabel, "VB's Case Is currently not supported (Daniel's too lazy for VB stuff)"); + } else { + B.Expression expr = ConvertExpression(caseLabel.Label); + if (expr != null) { + conditions.Add(new B.BinaryExpression(B.BinaryOperatorType.Equality, + new B.ReferenceExpression(currentSwitchTempName), + expr)); + string labelName = expr.ToCodeString().GetHashCode().ToString(System.Globalization.NumberFormatInfo.InvariantInfo); + labels.Add(MakeLabel(currentSwitchTempName + "_" + labelName)); + } + } + } + } + B.IfStatement s = null; + if (conditions.Count > 0) { + s = new B.IfStatement(GetLexicalInfo(switchSection)); + if (surroundingIf != null) { + s.FalseBlock = surroundingIf.FalseBlock; + surroundingIf.FalseBlock = new B.Block(); + surroundingIf.FalseBlock.Add(s); + } + s.TrueBlock = new B.Block(); + foreach (B.Statement stmt in labels) { + s.TrueBlock.Add(stmt); + } + B.Expression combined = (B.Expression)conditions[0]; + for (int i = 1; i < conditions.Count; i++) { + combined = new B.BinaryExpression(B.BinaryOperatorType.Or, combined, (B.Expression)conditions[i]); + } + s.Condition = combined; + foreach (Statement node in switchSection.Children) { + AddToBlock(node, s.TrueBlock); + } + } + if (s == null) + s = surroundingIf; + if (isDefault) { + if (s.FalseBlock == null) + s.FalseBlock = new B.Block(); + s.FalseBlock.Add(MakeLabel(currentSwitchTempName + "_default")); + foreach (Statement node in switchSection.Children) { + AddToBlock(node, s.FalseBlock); + } + } + return s; + } + + public object Visit(GotoCaseStatement gotoCaseStatement, object data) + { + if (currentSwitchTempName == null) { + AddError(gotoCaseStatement, "goto case cannot be used outside switch"); + return null; + } + string labelName; + if (gotoCaseStatement.IsDefaultCase) { + labelName = "default"; + } else { + B.Expression expr = ConvertExpression(gotoCaseStatement.Expression); + if (expr == null) return null; + labelName = expr.ToCodeString().GetHashCode().ToString(System.Globalization.NumberFormatInfo.InvariantInfo); + } + return new B.GotoStatement(GetLexicalInfo(gotoCaseStatement), + new B.ReferenceExpression(currentSwitchTempName + "_" + labelName)); + } + + public object Visit(CaseLabel caseLabel, object data) + { + throw new ApplicationException("CaseLabel was visited."); + } + } +} diff --git a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ConvertVisitorTypeMembers.cs b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ConvertVisitorTypeMembers.cs new file mode 100644 index 0000000000..b1845b3067 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ConvertVisitorTypeMembers.cs @@ -0,0 +1,324 @@ +#region license +// Copyright (c) 2005, Daniel Grunwald (daniel@danielgrunwald.de) +// All rights reserved. +// +// NRefactoryToBoo is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// NRefactoryToBoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with NRefactoryToBoo; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#endregion + +using System; +using System.Collections.Generic; +using ICSharpCode.NRefactory.Parser; +using ICSharpCode.NRefactory.Parser.AST; +using Boo.Lang.Compiler; +using B = Boo.Lang.Compiler.Ast; + +namespace NRefactoryToBooConverter +{ + partial class ConvertVisitor + { + public object Visit(FieldDeclaration fieldDeclaration, object data) + { + for (int i = 0; i < fieldDeclaration.Fields.Count; i++) { + ConvertField(fieldDeclaration.GetTypeForField(i), fieldDeclaration.Fields[i], fieldDeclaration); + } + return null; + } + + public object Visit(VariableDeclaration variableDeclaration, object data) + { + throw new ApplicationException("Visited VariableDeclaration."); + } + + void ConvertField(TypeReference typeRef, VariableDeclaration variable, FieldDeclaration fieldDeclaration) + { + B.TypeMember m; + if (currentType is B.EnumDefinition) { + if (variable.Initializer.IsNull) { + m = new B.EnumMember(GetLexicalInfo(fieldDeclaration)); + } else { + PrimitiveExpression p = variable.Initializer as PrimitiveExpression; + if (p == null || !(p.Value is int)) { + AddError(fieldDeclaration, "enum member initializer must be integer value"); + return; + } + m = new B.EnumMember(GetLexicalInfo(fieldDeclaration), new B.IntegerLiteralExpression((int)p.Value)); + } + } else { + m = new B.Field(GetLexicalInfo(fieldDeclaration), ConvertTypeReference(typeRef), ConvertExpression(variable.Initializer)); + m.Modifiers = ConvertModifier(fieldDeclaration, B.TypeMemberModifiers.Private); + } + m.Name = variable.Name; + ConvertAttributes(fieldDeclaration.Attributes, m.Attributes); + currentType.Members.Add(m); + } + + B.Block ConvertMethodBlock(BlockStatement block) + { + B.Block b = ConvertBlock(block); + RenameLocalsVisitor.RenameLocals(b, nameComparer); + return b; + } + + B.Method entryPointMethod; + + public object Visit(MethodDeclaration methodDeclaration, object data) + { + B.Method m = new B.Method(GetLexicalInfo(methodDeclaration)); + m.Name = methodDeclaration.Name; + m.Modifiers = ConvertModifier(methodDeclaration, B.TypeMemberModifiers.Private); + ConvertAttributes(methodDeclaration.Attributes, m.Attributes); + currentType.Members.Add(m); + if (methodDeclaration.HandlesClause.Count > 0) { + // TODO: Convert handles clauses to [Handles] attribute + AddError(methodDeclaration, "Handles-clause is not supported."); + } + if (methodDeclaration.ImplementsClause.Count > 0) { + AddError(methodDeclaration, "Explicit interface implementation is not supported."); + } + if (methodDeclaration.Templates.Count > 0) { + AddError(methodDeclaration, "Declaring generic methods is not supported."); + } + ConvertParameters(methodDeclaration.Parameters, m.Parameters); + m.EndSourceLocation = GetEndLocation((INode)methodDeclaration.Body ?? methodDeclaration); + m.ReturnType = ConvertTypeReference(methodDeclaration.TypeReference); + m.Body = ConvertMethodBlock(methodDeclaration.Body); + if (m.Name == "Main" && m.IsStatic && m.Parameters.Count <= 1 && + (methodDeclaration.TypeReference.SystemType == "System.Void" || methodDeclaration.TypeReference.SystemType == "System.Int32")) + { + entryPointMethod = m; + } + return m; + } + + + public object Visit(ConstructorDeclaration constructorDeclaration, object data) + { + B.Constructor m = new B.Constructor(GetLexicalInfo(constructorDeclaration)); + m.Modifiers = ConvertModifier(constructorDeclaration, B.TypeMemberModifiers.Private); + ConvertAttributes(constructorDeclaration.Attributes, m.Attributes); + currentType.Members.Add(m); + ConvertParameters(constructorDeclaration.Parameters, m.Parameters); + m.EndSourceLocation = GetEndLocation((INode)constructorDeclaration.Body ?? constructorDeclaration); + m.Body = ConvertMethodBlock(constructorDeclaration.Body); + ConstructorInitializer ci = constructorDeclaration.ConstructorInitializer; + if (ci != null && !ci.IsNull) { + B.Expression initializerBase; + if (ci.ConstructorInitializerType == ConstructorInitializerType.Base) + initializerBase = new B.SuperLiteralExpression(); + else + initializerBase = new B.SelfLiteralExpression(); + B.MethodInvocationExpression initializer = new B.MethodInvocationExpression(initializerBase); + ConvertExpressions(ci.Arguments, initializer.Arguments); + m.Body.Insert(0, new B.ExpressionStatement(initializer)); + } + return m; + } + + public object Visit(DestructorDeclaration destructorDeclaration, object data) + { + B.Destructor m = new B.Destructor(GetLexicalInfo(destructorDeclaration)); + ConvertAttributes(destructorDeclaration.Attributes, m.Attributes); + currentType.Members.Add(m); + m.EndSourceLocation = GetLocation(destructorDeclaration.EndLocation); + m.Body = ConvertMethodBlock(destructorDeclaration.Body); + return m; + } + + void ConvertParameters(List input, B.ParameterDeclarationCollection output) + { + bool isParams = false; + foreach (ParameterDeclarationExpression pde in input) { + B.ParameterDeclaration para = ConvertParameter(pde, out isParams); + if (para != null) + output.Add(para); + } + output.VariableNumber = isParams; + } + + B.ParameterDeclaration ConvertParameter(ParameterDeclarationExpression pde, out bool isParams) + { + B.ParameterDeclaration para = new B.ParameterDeclaration(pde.ParameterName, ConvertTypeReference(pde.TypeReference)); + if ((pde.ParamModifier & ParamModifier.Optional) != 0) { + AddError(pde, "Optional parameters are not supported."); + } + if ((pde.ParamModifier & ParamModifier.Out) != 0) { + para.Modifiers |= B.ParameterModifiers.Ref; + } + if ((pde.ParamModifier & ParamModifier.Ref) != 0) { + para.Modifiers |= B.ParameterModifiers.Ref; + } + isParams = (pde.ParamModifier & ParamModifier.Params) != 0; + ConvertAttributes(pde.Attributes, para.Attributes); + return para; + } + + public object Visit(ParameterDeclarationExpression parameterDeclarationExpression, object data) + { + bool tmp; + return ConvertParameter(parameterDeclarationExpression, out tmp); + } + + public object Visit(PropertyDeclaration propertyDeclaration, object data) + { + B.Property m = new B.Property(GetLexicalInfo(propertyDeclaration)); + m.Name = propertyDeclaration.Name; + m.Modifiers = ConvertModifier(propertyDeclaration, B.TypeMemberModifiers.Private); + ConvertAttributes(propertyDeclaration.Attributes, m.Attributes); + currentType.Members.Add(m); + ConvertParameters(propertyDeclaration.Parameters, m.Parameters); + m.EndSourceLocation = GetLocation(propertyDeclaration.EndLocation); + m.Type = ConvertTypeReference(propertyDeclaration.TypeReference); + if (propertyDeclaration.ImplementsClause.Count > 0) { + AddError(propertyDeclaration, "Explicit interface implementation is not supported."); + } + if (!propertyDeclaration.IsWriteOnly) { + m.Getter = new B.Method(GetLexicalInfo(propertyDeclaration.GetRegion)); + if (propertyDeclaration.GetRegion != null) { + ConvertAttributes(propertyDeclaration.GetRegion.Attributes, m.Getter.Attributes); + m.Modifiers = ConvertModifier(propertyDeclaration.GetRegion, m.Visibility); + m.Getter.Body = ConvertMethodBlock(propertyDeclaration.GetRegion.Block); + m.Getter.ReturnType = m.Type; + } + } + if (!propertyDeclaration.IsReadOnly) { + m.Setter = new B.Method(GetLexicalInfo(propertyDeclaration.SetRegion)); + if (propertyDeclaration.SetRegion != null) { + ConvertAttributes(propertyDeclaration.SetRegion.Attributes, m.Setter.Attributes); + m.Modifiers = ConvertModifier(propertyDeclaration.SetRegion, m.Visibility); + m.Setter.Body = ConvertMethodBlock(propertyDeclaration.SetRegion.Block); + } + } + return m; + } + + public const string DefaultIndexerName = "Indexer"; + + public object Visit(IndexerDeclaration indexerDeclaration, object data) + { + indexerDeclaration.Modifier |= Modifier.Default; + + B.Property m = new B.Property(GetLexicalInfo(indexerDeclaration)); + m.Name = DefaultIndexerName; + m.Modifiers = ConvertModifier(indexerDeclaration, B.TypeMemberModifiers.Private); + ConvertAttributes(indexerDeclaration.Attributes, m.Attributes); + currentType.Members.Add(m); + ConvertParameters(indexerDeclaration.Parameters, m.Parameters); + m.EndSourceLocation = GetLocation(indexerDeclaration.EndLocation); + m.Type = ConvertTypeReference(indexerDeclaration.TypeReference); + if (!indexerDeclaration.IsWriteOnly) { + m.Getter = new B.Method(GetLexicalInfo(indexerDeclaration.GetRegion)); + if (indexerDeclaration.GetRegion != null) { + ConvertAttributes(indexerDeclaration.GetRegion.Attributes, m.Getter.Attributes); + m.Modifiers = ConvertModifier(indexerDeclaration.GetRegion, m.Visibility); + m.Getter.Body = ConvertMethodBlock(indexerDeclaration.GetRegion.Block); + m.Getter.ReturnType = m.Type; + } + } + if (!indexerDeclaration.IsReadOnly) { + m.Setter = new B.Method(GetLexicalInfo(indexerDeclaration.SetRegion)); + if (indexerDeclaration.SetRegion != null) { + ConvertAttributes(indexerDeclaration.SetRegion.Attributes, m.Setter.Attributes); + m.Modifiers = ConvertModifier(indexerDeclaration.SetRegion, m.Visibility); + m.Setter.Body = ConvertMethodBlock(indexerDeclaration.SetRegion.Block); + } + } + return m; + } + + public object Visit(PropertyGetRegion propertyGetRegion, object data) + { + throw new ApplicationException("PropertyGetRegion visited."); + } + + public object Visit(PropertySetRegion propertySetRegion, object data) + { + throw new ApplicationException("PropertySetRegion visited."); + } + + public object Visit(EventDeclaration eventDeclaration, object data) + { + B.Event m = new B.Event(GetLexicalInfo(eventDeclaration)); + if (eventDeclaration.Name == null || eventDeclaration.Name.Length == 0) { + m.Name = eventDeclaration.VariableDeclarators[0].Name; + } else { + m.Name = eventDeclaration.Name; + } + m.Modifiers = ConvertModifier(eventDeclaration, B.TypeMemberModifiers.Private); + ConvertAttributes(eventDeclaration.Attributes, m.Attributes); + currentType.Members.Add(m); + m.EndSourceLocation = GetLocation(eventDeclaration.EndLocation); + m.Type = ConvertTypeReference(eventDeclaration.TypeReference); + if (eventDeclaration.ImplementsClause.Count > 0) { + AddError(eventDeclaration, "Explicit interface implementation is not supported."); + } + if (eventDeclaration.Parameters.Count > 0) { + AddError(eventDeclaration, "Events with parameters are not supported."); + } + if (eventDeclaration.VariableDeclarators.Count > 1) { + AddError(eventDeclaration, "You can only define one event per line."); + } + if (eventDeclaration.HasAddRegion) { + m.Add = new B.Method(GetLexicalInfo(eventDeclaration.AddRegion)); + ConvertAttributes(eventDeclaration.AddRegion.Attributes, m.Add.Attributes); + m.Modifiers = ConvertModifier(eventDeclaration.AddRegion, m.Visibility); + m.Add.Body = ConvertMethodBlock(eventDeclaration.AddRegion.Block); + } + if (eventDeclaration.HasRemoveRegion) { + m.Remove = new B.Method(GetLexicalInfo(eventDeclaration.RemoveRegion)); + ConvertAttributes(eventDeclaration.RemoveRegion.Attributes, m.Remove.Attributes); + m.Modifiers = ConvertModifier(eventDeclaration.RemoveRegion, m.Visibility); + m.Remove.Body = ConvertMethodBlock(eventDeclaration.RemoveRegion.Block); + } + if (eventDeclaration.HasRaiseRegion) { + m.Raise = new B.Method(GetLexicalInfo(eventDeclaration.RaiseRegion)); + ConvertAttributes(eventDeclaration.RaiseRegion.Attributes, m.Raise.Attributes); + m.Modifiers = ConvertModifier(eventDeclaration.RaiseRegion, m.Visibility); + m.Raise.Body = ConvertMethodBlock(eventDeclaration.RaiseRegion.Block); + } + return m; + } + + public object Visit(EventAddRegion eventAddRegion, object data) + { + throw new ApplicationException("EventAddRegion visited."); + } + + public object Visit(EventRemoveRegion eventRemoveRegion, object data) + { + throw new ApplicationException("EventRemoveRegion visited."); + } + + public object Visit(EventRaiseRegion eventRaiseRegion, object data) + { + throw new ApplicationException("EventRaiseRegion visited."); + } + + public object Visit(ConstructorInitializer constructorInitializer, object data) + { + throw new ApplicationException("ConstructorInitializer visited."); + } + + public object Visit(OperatorDeclaration operatorDeclaration, object data) + { + AddError(operatorDeclaration, "Declaring operators is not supported (BOO-223)."); + return null; + } + + public object Visit(DeclareDeclaration declareDeclaration, object data) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/Converter.cs b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/Converter.cs new file mode 100644 index 0000000000..fec1981c20 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/Converter.cs @@ -0,0 +1,51 @@ +#region license +// Copyright (c) 2005, Daniel Grunwald (daniel@danielgrunwald.de) +// All rights reserved. +// +// NRefactoryToBoo is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// NRefactoryToBoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with NRefactoryToBoo; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#endregion + +using System; +using NR = ICSharpCode.NRefactory.Parser.AST; +using Boo.Lang.Compiler; +using Boo.Lang.Compiler.Ast; + +namespace NRefactoryToBooConverter +{ + /// + /// Class with static conversion methods. + /// + public static class Converter + { + public static Module Convert(NR.CompilationUnit cu, ConverterSettings settings) + { + if (cu == null) + throw new ArgumentNullException("cu"); + if (settings == null) + throw new ArgumentNullException("settings"); + cu.AcceptVisitor(new RefactoryVisitor(), null); + return (Module)cu.AcceptVisitor(new ConvertVisitor(settings), null); + } + + public static Expression Convert(NR.Expression expression, ConverterSettings settings) + { + if (expression == null) + throw new ArgumentNullException("expression"); + if (settings == null) + throw new ArgumentNullException("settings"); + return (Expression)expression.AcceptVisitor(new ConvertVisitor(settings), null); + } + } +} diff --git a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ConverterSettings.cs b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ConverterSettings.cs new file mode 100644 index 0000000000..59d58858da --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ConverterSettings.cs @@ -0,0 +1,105 @@ +#region license +// Copyright (c) 2005, Daniel Grunwald (daniel@danielgrunwald.de) +// All rights reserved. +// +// NRefactoryToBoo is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// NRefactoryToBoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with NRefactoryToBoo; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#endregion + +using System; +using Boo.Lang.Compiler; + +namespace NRefactoryToBooConverter +{ + public sealed class ConverterSettings + { + CompilerErrorCollection errors; + CompilerWarningCollection warnings; + string fileName; + StringComparer nameComparer; + + public const string DefaultNameGenerationPrefix = "converterGeneratedName"; + public string NameGenerationPrefix = DefaultNameGenerationPrefix; + public bool SimplifyTypeNames = true; + + static StringComparer GetComparer(string fileName) + { + if (System.IO.Path.GetExtension(fileName).ToLower() == ".vb") + return StringComparer.InvariantCultureIgnoreCase; + else + return StringComparer.InvariantCulture; + } + + public bool IsVisualBasic { + get { + return System.IO.Path.GetExtension(fileName).ToLower() == ".vb"; + } + } + + public ConverterSettings(string fileName) + : this(fileName, GetComparer(fileName)) + { + } + + public ConverterSettings(string fileName, StringComparer nameComparer) + : this(fileName, nameComparer, new CompilerErrorCollection(), new CompilerWarningCollection()) + { + } + + public ConverterSettings(string fileName, CompilerErrorCollection errors, CompilerWarningCollection warnings) + : this(fileName, GetComparer(fileName), errors, warnings) + { + } + + public ConverterSettings(string fileName, StringComparer nameComparer, CompilerErrorCollection errors, CompilerWarningCollection warnings) + { + if (fileName == null) + throw new ArgumentNullException("fileName"); + if (nameComparer == null) + throw new ArgumentNullException("nameComparer"); + if (errors == null) + throw new ArgumentNullException("errors"); + if (warnings == null) + throw new ArgumentNullException("warnings"); + this.errors = errors; + this.warnings = warnings; + this.fileName = fileName; + this.nameComparer = nameComparer; + } + + public CompilerErrorCollection Errors { + get { + return errors; + } + } + + public CompilerWarningCollection Warnings { + get { + return warnings; + } + } + + public string FileName { + get { + return fileName; + } + } + + public StringComparer NameComparer { + get { + return nameComparer; + } + } + } +} diff --git a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/FindUnneededLabelsVisitor.cs b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/FindUnneededLabelsVisitor.cs new file mode 100644 index 0000000000..59cc6d0fa4 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/FindUnneededLabelsVisitor.cs @@ -0,0 +1,102 @@ +#region license +// Copyright (c) 2005, Daniel Grunwald (daniel@danielgrunwald.de) +// All rights reserved. +// +// NRefactoryToBoo is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// NRefactoryToBoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with NRefactoryToBoo; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#endregion + +using System; +using System.Collections.Generic; +using Boo.Lang.Compiler; +using Boo.Lang.Compiler.Ast; +using Boo.Lang.Compiler.Ast.Visitors; + +namespace NRefactoryToBooConverter +{ + /// + /// This visitor finds label statements that have no matching goto statements. + /// + public class FindUnneededLabelsVisitor : DepthFirstVisitor + { + string prefix; + StringComparer nameComparer; + + /// + /// Remove only those unneeded labels that start with . + /// Use null to remove all unneeded labels. + /// + public FindUnneededLabelsVisitor(string prefix, StringComparer nameComparer) + { + this.prefix = prefix; + this.nameComparer = nameComparer; + } + + List unneededLabels = new List(); + List neededLabels = new List(); + + public List NeededLabels { + get { + return neededLabels; + } + } + + public List UnneededLabels { + get { + return unneededLabels; + } + } + + /// + /// Removes all unneeded labels that have been found from the AST. + /// + public void RemoveLabels() + { + foreach (LabelStatement l in unneededLabels) { + l.ReplaceBy(null); + } + unneededLabels.Clear(); + neededLabels.Clear(); + } + + bool MatchName(string name) + { + if (prefix == null) + return true; + if (name.Length < prefix.Length) + return false; + return nameComparer.Equals(prefix, name.Substring(0, prefix.Length)); + } + + public override void OnLabelStatement(LabelStatement node) + { + string name = node.Name; + if (!MatchName(name)) return; + if (neededLabels.Contains(name)) return; + unneededLabels.Add(node); + } + + public override void OnGotoStatement(GotoStatement node) + { + string name = node.Label.Name; + if (!MatchName(name)) return; + if (neededLabels.Contains(name)) return; + neededLabels.Add(name); + for (int i = 0; i < unneededLabels.Count; i++) { + if (unneededLabels[i].Name == name) + unneededLabels.RemoveAt(i--); + } + } + } +} diff --git a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/NRefactoryToBooConverter.csproj b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/NRefactoryToBooConverter.csproj new file mode 100644 index 0000000000..099902a839 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/NRefactoryToBooConverter.csproj @@ -0,0 +1,51 @@ + + + Library + NRefactoryToBooConverter + NRefactoryToBooConverter + Debug + AnyCPU + {DBCF20A1-BA13-4582-BFA9-74DE4D987B73} + + + bin\Debug\ + false + DEBUG;TRACE + + + bin\Release\ + true + TRACE + + + + + + + ..\..\RequiredLibraries\Boo.Lang.Compiler.dll + False + + + ..\..\RequiredLibraries\Boo.Lang.dll + False + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/Parser.cs b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/Parser.cs new file mode 100644 index 0000000000..d142cc780d --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/Parser.cs @@ -0,0 +1,90 @@ +#region license +// Copyright (c) 2005, Daniel Grunwald (daniel@danielgrunwald.de) +// All rights reserved. +// +// NRefactoryToBoo is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// NRefactoryToBoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with NRefactoryToBoo; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#endregion + +using System; +using System.Collections.Generic; +using System.IO; +using Boo.Lang.Compiler; +using Boo.Lang.Compiler.Ast; +using ICSharpCode.NRefactory.Parser; + +namespace NRefactoryToBooConverter +{ + /// + /// Class with static methods to parse C# and VB code. + /// + public static class Parser + { + public static Module ParseModule(CompileUnit cu, TextReader input, ConverterSettings settings) + { + IList specials; + return ParseModule(cu, input, settings, out specials); + } + + public static Module ParseModule(CompileUnit cu, TextReader input, ConverterSettings settings, out IList specials) + { + if (cu == null) + throw new ArgumentNullException("cu"); + if (input == null) + throw new ArgumentNullException("input"); + if (settings == null) + throw new ArgumentNullException("settings"); + IParser parser = ParserFactory.CreateParser(settings.IsVisualBasic ? SupportedLanguage.VBNet : SupportedLanguage.CSharp, input); + ErrorTrap errorTrap = new ErrorTrap(settings); + parser.Errors.SemErr = errorTrap.DefaultCodeError; + parser.Errors.SynErr = errorTrap.DefaultCodeError; + parser.Errors.Error = errorTrap.DefaultMsgError; + parser.Parse(); + specials = parser.Lexer.SpecialTracker.CurrentSpecials; + // abort when file has errors + if (errorTrap.count > 0) + return null; + Module m = Converter.Convert(parser.CompilationUnit, settings); + if (m != null && cu != null) { + cu.Modules.Add(m); + } + return m; + } + + internal class ErrorTrap + { + CompilerErrorCollection errors; + string fileName; + internal int count; + + internal ErrorTrap(ConverterSettings settings) + { + this.errors = settings.Errors; + this.fileName = settings.FileName; + } + + internal void DefaultCodeError(int line, int col, int n) + { + errors.Add(new CompilerError(new LexicalInfo(fileName, line, col), "Error number " + n)); + count++; + } + + internal void DefaultMsgError(int line, int col, string s) + { + errors.Add(new CompilerError(new LexicalInfo(fileName, line, col), s)); + count++; + } + } + } +} diff --git a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/RefactoryVisitor.cs b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/RefactoryVisitor.cs new file mode 100644 index 0000000000..869dbbb685 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/RefactoryVisitor.cs @@ -0,0 +1,42 @@ +#region license +// Copyright (c) 2005, Daniel Grunwald (daniel@danielgrunwald.de) +// All rights reserved. +// +// NRefactoryToBoo is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// NRefactoryToBoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with NRefactoryToBoo; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#endregion + +using System; +using ICSharpCode.NRefactory.Parser; +using ICSharpCode.NRefactory.Parser.AST; + +namespace NRefactoryToBooConverter +{ + /// + /// Visitor that prepares the conversion by converting source-language specific constructs + /// into "better suited" constructs. + /// + /// + /// ForStatements of the form "for(int i = Start; i < End; i += Step)" are + /// converted to "For i As Integer = Start To End Step Step" (VB-Style) which has the better-matching + /// Boo representation of "for i as int in range(Start, End, Step):" + /// + public class RefactoryVisitor : CSharpToVBNetConvertVisitor + { + public RefactoryVisitor() + { + base.RenameConflictingFieldNames = false; // do not rename fields to VB-style + } + } +} diff --git a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/RenameLocalsVisitor.cs b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/RenameLocalsVisitor.cs new file mode 100644 index 0000000000..8ae07e532b --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/RenameLocalsVisitor.cs @@ -0,0 +1,158 @@ +#region license +// Copyright (c) 2005, Daniel Grunwald (daniel@danielgrunwald.de) +// All rights reserved. +// +// NRefactoryToBoo is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// NRefactoryToBoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with NRefactoryToBoo; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#endregion + +using System; +using System.Collections.Generic; +using Boo.Lang.Compiler; +using Boo.Lang.Compiler.Ast; +using Boo.Lang.Compiler.Ast.Visitors; + +namespace NRefactoryToBooConverter +{ + public sealed class RenameLocalsVisitor : DepthFirstVisitor + { + public static void RenameLocals(Block block, StringComparer nameComparer) + { + FindVariableDeclarationsVisitor fvdv = new FindVariableDeclarationsVisitor(); + block.Accept(fvdv); + List list = new List(); + foreach (DeclarationStatement decl in fvdv.Declarations) { + DeclarationStatement conflict = null; + int conflictIndex = -1; + for (int i = 0; i < list.Count; i++) { + if (nameComparer.Equals(list[i].Declaration.Name, decl.Declaration.Name)) { + conflict = list[i]; + conflictIndex = i; + break; + } + } + if (conflict == null) { + list.Add(decl); + } else { + // Handle conflict: try if "moveup" would be sufficient + if (IsSameType(decl.Declaration.Type, conflict.Declaration.Type, nameComparer)) { + // create declaration at beginning of class and + // replace decl & conflict by assignment + DeclarationStatement newDecl = new DeclarationStatement(conflict.LexicalInfo); + newDecl.Declaration = new Declaration(conflict.Declaration.LexicalInfo, conflict.Declaration.Name, conflict.Declaration.Type); + block.Insert(0, newDecl); + ReplaceWithInitializer(decl); + ReplaceWithInitializer(conflict); + list[conflictIndex] = newDecl; + } else { + string newName = FindFreeName(decl.Declaration.Name, list, fvdv.Declarations, nameComparer); + decl.ParentNode.Accept(new RenameLocalsVisitor(decl.Declaration.Name, newName, nameComparer)); + decl.Declaration.Name = newName; + } + } + } + } + + static string FindFreeName(string baseName, List list1, List list2, StringComparer nameComparer) + { + string tmp = baseName + "__"; + for (int i = 2;; i++) { + string tryName = tmp + i.ToString(System.Globalization.NumberFormatInfo.InvariantInfo); + bool found = false; + foreach (DeclarationStatement d in list1) { + if (nameComparer.Equals(d.Declaration.Name, tryName)) { + found = true; + break; + } + } + if (found) continue; + foreach (DeclarationStatement d in list2) { + if (nameComparer.Equals(d.Declaration.Name, tryName)) { + found = true; + break; + } + } + if (!found) + return tryName; + } + } + + static void ReplaceWithInitializer(DeclarationStatement decl) + { + if (decl.Initializer == null) { + decl.ReplaceBy(null); + } else { + ExpressionStatement statement = new ExpressionStatement(decl.LexicalInfo); + statement.Expression = new BinaryExpression(decl.LexicalInfo, BinaryOperatorType.Assign, + new ReferenceExpression(decl.Declaration.LexicalInfo, decl.Declaration.Name), + decl.Initializer); + decl.ReplaceBy(statement); + } + } + + static bool IsSameType(TypeReference a, TypeReference b, StringComparer nameComparer) + { + ArrayTypeReference arr1 = a as ArrayTypeReference; + ArrayTypeReference arr2 = b as ArrayTypeReference; + SimpleTypeReference s1 = a as SimpleTypeReference; + SimpleTypeReference s2 = b as SimpleTypeReference; + if (arr1 != null && arr2 != null) { + if (arr1.Rank.Value != arr2.Rank.Value) + return false; + return IsSameType(arr1.ElementType, arr2.ElementType, nameComparer); + } else if (s1 != null && s2 != null) { + return nameComparer.Equals(s1.Name, s2.Name); + } else { + return false; + } + } + + string oldName, newName; + StringComparer nameComparer; + + private RenameLocalsVisitor(string oldName, string newName, StringComparer nameComparer) + { + this.oldName = oldName; + this.newName = newName; + this.nameComparer = nameComparer; + } + + public override void OnReferenceExpression(ReferenceExpression node) + { + if (nameComparer.Equals(node.Name, oldName)) { + node.Name = newName; + } + } + } + + public class FindVariableDeclarationsVisitor : DepthFirstVisitor + { + List declarations = new List(); + + public List Declarations { + get { + return declarations; + } + } + + public override void OnCallableDefinition(CallableDefinition node) { } + public override void OnCallableBlockExpression(CallableBlockExpression node) { } + + public override void OnDeclarationStatement(DeclarationStatement node) + { + declarations.Add(node); + base.OnDeclarationStatement(node); + } + } +} diff --git a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ReplaceBreakStatementsVisitor.cs b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ReplaceBreakStatementsVisitor.cs new file mode 100644 index 0000000000..62dc04bfdf --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ReplaceBreakStatementsVisitor.cs @@ -0,0 +1,52 @@ +#region license +// Copyright (c) 2005, Daniel Grunwald (daniel@danielgrunwald.de) +// All rights reserved. +// +// NRefactoryToBoo is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// NRefactoryToBoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with NRefactoryToBoo; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#endregion + +using System; +using System.Collections.Generic; +using Boo.Lang.Compiler; +using Boo.Lang.Compiler.Ast; +using Boo.Lang.Compiler.Ast.Visitors; + +namespace NRefactoryToBooConverter +{ + public class ReplaceBreakStatementsVisitor : DepthFirstVisitor + { + string label; + + public ReplaceBreakStatementsVisitor(string label) + { + this.label = label; + } + + public override void OnGivenStatement(GivenStatement node) { } + + public override void OnForStatement(ForStatement node) { } + + public override void OnWhileStatement(WhileStatement node) { } + + public override void OnUnlessStatement(UnlessStatement node) { } + + public override void OnBreakStatement(BreakStatement node) + { + GotoStatement gotoStatement = new GotoStatement(node.LexicalInfo); + gotoStatement.Label = new ReferenceExpression(node.LexicalInfo, label); + node.ReplaceBy(gotoStatement); + } + } +} diff --git a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/VariableResolver.cs b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/VariableResolver.cs new file mode 100644 index 0000000000..95183d5d25 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/VariableResolver.cs @@ -0,0 +1,59 @@ +#region license +// Copyright (c) 2005, Daniel Grunwald (daniel@danielgrunwald.de) +// All rights reserved. +// +// NRefactoryToBoo is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// NRefactoryToBoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with NRefactoryToBoo; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#endregion + +using System; +using System.Collections; +using System.Collections.Generic; +using ICSharpCode.NRefactory.Parser; +using ICSharpCode.NRefactory.Parser.AST; + +namespace NRefactoryToBooConverter +{ + /// + /// This class tries to find out the type of an identifier by looking at the NRefactory AST. + /// The possibilities inside the parser are very limited, we can only + /// search for local variables and fields. + /// + public class VariableResolver + { + StringComparer nameComparer; + + public VariableResolver(StringComparer nameComparer) + { + this.nameComparer = nameComparer; + } + + public TypeReference FindType(string name, Statement currentStatement) + { + INode node = currentStatement; + while ((node = node.Parent) != null) { + foreach (INode childNode in node.Children) { + LocalVariableDeclaration varDecl = childNode as LocalVariableDeclaration; + if (varDecl != null) { + foreach (VariableDeclaration var in varDecl.Variables) { + if (nameComparer.Equals(var.Name, name)) + return var.TypeReference; + } + } + } + } + return null; + } + } +} diff --git a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Test/ComplexTests.cs b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Test/ComplexTests.cs new file mode 100644 index 0000000000..c78fbd1dbd --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Test/ComplexTests.cs @@ -0,0 +1,51 @@ +#region license +// Copyright (c) 2005, Daniel Grunwald (daniel@danielgrunwald.de) +// All rights reserved. +// +// NRefactoryToBoo is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// NRefactoryToBoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with NRefactoryToBoo; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#endregion + +using System; +using NUnit.Framework; + +namespace NRefactoryToBooConverter.Tests +{ + [TestFixture] + public class ComplexTests : TestHelper + { + [Test] + public void MovingLocals() + { + TestInClass("public void Run() { if (a) { int b = 1; } else { int b = 2; } }", + "public final def Run() as System.Void:\n" + + "\tb as System.Int32\n" + + "\tif a:\n" + + "\t\tb = 1\n" + + "\telse:\n" + + "\t\tb = 2"); + } + + [Test] + public void RenamingLocals() + { + TestInClass("public void Run() { if (a) { int b = 1; } else { double b = 2; } }", + "public final def Run() as System.Void:\n" + + "\tif a:\n" + + "\t\tb as System.Int32 = 1\n" + + "\telse:\n" + + "\t\tb__2 as System.Double = 2"); + } + } +} diff --git a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Test/ErrorTests.cs b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Test/ErrorTests.cs new file mode 100644 index 0000000000..39fb0c55c8 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Test/ErrorTests.cs @@ -0,0 +1,44 @@ +#region license +// Copyright (c) 2005, Daniel Grunwald (daniel@danielgrunwald.de) +// All rights reserved. +// +// NRefactoryToBoo is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// NRefactoryToBoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with NRefactoryToBoo; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#endregion + +using System; +using System.IO; +using Boo.Lang.Compiler; +using Boo.Lang.Compiler.Ast; +using NUnit.Framework; + +namespace NRefactoryToBooConverter.Tests +{ + /// + /// Tests for special cases that have to fail. + /// + //[TestFixture] + public class ErrorTests : TestHelper + { + /* + For the following errors are currently no checks implemented: + + enum Enumeration : WithBaseType + enum Enumeration + static class Bla : WithBaseType + static class Bla + enum Enumeration { void Main(); } // check that enums can only have fields is not implemented + */ + } +} diff --git a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Test/ExpressionTests.cs b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Test/ExpressionTests.cs new file mode 100644 index 0000000000..1cff07af64 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Test/ExpressionTests.cs @@ -0,0 +1,226 @@ +#region license +// Copyright (c) 2005, Daniel Grunwald (daniel@danielgrunwald.de) +// All rights reserved. +// +// NRefactoryToBoo is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// NRefactoryToBoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with NRefactoryToBoo; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#endregion + +using System; +using NUnit.Framework; + +namespace NRefactoryToBooConverter.Tests +{ + [TestFixture] + public class ExpressionTests : TestHelper + { + [Test] + public void Null() + { + TestExpr("null", "null"); + } + + [Test] + public void This() + { + TestExpr("this", "self"); + } + + [Test] + public void Super() + { + TestExpr("base.Member", "super.Member"); + } + + [Test] + public void Reference() + { + TestExpr("c", "c"); + } + + [Test] + public void MemberReference() + { + TestExpr("c.d", "c.d"); + } + + [Test] + public void MethodCall() + { + TestExpr("a()", "a()"); + } + + [Test] + public void MethodCallWithParameter() + { + TestExpr("a(4)", "a(4)"); + } + + [Test] + public void ObjectConstruction() + { + TestExpr("new MainClass()", "MainClass()"); + } + + [Test] + public void QualifiedConstruction() + { + TestExpr("new System.DefaultComparer()", "System.DefaultComparer()"); + } + + [Test] + public void Integer() + { + TestExpr("1", "1"); + } + + [Test] + public void Double() + { + TestExpr("1.0", "1.0"); + } + + [Test] + public void Single() + { + TestExpr("1f", "1.0F"); + } + + [Test] + public void UnaryMinus() + { + TestExpr("-(1)", "(-1)"); + } + + [Test] + public void UnaryBitNegation() + { + TestExpr("~1", "(~1)"); + } + + [Test] + public void UnaryLogicalNot() + { + TestExpr("!false", "(not false)"); + } + + [Test] + public void UnaryPlus() + { + TestExpr("+(1)", "1"); + } + + [Test] + public void PostIncrement() + { + TestExpr("i++", "(i++)"); + } + + [Test] + public void PostDecrement() + { + TestExpr("i--", "(i--)"); + } + + [Test] + public void Increment() + { + TestExpr("++i", "(++i)"); + } + + [Test] + public void Decrement() + { + TestExpr("--i", "(--i)"); + } + + [Test] + public void ArrayAccess() + { + TestExpr("arr[i]", "arr[i]"); + } + + [Test] + public void MultidimensionalArrayAccess() + { + TestExpr("arr[x,y]", "arr[x, y]"); + } + + [Test] + public void CreateArray() + { + TestExpr("new int[4]", "array(System.Int32, 4)"); + } + + [Test] + public void CreateNestedArray() + { + TestExpr("new int[4][]", "array(typeof((System.Int32)), 4)"); + } + + [Test] + public void CreateMultidimensionalArray() + { + TestExpr("new int[2, 3]", "matrix(System.Int32, (2, 3))"); + } + + [Test] + public void CreateEmptyArray() + { + TestExpr("new int[] { }", "(,)"); + } + + [Test] + public void CreateArrayWithOneElement() + { + TestExpr("new int[] { 1 }", "(1,)"); + } + + [Test] + public void CreateArrayWithTwoElements() + { + TestExpr("new int[] { 1 , 2 }", "(1, 2)"); + } + + [Test] + public void AnonymousMethod() + { + TestExpr("delegate { }", "def ():\n\tpass"); + } + + [Test] + public void AnonymousMethodWithEmptyParameterList() + { + TestExpr("delegate () { }", "def ():\n\tpass"); + } + + [Test] + public void AnonymousMethodWithParameters() + { + TestExpr("delegate (int a, string b) { }", "def (a as System.Int32, b as System.String):\n\tpass"); + } + + [Test, Ignore("ConditionalExpression does not have a boo syntax")] + public void Conditional() + { + TestExpr("a ? b : c", "a ? b : c"); + } + + [Test, Ignore("ConditionalExpression does not have a boo syntax")] + public void NullCoalescing() + { + TestExpr("a ?? b", "(a != null) ? a : b"); + } + } +} diff --git a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Test/GlobalTests.cs b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Test/GlobalTests.cs new file mode 100644 index 0000000000..c0175b253c --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Test/GlobalTests.cs @@ -0,0 +1,148 @@ +#region license +// Copyright (c) 2005, Daniel Grunwald (daniel@danielgrunwald.de) +// All rights reserved. +// +// NRefactoryToBoo is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// NRefactoryToBoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with NRefactoryToBoo; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#endregion + +using System; +using NUnit.Framework; + +namespace NRefactoryToBooConverter.Tests +{ + [TestFixture] + public class GlobalTests : TestHelper + { + [Test] + public void EmptyFile() + { + Test("", ""); + } + + [Test] + public void EmptyNamespace() + { + Test("namespace A.B {}", "namespace A.B"); + } + + [Test] + public void SimpleUsing() + { + Test("using System.Windows.Forms;", "import System.Windows.Forms"); + } + + [Test] + public void AliasUsing() + { + Test("using WinForms = System.Windows.Forms;", "import System.Windows.Forms as WinForms"); + } + + [Test] + public void UsingOutsideNamespace() + { + Test("using System.Windows.Forms;\nnamespace A.B { } ", "namespace A.B\nimport System.Windows.Forms"); + } + + [Test] + public void UsingInsideNamespace() + { + Test("namespace A.B { using System.Windows.Forms; } ", "namespace A.B\nimport System.Windows.Forms"); + } + + [Test] + public void ClassDeclaration() + { + Test("public class Test {}", "public class Test:\n\tpass"); + } + + [Test] + public void ClassDeclarationWithAttribute() + { + Test("[TestFixture] class Test {}", "[TestFixture]\ninternal class Test:\n\tpass"); + } + + [Test] + public void ClassDeclarationWithMultipleAttributes() + { + Test("[TestFixture] [OtherA] class Test {}", "[TestFixture]\n[OtherA]\ninternal class Test:\n\tpass"); + } + + [Test] + public void ClassDeclarationWithBaseType() + { + Test("public class TestException : Exception {}", "public class TestException(Exception):\n\tpass"); + } + + [Test] + public void ClassDeclarationWithMultipleBaseTypes() + { + Test("public class TestException : Exception, IDisposable {}", "public class TestException(Exception, IDisposable):\n\tpass"); + } + + [Test] + public void InnerClassDeclaration() + { + Test("public class Test { class Inner {} }", "public class Test:\n\tprivate class Inner:\n\t\tpass"); + } + + [Test] + public void InterfaceDeclaration() + { + Test("public interface Test {}", "public interface Test:\n\tpass"); + } + + [Test] + public void InterfaceDeclarationWithAttribute() + { + Test("[TestFixture] interface Test {}", "[TestFixture]\ninternal interface Test:\n\tpass"); + } + + [Test] + public void InterfaceDeclarationWithBaseType() + { + Test("public interface ExtendedDisposable : IDisposable {}", "public interface ExtendedDisposable(IDisposable):\n\tpass"); + } + + [Test] + public void EnumerationDeclaration() + { + Test("public enum Test {}", "public enum Test:\n\tpass"); + } + + [Test] + public void EnumerationDeclarationWithAttribute() + { + Test("[TestFixture] enum Test {}", "[TestFixture]\ninternal enum Test:\n\tpass"); + } + + [Test] + public void StructureDeclaration() + { + Test("public struct Test {}", "public struct Test:\n\tpass"); + } + + [Test] + public void StructureDeclarationWithAttribute() + { + Test("[TestFixture] struct Test {}", "[TestFixture]\ninternal struct Test:\n\tpass"); + } + + [Test] + public void StructureDeclarationWithBaseType() + { + Test("public struct Bla : ValueType {}", "public struct Bla(ValueType):\n\tpass"); + } + } +} diff --git a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Test/MemberTests.cs b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Test/MemberTests.cs new file mode 100644 index 0000000000..ed1b5aedb4 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Test/MemberTests.cs @@ -0,0 +1,247 @@ +#region license +// Copyright (c) 2005, Daniel Grunwald (daniel@danielgrunwald.de) +// All rights reserved. +// +// NRefactoryToBoo is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// NRefactoryToBoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with NRefactoryToBoo; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#endregion + +using System; +using NUnit.Framework; + +namespace NRefactoryToBooConverter.Tests +{ + [TestFixture] + public class MemberTests : TestHelper + { + [Test] + public void EnumerationMember() + { + Test("public enum Trool { No, Maybe, Yes }", "public enum Trool:\n\tNo\n\tMaybe\n\tYes"); + } + + [Test] + public void EnumerationMemberWithAttribute() + { + Test("public enum Trool { No, [XXX] Maybe, Yes }", "public enum Trool:\n\tNo\n\t[XXX]\n\tMaybe\n\tYes"); + } + + [Test] + public void EnumerationMemberWithValue() + { + Test("public enum Trool { No = 0, Maybe = 2, Yes = 4 }", "public enum Trool:\n\tNo = 0\n\tMaybe = 2\n\tYes = 4"); + } + + [Test] + public void Field() + { + TestInClass("MyType o;", "private o as MyType"); + } + + [Test] + public void MultipleFields() + { + TestInClass("MyType a, b, c;", "private a as MyType\nprivate b as MyType\nprivate c as MyType"); + } + + [Test] + public void PrimitiveField() + { + TestInClass("int num;", "private num as System.Int32"); + } + + [Test] + public void ArrayField() + { + TestInClass("Field[] Core;", "private Core as (Field)"); + } + + [Test] + public void FieldWithModifier() + { + TestInClass("public static int num;", "public static num as System.Int32"); + } + + [Test] + public void FullyQualifiedField() + { + TestInClass("System.IDisposable d;", "private d as System.IDisposable"); + } + + [Test] + public void FieldWithInitializer() + { + TestInClass("MyType o = null;", "private o as MyType = null"); + } + + [Test] + public void Method() + { + TestInClass("void Main() {}", "private final def Main() as System.Void:\n\tpass"); + } + + [Test] + public void MethodWithAttribute() + { + TestInClass("[Test] void Main() {}", "[Test]\nprivate final def Main() as System.Void:\n\tpass"); + } + + [Test] + public void MethodWithParameters() + { + TestInClass("void Main(int a, MyType b) {}", "private final def Main(a as System.Int32, b as MyType) as System.Void:\n\tpass"); + } + + [Test] + public void MethodWithRefParameters() + { + TestInClass("void Main(ref int a, out MyType b) {}", "private final def Main(ref a as System.Int32, ref b as MyType) as System.Void:\n\tpass"); + } + + [Test] + public void MethodWithParamsParameters() + { + TestInClass("void Main(int a, params string[] args) {}", "private final def Main(a as System.Int32, *args as (System.String)) as System.Void:\n\tpass"); + } + + [Test] + public void MethodWithReturnType() + { + TestInClass("MyType Main() {}", "private final def Main() as MyType:\n\tpass"); + } + + [Test] + public void MethodWithModifier() + { + TestInClass("public static void Run() {}", "public static def Run() as System.Void:\n\tpass"); + } + + [Test] + public void StaticMethodInStaticClass() + { + Test("public static class MainClass { public static void Run() {} }", + "public static class MainClass:\n\tpublic static def Run() as System.Void:\n\t\tpass"); + } + + [Test] + public void Constructor() + { + TestInClass("ClassName() {}", "private def constructor():\n\tpass"); + } + + [Test] + public void ConstructorWithAttribute() + { + TestInClass("[Test] ClassName() {}", "[Test]\nprivate def constructor():\n\tpass"); + } + + [Test] + public void ConstructorWithParameters() + { + TestInClass("ClassName(int a, MyType b) {}", "private def constructor(a as System.Int32, b as MyType):\n\tpass"); + } + + [Test] + public void ConstructorWithModifier() + { + TestInClass("public static ClassName() {}", "public static def constructor():\n\tpass"); + } + + [Test] + public void ConstructorWithThisCall() + { + TestInClass("public ClassName() : this(5) {}", "public def constructor():\n\tself(5)"); + } + + [Test] + public void ConstructorWithBaseCall() + { + TestInClass("public ClassName() : base(5) {}", "public def constructor():\n\tsuper(5)"); + } + + [Test] + public void Destructor() + { + TestInClass("~ClassName() {}", "def destructor():\n\tpass"); + } + + [Test] + public void DestructorWithAttribute() + { + TestInClass("[Test] ~ClassName() {}", "[Test]\ndef destructor():\n\tpass"); + } + + [Test] + public void ReadOnlyProperty() + { + TestInClass("public string Text { get { } }", "public Text as System.String:\n\tget:\n\t\tpass"); + } + + [Test] + public void WriteOnlyProperty() + { + TestInClass("public string Text { set { } }", "public Text as System.String:\n\tset:\n\t\tpass"); + } + + [Test] + public void Property() + { + TestInClass("public string Text { get {} set { } }", "public Text as System.String:\n\tget:\n\t\tpass\n\tset:\n\t\tpass"); + } + + [Test] + public void PropertyWithAttributes() + { + TestInClass("[AA] public string Text { [BB] get {} [CC] set { } }", + "[AA]\npublic Text as System.String:\n\t[BB]\n\tget:\n\t\tpass\n\t[CC]\n\tset:\n\t\tpass"); + } + + [Test] + public void ReadOnlyIndexer() + { + TestInClassWithIndexer("public string this[int index] { get { } }", "public Indexer(index as System.Int32) as System.String:\n\tget:\n\t\tpass"); + } + + [Test] + public void WriteOnlyIndexer() + { + TestInClassWithIndexer("public string this[int index] { set { } }", "public Indexer(index as System.Int32) as System.String:\n\tset:\n\t\tpass"); + } + + [Test] + public void Indexer() + { + TestInClassWithIndexer("public string this[int index] { get {} set { } }", "public Indexer(index as System.Int32) as System.String:\n\tget:\n\t\tpass\n\tset:\n\t\tpass"); + } + + [Test] + public void IndexerWithAttributes() + { + TestInClassWithIndexer("[AA] public string this[int index] { [BB] get {} [CC] set { } }", + "[AA]\npublic Indexer(index as System.Int32) as System.String:\n\t[BB]\n\tget:\n\t\tpass\n\t[CC]\n\tset:\n\t\tpass"); + } + + [Test] + public void Event() + { + TestInClass("public event EventHandler Closed;", "public event Closed as EventHandler"); + } + + [Test] + public void EventWithAttribute() + { + TestInClass("[LookHere] event EventHandler Closed;", "[LookHere]\nprivate event Closed as EventHandler"); + } + } +} diff --git a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Test/NRefactoryToBooConverter.Tests.csproj b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Test/NRefactoryToBooConverter.Tests.csproj new file mode 100644 index 0000000000..e824250723 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Test/NRefactoryToBooConverter.Tests.csproj @@ -0,0 +1,54 @@ + + + Library + NRefactoryToBooConverter.Tests + NRefactoryToBooConverter.Tests + Debug + AnyCPU + {C9DE556D-325C-4544-B29F-16A9EB7C9830} + + + bin\Debug\ + false + DEBUG;TRACE + + + bin\Release\ + true + TRACE + + + + + + + ..\..\RequiredLibraries\Boo.Lang.Compiler.dll + False + + + ..\..\RequiredLibraries\Boo.Lang.dll + False + + + + + + + + + + + + + + {DBCF20A1-BA13-4582-BFA9-74DE4D987B73} + NRefactoryToBooConverter + + + {3A9AE6AA-BC07-4A2F-972C-581E3AE2F195} + NRefactory + True + + + + \ No newline at end of file diff --git a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Test/StatementTests.cs b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Test/StatementTests.cs new file mode 100644 index 0000000000..a099ce6051 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Test/StatementTests.cs @@ -0,0 +1,223 @@ +#region license +// Copyright (c) 2005, Daniel Grunwald (daniel@danielgrunwald.de) +// All rights reserved. +// +// NRefactoryToBoo is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// NRefactoryToBoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with NRefactoryToBoo; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#endregion + +using System; +using NUnit.Framework; + +namespace NRefactoryToBooConverter.Tests +{ + [TestFixture] + public class StatementTests : TestHelper + { + [Test] + public void IfStatement() + { + TestStatement("if (a) B();", "if a:\n\tB()"); + } + + [Test] + public void IfElseStatement() + { + TestStatement("if (a) B(); else C();", "if a:\n\tB()\nelse:\n\tC()"); + } + + [Test] + public void ForLoop() + { + TestStatement("for (int i = 0; i < 10; i++) {}", "for i in range(0, 10):\n\tpass"); + } + + [Test] + public void ForLoopWithoutBody() + { + TestStatement("for (int i = 0; i < 10; i++);", "for i in range(0, 10):\n\tpass"); + } + + [Test] + public void ForLoopWithStep() + { + TestStatement("for (int i = 0; i <= 10; i += 2);", "for i in range(0, 11, 2):\n\tpass"); + } + + [Test] + public void ForLoopDecrementing() + { + TestStatement("for (int i = 10; i > 0; --i);", "for i in range(10, 0, -1):\n\tpass"); + } + + [Test] + public void ForLoopDecrementingWithStep() + { + TestStatement("for (int i = 10; i >= 0; i -= 2);", "for i in range(10, -1, -2):\n\tpass"); + } + + [Test] + public void ForLoop2() + { + TestStatement("for (i = 0; i < 10; i++) {}", "i = 0\ngoto ??1\nwhile true:\n\ti += 1\n\t:??1\n\tbreak unless (i <= 9)"); + } + + [Test] + public void ForLoopWithStep2() + { + TestStatement("for (i = 0; i <= 10; i += 2);", "i = 0\ngoto ??1\nwhile true:\n\ti += 2\n\t:??1\n\tbreak unless (i <= 10)"); + } + + [Test] + public void ForLoopDecrementing2() + { + TestStatement("for (i = 10; i > 0; --i);", "i = 10\ngoto ??1\nwhile true:\n\ti += -1\n\t:??1\n\tbreak unless (i >= 1)"); + } + + [Test] + public void AdvancedForLoop() + { + TestStatement("for (f = Open(); (next = Peek()) != -1; Process(next));", + "f = Open()\ngoto ??1\nwhile true:\n\tProcess(next)\n\t:??1\n\tbreak unless ((next = Peek()) != (-1))"); + } + + [Test] + public void WhileLoop() + { + TestStatement("while ((next = Peek()) != -1) { Process(next); }", + "while ((next = Peek()) != (-1)):\n\tProcess(next)"); + } + + [Test] + public void DoLoop() + { + TestStatement("do { ok = Next(); } while (ok);", + "while true:\n\tok = Next()\n\tbreak unless ok"); + } + + [Test] + public void ForeachLoop() + { + TestStatement("foreach (string s in list) {}", + "for s as System.String in list:\n\tpass"); + } + + [Test] + public void Using() + { + TestStatement("using (StringReader r = file.Open()) { r.ReadLine(); }", + "using (r = file.Open()):\n\tr.ReadLine()"); + } + + [Test] + public void Return() + { + TestStatement("return val;", "return val"); + } + + [Test] + public void Throw() + { + TestStatement("throw cachedException;", "raise cachedException"); + } + + [Test] + public void TryFinally() + { + TestStatement("try { Action(); } finally { CleanUp(); }", + "try:\n\tAction()\nensure:\n\tCleanUp()"); + } + + [Test] + public void TryCatch() + { + TestStatement("try { Action(); } catch { DisplayError(); }", + "try:\n\tAction()\nexcept:\n\tDisplayError()"); + } + + [Test] + public void TryCatchWithTypes() + { + TestStatement("try { Action(); }" + + "catch(FirstException ex) { DisplayError(ex); }" + + "catch(SecondException ex) { DisplayError(ex); }", + "try:\n\tAction()\n" + + "except ex as FirstException:\n\tDisplayError(ex)\n" + + "except ex as SecondException:\n\tDisplayError(ex)"); + } + + [Test] + public void Switch() + { + TestStatement("switch (var) { case 1: A1(); break; default: A3(); break; case 2: case 3: A2(); break; }", + "??1 = var\n" + + "if (??1 == 1):\n" + + "\tA1()\n" + + "else:\n" + + "\tif ((??1 == 2) or (??1 == 3)):\n" + + "\t\tA2()\n" + + "\telse:\n" + + "\t\tA3()"); + } + + [Test] + public void SwitchWithEarlyBreak() + { + TestStatement("switch (var) { case 1: if (a) break; B(); break; }", + "??1 = var\n" + + "if (??1 == 1):\n" + + "\tif a:\n" + + "\t\tgoto ??1_end\n" + + "\tB()\n" + + ":??1_end"); + } + + [Test] + public void SwitchWithGotoCase() + { + TestStatement("switch (var) { case 1: B(); goto default; default: A(); break; }", + "??1 = var\n" + + "if (??1 == 1):\n" + + "\tB()\n" + + "\tgoto ??1_default\n" + + "else:\n" + + "\t:??1_default\n" + + "\tA()"); + } + + [Test] + public void VBArrayDecl() + { + TestStatementVB("Dim A(10) As Integer", "A as (System.Int32) = array(System.Int32, 11)"); + } + + [Test] + public void RedimTest() + { + TestStatementVB("Dim A As Integer()\nRedim A(5)", "A as (System.Int32)\nA = array(System.Int32, 6)"); + } + + [Test] + public void VBMethodCall() + { + TestStatementVB("B = A(5)", "B = A(5)"); + } + + [Test] + public void VBIndexerCall() + { + TestStatementVB("Dim A As Integer()\nB = A(5)", "A as (System.Int32)\nB = A[5]"); + } + } +} diff --git a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Test/TestHelper.cs b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Test/TestHelper.cs new file mode 100644 index 0000000000..27652ae255 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Test/TestHelper.cs @@ -0,0 +1,109 @@ +#region license +// Copyright (c) 2005, Daniel Grunwald (daniel@danielgrunwald.de) +// All rights reserved. +// +// NRefactoryToBoo is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// NRefactoryToBoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with NRefactoryToBoo; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#endregion + +using System; +using System.IO; +using Boo.Lang.Compiler; +using Boo.Lang.Compiler.Ast; +using NUnit.Framework; + +namespace NRefactoryToBooConverter.Tests +{ + public class TestHelper + { + protected string Convert(string program) + { + ConverterSettings settings = new ConverterSettings("prog.cs"); + settings.SimplifyTypeNames = false; + Module module = Parser.ParseModule(new CompileUnit(), new StringReader(program), settings); + return GetStringFromModule(module, settings); + } + + protected string ConvertVB(string program) + { + ConverterSettings settings = new ConverterSettings("prog.vb"); + settings.SimplifyTypeNames = false; + Module module = Parser.ParseModule(new CompileUnit(), new StringReader(program), settings); + return GetStringFromModule(module, settings); + } + + string GetStringFromModule(Module module, ConverterSettings settings) + { + if (settings.Errors.Count > 0) { + Assert.Fail(settings.Errors.Count.ToString() + " errors: " + settings.Errors[0]); + } + if (settings.Warnings.Count > 0) { + Assert.Fail(settings.Warnings.Count.ToString() + " warnings: " + settings.Warnings[0]); + } + Assert.IsNotNull(module, "Module is null"); + string str = module.ToCodeString(); + str = str.Trim().Replace("\r", ""); + for (int i = 0; i < 5; i++) { + str = str.Replace("\n\n", "\n"); + str = str.Replace(" ", " "); + } + return str; + } + + protected void Test(string input, string output) + { + Assert.AreEqual(output.Replace("??", ConverterSettings.DefaultNameGenerationPrefix), Convert(input)); + } + + protected void TestVB(string input, string output) + { + Assert.AreEqual(output.Replace("??", ConverterSettings.DefaultNameGenerationPrefix), ConvertVB(input)); + } + + protected void TestInClass(string input, string output) + { + Test("public class ClassName {\n" + input + "\n}", "public class ClassName:\n\t" + output.Replace("\n", "\n\t")); + } + + protected void TestInClassVB(string input, string output) + { + TestVB("Public Class ClassName\n" + input + "\nEnd Class\n", "public class ClassName:\n\t" + output.Replace("\n", "\n\t")); + } + + protected void TestInClassWithIndexer(string input, string output) + { + Test("public class ClassName {\n" + input + "\n}", "[System.Reflection.DefaultMember('Indexer')]\npublic class ClassName:\n\t" + output.Replace("\n", "\n\t")); + } + + protected void TestStatement(string input, string output) + { + TestInClass("public void Method() {\n" + input + "\n}", "public final def Method() as System.Void:\n\t" + output.Replace("\n", "\n\t")); + } + + protected void TestStatementVB(string input, string output) + { + TestInClassVB("Public Sub Method()\n" + input + "\nEnd Sub", "public final def Method() as System.Void:\n\t" + output.Replace("\n", "\n\t")); + } + + protected void TestExpr(string input, string output) + { + TestStatement("a = " + input + ";", "a = " + output); + } + + protected void TestExprVB(string input, string output) + { + TestStatementVB("a = " + input, "a = " + output); + } + } +} diff --git a/src/AddIns/BackendBindings/Boo/StandaloneConverter/AssemblyInfo.cs b/src/AddIns/BackendBindings/Boo/StandaloneConverter/AssemblyInfo.cs new file mode 100644 index 0000000000..c3b8af0656 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/StandaloneConverter/AssemblyInfo.cs @@ -0,0 +1,46 @@ +#region license +// Copyright (c) 2005, Daniel Grunwald (daniel@danielgrunwald.de) +// All rights reserved. +// +// NRefactoryToBoo is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// NRefactoryToBoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with NRefactoryToBoo; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#endregion + +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following +// attributes. +// +// change them to the information which is associated with the assembly +// you compile. + +[assembly: AssemblyTitle("NRefactoryToBooConverter Executable")] +[assembly: AssemblyDescription("Converts from C# and VB.NET source files to boo source files")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Daniel Grunwald")] +[assembly: AssemblyProduct("BooBinding")] +[assembly: AssemblyCopyright("(C) 2005, Daniel Grunwald")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// You can specify all values by your own or you can build default build and revision +// numbers with the '*' character (the default): + +[assembly: AssemblyVersion(NRefactoryToBooConverter.VersionInfo.VersionNumber)] + diff --git a/src/AddIns/BackendBindings/Boo/StandaloneConverter/Main.cs b/src/AddIns/BackendBindings/Boo/StandaloneConverter/Main.cs new file mode 100644 index 0000000000..bf6b8439f4 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/StandaloneConverter/Main.cs @@ -0,0 +1,363 @@ +#region license +// Copyright (c) 2005, Daniel Grunwald (daniel@danielgrunwald.de) +// All rights reserved. +// +// NRefactoryToBoo is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// NRefactoryToBoo is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with NRefactoryToBoo; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#endregion + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using NRefactoryToBooConverter; +using Boo.Lang.Compiler; +using Boo.Lang.Compiler.Ast; + +namespace StandaloneConverter +{ + class MainClass + { + /// + /// 0 = conversion successful + /// 1 = internal error + /// 2 = invalid command line parameters + /// 3 = no command line parameters + /// 4 = conversion error + /// + public static int Main(string[] args) + { + Console.WriteLine("Standalone C# to Boo converter"); + Console.WriteLine("(C) Daniel Grunwald, 2005"); + Console.WriteLine(); + return new MainClass().Run(args); + } + + bool overwriteFiles = false; + + public int Run(string[] args) + { + try { + bool failed = false; + string outputdir = null; + List input = new List(); + for (int i = 0; i < args.Length; i++) { + string arg = args[i]; + switch (arg.ToLower()) { + case "--help": + case "-?": + case "/?": + ShowHelp(); + return 0; + case "-o": + case "--output": + outputdir = args[++i]; + break; + case "--overwrite": + case "--force": + case "-f": + overwriteFiles = true; + break; + case "--version": + Console.WriteLine("Version " + typeof(MainClass).Assembly.GetName().Version.ToString()); + return 0; + case "--noprimitivenames": + simplifyTypeNames = false; + break; + default: + if (arg.StartsWith("-")) { + Console.WriteLine("Invalid argument: " + arg); + failed = true; + } else { + input.Add(arg); + } + break; + } + } + if (failed) + return 2; + if (input.Count == 0) { + Console.WriteLine("No input(s) specified."); + Console.WriteLine("Use the parameter '--help' to display the possible command line arguments."); + return 3; + } + if (Convert(input, outputdir)) { + Console.WriteLine(); + Console.WriteLine("Conversion successful."); + return 0; + } else { + Console.WriteLine(); + Console.WriteLine("Conversion failed."); + return 4; + } + } catch (Exception ex) { + Console.WriteLine(ex); + return 1; + } + } + + void ShowHelp() + { + Console.Write(Path.GetFileName(typeof(MainClass).Assembly.Location)); + Console.WriteLine(" [-o outputdirectory] [switches] input1 input2 ..."); + Console.WriteLine(); + Console.WriteLine("An input parameter can be either a C# or VB.NET file or a directory."); + Console.WriteLine("When a directory is specified, all .cs and .vb files inside that"); + Console.WriteLine("directory are converted recursivly."); + Console.WriteLine(); + Console.WriteLine(" --output (short: -o)"); + Console.WriteLine(" Specifies the output directory to store the generated files in."); + Console.WriteLine(" When no output directory is specified, the generated files are stored"); + Console.WriteLine(" in the directory of the source files."); + Console.WriteLine(); + Console.WriteLine("Switches:"); + Console.WriteLine(" --overwrite or --force (short: -f)"); + Console.WriteLine(" Overwrite existing .boo files."); + Console.WriteLine(" --noPrimitiveNames"); + Console.WriteLine(" Use the fully type names (System.Int32) instead of the short names (int)."); + Console.WriteLine(" --help (short: -? or /?)"); + Console.WriteLine(" Shows this help text"); + } + + bool simplifyTypeNames = true; + + ConverterSettings ApplySettings(string fileName, CompilerErrorCollection errors, CompilerWarningCollection warnings) + { + ConverterSettings settings = new ConverterSettings(fileName, errors, warnings); + settings.SimplifyTypeNames = simplifyTypeNames; + return settings; + } + + bool Convert(List inputs, string outputdir) + { + bool success = true; + foreach (string input in inputs) { + if (Directory.Exists(input)) { + success &= ConvertDirectory(input, GetOutputName(outputdir, input)); + } else { + success &= ConvertFile(input, GetOutputName(outputdir, input)); + } + } + return success; + } + + string GetOutputName(string outputdir, string input) + { + return outputdir == null ? input : Path.Combine(outputdir, Path.GetFileName(input)); + } + + bool ConvertDirectory(string inputdir, string outputdir) + { + bool success = true; + foreach (string file in Directory.GetFiles(inputdir, "*.cs")) { + success &= ConvertFile(file, Path.Combine(outputdir, Path.GetFileName(file))); + } + foreach (string file in Directory.GetFiles(inputdir, "*.vb")) { + success &= ConvertFile(file, Path.Combine(outputdir, Path.GetFileName(file))); + } + foreach (string dir in Directory.GetDirectories(inputdir)) { + success &= ConvertDirectory(dir, Path.Combine(outputdir, Path.GetFileName(dir))); + } + return success; + } + + bool ConvertFile(string input, string output) + { + try { + return ConvertFileInternal(input, Path.ChangeExtension(output, ".boo")); + } catch (Exception ex) { + Console.WriteLine("Error converting " + input + ":"); + Console.WriteLine(" " + ex.Message); + return false; + } + } + + bool ConvertFileInternal(string input, string output) + { + string directory = Path.GetDirectoryName(output); + if (directory.Length > 0) { + if (!Directory.Exists(directory)) { + Directory.CreateDirectory(directory); + } + } + bool isFailed = false; + if (!overwriteFiles && File.Exists(output)) { + FailFile(ref isFailed, input, "The output file '{0}' already exists.", output); + return false; + } + try { + CompilerErrorCollection errors = new CompilerErrorCollection(); + CompilerWarningCollection warnings = new CompilerWarningCollection(); + Module module; + IList specials; + CompileUnit compileUnit = new CompileUnit(); + using (StreamReader r = OpenFile(input)) { + module = Parser.ParseModule(compileUnit, r, ApplySettings(input, errors, warnings), out specials); + } + foreach (CompilerError error in errors) { + FailFile(ref isFailed, input, error.ToString()); + } + if (isFailed) { + return false; + } + if (warnings.Count > 0) { + Console.WriteLine(input + ":"); + foreach (CompilerWarning warning in warnings) { + Console.WriteLine(" " + warning.ToString()); + } + } + using (StreamWriter w = new StreamWriter(output, false, Encoding.UTF8)) { + BooPrinterVisitorWithComments printer = new BooPrinterVisitorWithComments(specials, w); + printer.OnModule(module); + printer.Finish(); + } + } catch (Exception ex) { + FailFile(ref isFailed, input, ex); + } + return !isFailed; + } + + void FailFile(ref bool isFailed, string input, Exception ex) + { + FailFile(ref isFailed, input, "Internal error:"); + CompilerError cerr = ex as CompilerError; + if (cerr != null) + Console.WriteLine(cerr.ToString(true)); + else + Console.WriteLine(ex.ToString()); + } + + void FailFile(ref bool isFailed, string input, string message, params object[] args) + { + if (!isFailed) { + isFailed = true; + Console.WriteLine(input + " failed:"); + } + if (args.Length == 0) { + Console.WriteLine(" " + message); + } else { + Console.WriteLine(" " + message, args); + } + } + + #region Open file with encoding autodetection + StreamReader OpenFile(string fileName) + { + FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read); + if (fs.Length > 3) { + // the autodetection of StreamReader is not capable of detecting the difference + // between ISO-8859-1 and UTF-8 without BOM. + int firstByte = fs.ReadByte(); + int secondByte = fs.ReadByte(); + switch ((firstByte << 8) | secondByte) { + case 0x0000: // either UTF-32 Big Endian or a binary file; use StreamReader + case 0xfffe: // Unicode BOM (UTF-16 LE or UTF-32 LE) + case 0xfeff: // UTF-16 BE BOM + case 0xefbb: // start of UTF-8 BOM + // StreamReader autodetection works + fs.Position = 0; + return new StreamReader(fs); + default: + return AutoDetect(fs, (byte)firstByte, (byte)secondByte); + } + } else { + return new StreamReader(fs); + } + } + + StreamReader AutoDetect(FileStream fs, byte firstByte, byte secondByte) + { + int max = (int)Math.Min(fs.Length, 500000); // look at max. 500 KB + const int ASCII = 0; + const int Error = 1; + const int UTF8 = 2; + const int UTF8Sequence = 3; + int state = ASCII; + int sequenceLength = 0; + byte b; + for (int i = 0; i < max; i++) { + if (i == 0) { + b = firstByte; + } else if (i == 1) { + b = secondByte; + } else { + b = (byte)fs.ReadByte(); + } + if (b < 0x80) { + // normal ASCII character + if (state == UTF8Sequence) { + state = Error; + break; + } + } else if (b < 0xc0) { + // 10xxxxxx : continues UTF8 byte sequence + if (state == UTF8Sequence) { + --sequenceLength; + if (sequenceLength < 0) { + state = Error; + break; + } else if (sequenceLength == 0) { + state = UTF8; + } + } else { + state = Error; + break; + } + } else if (b > 0xc2 && b < 0xf5) { + // beginning of byte sequence + if (state == UTF8 || state == ASCII) { + state = UTF8Sequence; + if (b < 0xe0) { + sequenceLength = 1; // one more byte following + } else if (b < 0xf0) { + sequenceLength = 2; // two more bytes following + } else { + sequenceLength = 3; // three more bytes following + } + } else { + state = Error; + break; + } + } else { + // 0xc0, 0xc1, 0xf5 to 0xff are invalid in UTF-8 (see RFC 3629) + state = Error; + break; + } + } + fs.Position = 0; + switch (state) { + case ASCII: + // when the file seems to be ASCII, we read it using the user-specified encoding + // so it is saved again using that encoding. + return new StreamReader(fs, GetDefaultEncoding()); + case Error: + return new StreamReader(fs, GetDefaultEncoding()); + default: + return new StreamReader(fs); + } + } + + Encoding GetDefaultEncoding() + { + Encoding encoding = Encoding.Default; + int codepage = encoding.CodePage; + if (codepage == 65001 || codepage == 65000 || codepage == 1200 || codepage == 1201) { + return Encoding.GetEncoding("ISO-8859-1"); + } else { + return encoding; + } + } + #endregion + } +} diff --git a/src/AddIns/BackendBindings/Boo/StandaloneConverter/StandaloneConverter.csproj b/src/AddIns/BackendBindings/Boo/StandaloneConverter/StandaloneConverter.csproj new file mode 100644 index 0000000000..edc2d55782 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/StandaloneConverter/StandaloneConverter.csproj @@ -0,0 +1,51 @@ + + + Exe + StandaloneConverter + StandaloneConverter + Debug + AnyCPU + {66338092-7611-40FC-B69C-B73A0528DA82} + + + bin\Debug\ + False + DEBUG;TRACE + True + Full + True + + + bin\Release\ + True + TRACE + False + None + False + + + + + + + ..\RequiredLibraries\Boo.Lang.Compiler.dll + False + + + + + + + + + {DBCF20A1-BA13-4582-BFA9-74DE4D987B73} + NRefactoryToBooConverter + + + {3A9AE6AA-BC07-4A2F-972C-581E3AE2F195} + NRefactory + False + + + + \ No newline at end of file diff --git a/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs b/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs index 5e0940d130..a6e834cfb3 100644 --- a/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs +++ b/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs @@ -549,7 +549,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver if (languageProperties.ImportModules) { ArrayList list = new ArrayList(); - AddImportedNamespaceContents(list); + AddImportedNamespaceContents(list, cu, callingClass); foreach (object o in list) { IClass c = o as IClass; if (c != null && IsSameName(identifier, c.Name)) { @@ -721,7 +721,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver if (languageProperties.ImportModules) { ArrayList list = new ArrayList(); - AddImportedNamespaceContents(list); + AddImportedNamespaceContents(list, cu, callingClass); foreach (object o in list) { IMethod m = o as IMethod; if (m != null && IsSameName(m.Name, memberName)) { @@ -807,7 +807,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver IParameter SearchMethodParameter(string parameter) { - IMethod method = callingMember as IMethod; + IMethodOrProperty method = callingMember as IMethodOrProperty; if (method == null) { return null; } @@ -904,10 +904,29 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver } } - IMethod method = callingMember as IMethod; - if (method != null) { - foreach (IParameter p in method.Parameters) { - result.Add(new DefaultField.ParameterField(p.ReturnType, p.Name, method.Region, callingClass)); + AddContentsFromCalling(result, callingClass, callingMember); + + foreach (KeyValuePair> pair in lookupTableVisitor.Variables) { + if (pair.Value != null && pair.Value.Count > 0) { + foreach (LocalLookupVariable v in pair.Value) { + if (IsInside(new Point(caretColumn, caretLine), v.StartPos, v.EndPos)) { + // convert to a field for display + result.Add(CreateLocalVariableField(v, pair.Key)); + break; + } + } + } + } + AddImportedNamespaceContents(result, cu, callingClass); + return result; + } + + public static void AddContentsFromCalling(ArrayList result, IClass callingClass, IMember callingMember) + { + IMethodOrProperty methodOrProperty = callingMember as IMethodOrProperty; + if (methodOrProperty != null) { + foreach (IParameter p in methodOrProperty.Parameters) { + result.Add(new DefaultField.ParameterField(p.ReturnType, p.Name, methodOrProperty.Region, callingClass)); } } @@ -927,43 +946,33 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver result.Add(m); } } - if (callingClass.DeclaringType != null) { - result.Add(callingClass.DeclaringType); - members.Clear(); - t = callingClass.DeclaringType.DefaultReturnType; + members.Clear(); + IClass c = callingClass.DeclaringType; + while (c != null) { + result.Add(c); + t = c.DefaultReturnType; members.AddRange(t.GetMethods()); members.AddRange(t.GetFields()); members.AddRange(t.GetEvents()); members.AddRange(t.GetProperties()); - foreach (IMember m in members) { - if (m.IsStatic) { - result.Add(m); - } - } + c = c.DeclaringType; } - } - foreach (KeyValuePair> pair in lookupTableVisitor.Variables) { - if (pair.Value != null && pair.Value.Count > 0) { - foreach (LocalLookupVariable v in pair.Value) { - if (IsInside(new Point(caretColumn, caretLine), v.StartPos, v.EndPos)) { - // convert to a field for display - result.Add(CreateLocalVariableField(v, pair.Key)); - break; - } + foreach (IMember m in members) { + if (m.IsStatic) { + result.Add(m); } } } - AddImportedNamespaceContents(result); - return result; } - void AddImportedNamespaceContents(ArrayList result) + public static void AddImportedNamespaceContents(ArrayList result, ICompilationUnit cu, IClass callingClass) { - projectContent.AddNamespaceContents(result, "", languageProperties, true); + IProjectContent projectContent = cu.ProjectContent; + projectContent.AddNamespaceContents(result, "", projectContent.Language, true); foreach (IUsing u in cu.Usings) { - AddUsing(result, u); + AddUsing(result, u, projectContent); } - AddUsing(result, projectContent.DefaultImports); + AddUsing(result, projectContent.DefaultImports, projectContent); if (callingClass != null) { foreach (object member in projectContent.GetNamespaceContents(callingClass.Namespace)) { @@ -981,15 +990,15 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver } } - void AddUsing(ArrayList result, IUsing u) + static void AddUsing(ArrayList result, IUsing u, IProjectContent projectContent) { if (u == null) { return; } - bool importNamespaces = languageProperties.ImportNamespaces; + bool importNamespaces = projectContent.Language.ImportNamespaces; foreach (string name in u.Usings) { if (importNamespaces) { - projectContent.AddNamespaceContents(result, name, languageProperties, true); + projectContent.AddNamespaceContents(result, name, projectContent.Language, true); } else { foreach (object o in projectContent.GetNamespaceContents(name)) { if (!(o is string)) diff --git a/src/Main/Base/Project/Src/Dom/ResolveResult.cs b/src/Main/Base/Project/Src/Dom/ResolveResult.cs index 688a624766..d0b9adcd3c 100644 --- a/src/Main/Base/Project/Src/Dom/ResolveResult.cs +++ b/src/Main/Base/Project/Src/Dom/ResolveResult.cs @@ -128,6 +128,16 @@ namespace ICSharpCode.SharpDevelop.Dom } } + public TypeResolveResult TypeResult { + get { + if (primaryResult is TypeResolveResult) + return (TypeResolveResult)primaryResult; + if (secondaryResult is TypeResolveResult) + return (TypeResolveResult)secondaryResult; + return null; + } + } + public MixedResolveResult(ResolveResult primaryResult, ResolveResult secondaryResult) : base(primaryResult.CallingClass, primaryResult.CallingMember, primaryResult.ResolvedType) { diff --git a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/SharpDevelopTextAreaControl.cs b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/SharpDevelopTextAreaControl.cs index 0a32aca853..dd1b308ff0 100644 --- a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/SharpDevelopTextAreaControl.cs +++ b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/SharpDevelopTextAreaControl.cs @@ -247,20 +247,22 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor return false; } } - string word = GetWordBeforeCaret(); - if (word != null) { - CodeTemplateGroup templateGroup = CodeTemplateLoader.GetTemplateGroupPerFilename(FileName); - if (templateGroup != null) { - foreach (CodeTemplate template in templateGroup.Templates) { - if (template.Shortcut == word) { - if (word.Length > 0) { - int newCaretOffset = DeleteWordBeforeCaret(); - //// set new position in text area - ActiveTextAreaControl.TextArea.Caret.Position = Document.OffsetToPosition(newCaretOffset); + if (ch == ' ') { + string word = GetWordBeforeCaret(); + if (word != null) { + CodeTemplateGroup templateGroup = CodeTemplateLoader.GetTemplateGroupPerFilename(FileName); + if (templateGroup != null) { + foreach (CodeTemplate template in templateGroup.Templates) { + if (template.Shortcut == word) { + if (word.Length > 0) { + int newCaretOffset = DeleteWordBeforeCaret(); + //// set new position in text area + ActiveTextAreaControl.TextArea.Caret.Position = Document.OffsetToPosition(newCaretOffset); + } + + InsertTemplate(template); + return true; } - - InsertTemplate(template); - return true; } } } diff --git a/src/SharpDevelop.WithTests.sln b/src/SharpDevelop.WithTests.sln index 3ee3ede2e3..b70a26e7ba 100644 --- a/src/SharpDevelop.WithTests.sln +++ b/src/SharpDevelop.WithTests.sln @@ -1,5 +1,5 @@ -Microsoft Visual Studio Solution File, Format Version 9.00 -# SharpDevelop 2.0.0.413 +Microsoft Visual Studio Solution File, Format Version 9.00 +# SharpDevelop 2.0.0.539 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AddIns", "AddIns", "{14A277EE-7DF1-4529-B639-7D1EF334C1C5}" ProjectSection(SolutionItems) = postProject EndProjectSection @@ -20,6 +20,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Backends", "Backends", "{FE ProjectSection(SolutionItems) = postProject EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BooBinding", "AddIns\BackendBindings\Boo\BooBinding\Project\BooBinding.csproj", "{4AC2D5F1-F671-480C-A075-6BF62B3721B2}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpBinding.Tests", "AddIns\BackendBindings\CSharpBinding\Test\CSharpBinding.Tests.csproj", "{4D0DFCB0-F6FB-469D-AA6F-C7F1D5FD5DE7}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILAsmBinding", "AddIns\BackendBindings\ILAsmBinding\Project\ILAsmBinding.csproj", "{6e59af58-f635-459a-9a35-c9ac41c00339}" @@ -182,6 +184,7 @@ Global {BF38FB72-B380-4196-AF8C-95749D726C61} = {FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C} {6e59af58-f635-459a-9a35-c9ac41c00339} = {FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C} {4D0DFCB0-F6FB-469D-AA6F-C7F1D5FD5DE7} = {FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C} + {4AC2D5F1-F671-480C-A075-6BF62B3721B2} = {FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C} {4B8F0F98-8BE1-402B-AA8B-C8D548577B38} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} {7D5C266F-D6FF-4D14-B315-0C0FC6C4EF51} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} {64A3E5E6-90BF-47F6-94DF-68C94B62C817} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} diff --git a/src/SharpDevelop.sln b/src/SharpDevelop.sln index cf62c55a51..e2bd514574 100644 --- a/src/SharpDevelop.sln +++ b/src/SharpDevelop.sln @@ -1,5 +1,5 @@ -Microsoft Visual Studio Solution File, Format Version 9.00 -# SharpDevelop 2.0.0.377 +Microsoft Visual Studio Solution File, Format Version 9.00 +# SharpDevelop 2.0.0.539 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AddIns", "AddIns", "{14A277EE-7DF1-4529-B639-7D1EF334C1C5}" ProjectSection(SolutionItems) = postProject EndProjectSection @@ -18,6 +18,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Backends", "Backends", "{FE ProjectSection(SolutionItems) = postProject EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BooBinding", "AddIns\BackendBindings\Boo\BooBinding\Project\BooBinding.csproj", "{4AC2D5F1-F671-480C-A075-6BF62B3721B2}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILAsmBinding", "AddIns\BackendBindings\ILAsmBinding\Project\ILAsmBinding.csproj", "{6e59af58-f635-459a-9a35-c9ac41c00339}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VBNetBinding", "AddIns\BackendBindings\VBNetBinding\Project\VBNetBinding.csproj", "{BF38FB72-B380-4196-AF8C-95749D726C61}" @@ -168,6 +170,7 @@ Global {1F1AC7CD-D154-45BB-8EAF-804CA8055F5A} = {FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C} {BF38FB72-B380-4196-AF8C-95749D726C61} = {FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C} {6e59af58-f635-459a-9a35-c9ac41c00339} = {FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C} + {4AC2D5F1-F671-480C-A075-6BF62B3721B2} = {FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C} {4B8F0F98-8BE1-402B-AA8B-C8D548577B38} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} {7D5C266F-D6FF-4D14-B315-0C0FC6C4EF51} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} {64A3E5E6-90BF-47F6-94DF-68C94B62C817} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2}