diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/BooBinding.csproj b/src/AddIns/BackendBindings/Boo/BooBinding/Project/BooBinding.csproj index b5127a3912..7e73ccbc05 100644 --- a/src/AddIns/BackendBindings/Boo/BooBinding/Project/BooBinding.csproj +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/BooBinding.csproj @@ -33,6 +33,9 @@ False + + ..\..\RequiredLibraries\Boo.Lang.Extensions.dll + ..\..\RequiredLibraries\Boo.Lang.Interpreter.dll @@ -68,6 +71,7 @@ + diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/BooProject.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/BooProject.cs index 952da21a35..53fb167b59 100644 --- a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/BooProject.cs +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/BooProject.cs @@ -101,9 +101,12 @@ namespace Grunwald.BooBinding pc.AddReferencedContent(AssemblyParserService.GetProjectContentForReference(systemItem)); ReferenceProjectItem booLangItem = new ReferenceProjectItem(this, typeof(Boo.Lang.Builtins).Assembly.Location); pc.AddReferencedContent(AssemblyParserService.GetProjectContentForReference(booLangItem)); + ReferenceProjectItem booExtensionsItem = new ReferenceProjectItem(this, typeof(Boo.Lang.Extensions.PropertyAttribute).Assembly.Location); + pc.AddReferencedContent(AssemblyParserService.GetProjectContentForReference(booExtensionsItem)); pc.DefaultImports = new DefaultUsing(pc); pc.DefaultImports.Usings.Add("Boo.Lang"); pc.DefaultImports.Usings.Add("Boo.Lang.Builtins"); + pc.DefaultImports.Usings.Add("Boo.Lang.Extensions"); return pc; } diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BindNamespacesWithoutRemovingErrors.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BindNamespacesWithoutRemovingErrors.cs new file mode 100644 index 0000000000..70e32c4df0 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BindNamespacesWithoutRemovingErrors.cs @@ -0,0 +1,25 @@ +// +// +// +// +// $Revision$ +// + +using System; +using Boo.Lang.Compiler.Steps; + +namespace Grunwald.BooBinding.CodeCompletion +{ + /// + /// The Boo 'BindNamespaces' step will remove imports that cannot be resolved. + /// However, we need to keep those imports available for use inside SharpDevelop. + /// + public class BindNamespacesWithoutRemovingErrors : BindNamespaces + { + public override void OnImport(Boo.Lang.Compiler.Ast.Import import) + { + base.OnImport(import); + ReplaceCurrentNode(import); // prevent removal of import + } + } +} diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooParser.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooParser.cs index f14aac6250..c4cc233220 100644 --- a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooParser.cs +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/BooParser.cs @@ -163,24 +163,87 @@ namespace Grunwald.BooBinding.CodeCompletion compiler.Parameters.OutputWriter = new StringWriter(); compiler.Parameters.TraceLevel = System.Diagnostics.TraceLevel.Off; - Compile compilePipe = new Compile(); + // Compile pipeline as of Boo 0.9.2: + // Boo.Lang.Compiler.Pipelines.Parse: + // Boo.Lang.Parser.BooParsingStep + // Boo.Lang.Compiler.Pipelines.ExpandMacros: + // Boo.Lang.Compiler.Steps.InitializeTypeSystemServices + // Boo.Lang.Compiler.Steps.PreErrorChecking + // Boo.Lang.Compiler.Steps.MergePartialClasses + // Boo.Lang.Compiler.Steps.InitializeNameResolutionService + // Boo.Lang.Compiler.Steps.IntroduceGlobalNamespaces + // Boo.Lang.Compiler.Steps.TransformCallableDefinitions + // Boo.Lang.Compiler.Steps.BindTypeDefinitions + // Boo.Lang.Compiler.Steps.BindGenericParameters + // Boo.Lang.Compiler.Steps.BindNamespaces + // Boo.Lang.Compiler.Steps.BindBaseTypes + // Boo.Lang.Compiler.Steps.MacroAndAttributeExpansion + // Boo.Lang.Compiler.Pipelines.ResolveExpressions: + // Boo.Lang.Compiler.Steps.ExpandAstLiterals + // Boo.Lang.Compiler.Steps.IntroduceModuleClasses + // Boo.Lang.Compiler.Steps.NormalizeStatementModifiers + // Boo.Lang.Compiler.Steps.NormalizeTypeAndMemberDefinitions + // Boo.Lang.Compiler.Steps.NormalizeOmittedExpressions + // Boo.Lang.Compiler.Steps.BindTypeDefinitions + // Boo.Lang.Compiler.Steps.BindGenericParameters + // Boo.Lang.Compiler.Steps.BindEnumMembers + // Boo.Lang.Compiler.Steps.BindBaseTypes + // Boo.Lang.Compiler.Steps.CheckMemberTypes + // Boo.Lang.Compiler.Steps.BindMethods + // Boo.Lang.Compiler.Steps.ResolveTypeReferences + // Boo.Lang.Compiler.Steps.BindTypeMembers + // Boo.Lang.Compiler.Steps.CheckGenericConstraints + // Boo.Lang.Compiler.Steps.ProcessInheritedAbstractMembers + // Boo.Lang.Compiler.Steps.CheckMemberNames + // Boo.Lang.Compiler.Steps.ProcessMethodBodiesWithDuckTyping + // Boo.Lang.Compiler.Steps.PreProcessExtensionMethods + // Boo.Lang.Compiler.Pipelines.Compile: + // Boo.Lang.Compiler.Steps.ConstantFolding + // Boo.Lang.Compiler.Steps.NormalizeLiterals + // Boo.Lang.Compiler.Steps.OptimizeIterationStatements + // Boo.Lang.Compiler.Steps.BranchChecking + // Boo.Lang.Compiler.Steps.CheckIdentifiers + // Boo.Lang.Compiler.Steps.StricterErrorChecking + // Boo.Lang.Compiler.Steps.CheckAttributesUsage + // Boo.Lang.Compiler.Steps.ExpandDuckTypedExpressions + // Boo.Lang.Compiler.Steps.ProcessAssignmentsToValueTypeMembers + // Boo.Lang.Compiler.Steps.ExpandProperties + // Boo.Lang.Compiler.Steps.RemoveDeadCode + // Boo.Lang.Compiler.Steps.CheckMembersProtectionLevel + // Boo.Lang.Compiler.Steps.NormalizeIterationStatements + // Boo.Lang.Compiler.Steps.ProcessSharedLocals + // Boo.Lang.Compiler.Steps.ProcessClosures + // Boo.Lang.Compiler.Steps.ProcessGenerators + // Boo.Lang.Compiler.Steps.ExpandVarArgsMethodInvocations + // Boo.Lang.Compiler.Steps.InjectCallableConversions + // Boo.Lang.Compiler.Steps.ImplementICallableOnCallableDefinitions + // Boo.Lang.Compiler.Steps.CheckNeverUsedMembers + // Boo.Lang.Compiler.Pipelines.CompileToMemory: + // Boo.Lang.Compiler.Steps.EmitAssembly + // Boo.Lang.Compiler.Pipelines.CompileToFile: + // Boo.Lang.Compiler.Steps.SaveAssembly + + + CompilerPipeline compilePipe = new Parse(); + compilePipe.Add(new InitializeTypeSystemServices()); + compilePipe.Add(new PreErrorChecking()); + compilePipe.Add(new MergePartialClasses()); + compilePipe.Add(new InitializeNameResolutionService()); + compilePipe.Add(new IntroduceGlobalNamespaces()); + // TransformCallableDefinitions: not used for CC + compilePipe.Add(new BindTypeDefinitions()); + compilePipe.Add(new BindGenericParameters()); + compilePipe.Add(new BindNamespacesWithoutRemovingErrors()); + compilePipe.Add(new BindBaseTypes()); + compilePipe.Add(new MacroAndAttributeExpansion()); + compilePipe.Add(new IntroduceModuleClasses()); + 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(NormalizeStatementModifiers)); - 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.Add(visitor); compilePipe.BreakOnErrors = false; compiler.Parameters.Pipeline = compilePipe; diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ExpressionFinder.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ExpressionFinder.cs index 7e2fcc25af..e310f7487e 100644 --- a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ExpressionFinder.cs +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ExpressionFinder.cs @@ -14,14 +14,14 @@ using ICSharpCode.SharpDevelop.Dom; namespace Grunwald.BooBinding.CodeCompletion { - // TODO: We could need some unit tests for this. public class ExpressionFinder : IExpressionFinder { - string fileName; + public ExpressionFinder() + { + } public ExpressionFinder(string fileName) { - this.fileName = fileName; } #region RemoveLastPart @@ -79,6 +79,14 @@ namespace Grunwald.BooBinding.CodeCompletion const string _openingBrackets = "{[("; public ExpressionResult FindExpression(string inText, int offset) + { + ExpressionResult r = FindExpressionInternal(inText, offset); + if (string.IsNullOrEmpty(r.Expression)) + r.Expression = null; + return r; + } + + ExpressionResult FindExpressionInternal(string inText, int offset) { offset--; // earlier all ExpressionFinder calls had an inexplicable "cursor - 1". // The IExpressionFinder API now uses normal cursor offsets, so we need to adjust the offset @@ -154,7 +162,8 @@ namespace Grunwald.BooBinding.CodeCompletion ExpressionResult GetExpression(string inText, int start, int end) { - if (start == end) return ExpressionResult.Empty; + if (start == end) + return new ExpressionResult(string.Empty); StringBuilder b = new StringBuilder(); bool wasSpace = true; int i = start; @@ -234,7 +243,7 @@ namespace Grunwald.BooBinding.CodeCompletion #region Find Full Expression public ExpressionResult FindFullExpression(string inText, int offset) { - ExpressionResult result = FindExpression(inText, offset); + ExpressionResult result = FindExpressionInternal(inText, offset); if (result.Expression == null) return result; StringBuilder b = new StringBuilder(result.Expression); @@ -261,7 +270,10 @@ namespace Grunwald.BooBinding.CodeCompletion } else { if (bracketStack.Count == 0) { b.Append(inText, offset, i - offset); - result.Expression = b.ToString(); + if (b.Length == 0) + result.Expression = null; + else + result.Expression = b.ToString(); return result; } else if (c == '\0') { // end of document diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Test/BooBinding.Tests.csproj b/src/AddIns/BackendBindings/Boo/BooBinding/Test/BooBinding.Tests.csproj index b5e2d6cf1e..64ce8b5de6 100644 --- a/src/AddIns/BackendBindings/Boo/BooBinding/Test/BooBinding.Tests.csproj +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Test/BooBinding.Tests.csproj @@ -47,6 +47,7 @@ + diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Test/ExpressionFinderTests.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Test/ExpressionFinderTests.cs new file mode 100644 index 0000000000..8322d41ee5 --- /dev/null +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Test/ExpressionFinderTests.cs @@ -0,0 +1,68 @@ +// +// +// +// +// $Revision$ +// + +using System; +using Grunwald.BooBinding.CodeCompletion; +using ICSharpCode.SharpDevelop.Dom; +using NUnit.Framework; + +namespace Grunwald.BooBinding.Tests +{ + [TestFixture] + public class ExpressionFinderTests + { + const string code = "class A:\n\tpublic simple = 1\n// comment\ndef main():\n\tpass"; + ExpressionFinder ef = new ExpressionFinder(); + + void FindFull(string program, string location, string expectedExpression, ExpressionContext expectedContext) + { + int pos = program.IndexOf(location); + if (pos < 0) Assert.Fail("location not found in program"); + ExpressionResult er = ef.FindFullExpression(program, pos); + Assert.AreEqual(expectedExpression, er.Expression); + if (expectedContext != null) { + Assert.AreEqual(expectedContext, er.Context); + } + } + + [Test] + public void Simple() + { + FindFull(code, "mple = 1", "simple", ExpressionContext.Default); + } + + [Test] + public void SimpleBeginningOfExpression() + { + FindFull(code, "simple = 1", "simple", ExpressionContext.Default); + } + + [Test] + public void NoMatchForComment1() + { + FindFull(code, "// comment", null, null); + } + + [Test] + public void NoMatchForComment2() + { + FindFull(code, "/ comment", null, null); + } + + [Test] + public void NoMatchForComment3() + { + FindFull(code, " comment", null, null); + } + + [Test] + public void NoMatchForComment4() + { + FindFull(code, "comment", null, null); + } + } +} diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerLoader/NRefactoryDesignerLoader.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerLoader/NRefactoryDesignerLoader.cs index 22c817c450..4c10255ca0 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerLoader/NRefactoryDesignerLoader.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerLoader/NRefactoryDesignerLoader.cs @@ -19,6 +19,7 @@ using ICSharpCode.NRefactory.Ast; using ICSharpCode.NRefactory.Visitors; using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.Dom; +using ReturnTypeOptions = ICSharpCode.SharpDevelop.Dom.NRefactoryResolver.TypeVisitor.ReturnTypeOptions; namespace ICSharpCode.FormsDesigner { @@ -213,8 +214,8 @@ namespace ICSharpCode.FormsDesigner } TypeDeclaration typeDecl = o as TypeDeclaration; if (typeDecl != null) { - foreach (TypeReference tref in typeDecl.BaseTypes) { - FixTypeReference(tref, typeDecl.StartLocation, domCu); + for (int i = 0; i < typeDecl.BaseTypes.Count; i++) { + typeDecl.BaseTypes[i] = FixTypeReference(typeDecl.BaseTypes[i], typeDecl.StartLocation, domCu, ReturnTypeOptions.BaseTypeReference); } for (int i = 0; i < typeDecl.Children.Count; i++) { object child = typeDecl.Children[i]; @@ -242,28 +243,26 @@ namespace ICSharpCode.FormsDesigner } FieldDeclaration fieldDecl = o as FieldDeclaration; if (fieldDecl != null) { - FixTypeReference(fieldDecl.TypeReference, fieldDecl.StartLocation, domCu); + fieldDecl.TypeReference = FixTypeReference(fieldDecl.TypeReference, fieldDecl.StartLocation, domCu, ReturnTypeOptions.None); foreach (VariableDeclaration var in fieldDecl.Fields) { if (var != null) { - FixTypeReference(var.TypeReference, fieldDecl.StartLocation, domCu); + var.TypeReference = FixTypeReference(var.TypeReference, fieldDecl.StartLocation, domCu, ReturnTypeOptions.None); } } } } - void FixTypeReference(TypeReference type, Location location, ICSharpCode.SharpDevelop.Dom.ICompilationUnit domCu) + TypeReference FixTypeReference(TypeReference type, Location location, ICompilationUnit domCu, ReturnTypeOptions options) { - if (type == null) - return; - if (type.Type != type.Type) - return; - foreach (TypeReference tref in type.GenericTypes) { - FixTypeReference(tref, location, domCu); - } + if (type == null || type.IsKeyword) + return type; ICSharpCode.SharpDevelop.Dom.IClass curType = domCu.GetInnermostClass(location.Y, location.X); - ICSharpCode.SharpDevelop.Dom.IReturnType rt = domCu.ProjectContent.SearchType(new SearchTypeRequest(type.Type, type.GenericTypes.Count, curType, domCu, location.Y, location.X)).Result; - if (rt != null) { - type.Type = rt.FullyQualifiedName; + IReturnType rt = SharpDevelop.Dom.NRefactoryResolver.TypeVisitor.CreateReturnType( + type, curType, null, location.Y, location.X, domCu.ProjectContent, options); + if (rt != null && rt.GetUnderlyingClass() != null) { + return SharpDevelop.Dom.Refactoring.CodeGenerator.ConvertType(rt, null); + } else { + return type; } } diff --git a/src/Libraries/NRefactory/Project/Src/Ast/TypeReference.cs b/src/Libraries/NRefactory/Project/Src/Ast/TypeReference.cs index b3878da1d8..35fa72a3f7 100644 --- a/src/Libraries/NRefactory/Project/Src/Ast/TypeReference.cs +++ b/src/Libraries/NRefactory/Project/Src/Ast/TypeReference.cs @@ -425,7 +425,7 @@ namespace ICSharpCode.NRefactory.Ast public override string ToString() { - return "[InnerClassTypeReference: (" + baseType.ToString() + ")." + base.ToString() + "]"; + return baseType.ToString() + "+" + base.ToString(); } } } diff --git a/src/Libraries/NRefactory/Project/Src/PrettyPrinter/VBNet/VBNetOutputVisitor.cs b/src/Libraries/NRefactory/Project/Src/PrettyPrinter/VBNet/VBNetOutputVisitor.cs index c21847984f..1760cebb6d 100644 --- a/src/Libraries/NRefactory/Project/Src/PrettyPrinter/VBNet/VBNetOutputVisitor.cs +++ b/src/Libraries/NRefactory/Project/Src/PrettyPrinter/VBNet/VBNetOutputVisitor.cs @@ -2655,6 +2655,34 @@ namespace ICSharpCode.NRefactory.PrettyPrinter outputFormatter.PrintToken(Tokens.OpenParenthesis); AppendCommaSeparatedList(objectCreateExpression.Parameters); outputFormatter.PrintToken(Tokens.CloseParenthesis); + CollectionInitializerExpression initializer = objectCreateExpression.ObjectInitializer; + if (!initializer.IsNull) { + outputFormatter.Space(); + outputFormatter.PrintToken(Tokens.With); + outputFormatter.Space(); + outputFormatter.PrintToken(Tokens.OpenCurlyBrace); + outputFormatter.IndentationLevel++; + for (int i = 0; i < initializer.CreateExpressions.Count; i++) { + Expression expr = initializer.CreateExpressions[i]; + if (i > 0) + outputFormatter.PrintToken(Tokens.Comma); + outputFormatter.PrintLineContinuation(); + outputFormatter.Indent(); + NamedArgumentExpression nae = expr as NamedArgumentExpression; + if (nae != null) { + outputFormatter.PrintToken(Tokens.Dot); + outputFormatter.PrintIdentifier(nae.Name); + outputFormatter.Space(); + outputFormatter.PrintToken(Tokens.Assign); + outputFormatter.Space(); + TrackedVisit(nae.Expression, data); + } + } + outputFormatter.IndentationLevel--; + outputFormatter.PrintLineContinuation(); + outputFormatter.Indent(); + outputFormatter.PrintToken(Tokens.CloseCurlyBrace); + } return null; } diff --git a/src/Libraries/NRefactory/Project/Src/Visitors/CodeDOMOutputVisitor.cs b/src/Libraries/NRefactory/Project/Src/Visitors/CodeDOMOutputVisitor.cs index d1ed5dbc0c..e57c5f6dd4 100644 --- a/src/Libraries/NRefactory/Project/Src/Visitors/CodeDOMOutputVisitor.cs +++ b/src/Libraries/NRefactory/Project/Src/Visitors/CodeDOMOutputVisitor.cs @@ -78,17 +78,32 @@ namespace ICSharpCode.NRefactory.Visitors variables.Clear(); parameters.Clear(); } - + + string GetDotNetNameFromTypeReference(TypeReference type) + { + string name; + InnerClassTypeReference ictr = type as InnerClassTypeReference; + if (ictr != null) { + name = GetDotNetNameFromTypeReference(ictr.BaseType) + "+" + ictr.Type; + } else { + name = type.Type; + } + if (type.GenericTypes.Count != 0) + name = name + "`" + type.GenericTypes.Count.ToString(); + return name; + } + CodeTypeReference ConvType(TypeReference type) { if (type == null) { throw new ArgumentNullException("type"); } - if (string.IsNullOrEmpty(type.Type)) { - throw new InvalidOperationException("empty type"); - } - CodeTypeReference t = new CodeTypeReference(type.Type); + CodeTypeReference t = new CodeTypeReference(GetDotNetNameFromTypeReference(type)); + InnerClassTypeReference ictr = type as InnerClassTypeReference; + if (ictr != null) { + type = ictr.CombineToNormalTypeReference(); + } foreach (TypeReference gt in type.GenericTypes) { t.TypeArguments.Add(ConvType(gt)); } diff --git a/src/Libraries/NRefactory/Test/NRefactoryTests.csproj b/src/Libraries/NRefactory/Test/NRefactoryTests.csproj index 866fa1a7dc..b33310ca05 100644 --- a/src/Libraries/NRefactory/Test/NRefactoryTests.csproj +++ b/src/Libraries/NRefactory/Test/NRefactoryTests.csproj @@ -47,6 +47,9 @@ ..\..\..\Tools\NUnit\nunit.framework.dll False + + 3.5 + @@ -54,6 +57,7 @@ + diff --git a/src/Libraries/NRefactory/Test/NRefactoryTests.csproj.user b/src/Libraries/NRefactory/Test/NRefactoryTests.csproj.user deleted file mode 100644 index eb26958768..0000000000 --- a/src/Libraries/NRefactory/Test/NRefactoryTests.csproj.user +++ /dev/null @@ -1,10 +0,0 @@ - - - 8.0.50215 - - - Program - D:\Corsavy\SharpDevelop\bin\SharpDevelop.exe - D:\Corsavy\SharpDevelop\src\Libraries\NRefactory\NRefactory.sln - - \ No newline at end of file diff --git a/src/Libraries/NRefactory/Test/Output/CodeDOM/CodeDOMTypeReferenceTest.cs b/src/Libraries/NRefactory/Test/Output/CodeDOM/CodeDOMTypeReferenceTest.cs new file mode 100644 index 0000000000..79fcccb97e --- /dev/null +++ b/src/Libraries/NRefactory/Test/Output/CodeDOM/CodeDOMTypeReferenceTest.cs @@ -0,0 +1,33 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using System.CodeDom; +using ICSharpCode.NRefactory.Ast; +using ICSharpCode.NRefactory.Visitors; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.Tests.Output.CodeDOM.Tests +{ + [TestFixture] + public class CodeDOMTypeReferenceTest + { + [TestAttribute] + public void InnerClassTypeReferencTest() + { + InnerClassTypeReference ictr = new InnerClassTypeReference( + new TypeReference("OuterClass", new List { new TypeReference("String") }), + "InnerClass", + new List { new TypeReference("Int32"), new TypeReference("Int64") }); + Assert.AreEqual("OuterClass+InnerClass", ictr.ToString()); + CodeTypeOfExpression result = (CodeTypeOfExpression)new TypeOfExpression(ictr).AcceptVisitor(new CodeDomVisitor(), null); + Assert.AreEqual("OuterClass`1+InnerClass`2", result.Type.BaseType); + Assert.AreEqual(3, result.Type.TypeArguments.Count); + } + } +} diff --git a/src/Libraries/NRefactory/Test/Output/VBNet/VBNetOutputTest.cs b/src/Libraries/NRefactory/Test/Output/VBNet/VBNetOutputTest.cs index a9360578c0..97cb95fb57 100644 --- a/src/Libraries/NRefactory/Test/Output/VBNet/VBNetOutputTest.cs +++ b/src/Libraries/NRefactory/Test/Output/VBNet/VBNetOutputTest.cs @@ -467,5 +467,20 @@ End Using"); TestExpression("347UL"); TestExpression("\".\"C"); } + + [Test] + public void AddressOf() + { + TestExpression("AddressOf Abc"); + } + + [Test] + public void ObjectInitializer() + { + TestExpression("New StringWriter() With { _\n" + + " .NewLine = Environment.NewLine, _\n" + + " .Encoding = Encoding.UTF8 _\n" + + "}"); + } } } diff --git a/src/Main/Base/Project/Src/Commands/CustomStringTagProvider.cs b/src/Main/Base/Project/Src/Commands/CustomStringTagProvider.cs index bac923a424..9ff8db18de 100644 --- a/src/Main/Base/Project/Src/Commands/CustomStringTagProvider.cs +++ b/src/Main/Base/Project/Src/Commands/CustomStringTagProvider.cs @@ -80,6 +80,11 @@ namespace ICSharpCode.SharpDevelop.Commands return Path.GetExtension(GetCurrentItemPath()) ?? string.Empty; } catch (Exception) {} return string.Empty; + case "ITEMNAMENOEXT": + try { + return Path.GetFileNameWithoutExtension(GetCurrentItemPath()) ?? string.Empty; + } catch (Exception) {} + return string.Empty; case "CURLINE": { diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/CSharpToVBNetConvertVisitor.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/CSharpToVBNetConvertVisitor.cs index e5136b499b..3ffc875178 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/CSharpToVBNetConvertVisitor.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/CSharpToVBNetConvertVisitor.cs @@ -467,6 +467,14 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver // casts from float to int in C# truncate, but VB rounds // we'll have to introduce a call to Math.Truncate castExpression.Expression = ExpressionBuilder.Identifier("Math").Call("Truncate", castExpression.Expression); + } else if (sourceType != null && sourceType.FullyQualifiedName == "System.Char") { + // casts from char to int are valid in C#, but need to use AscW in VB + castExpression.Expression = ExpressionBuilder.Identifier("AscW").Call(castExpression.Expression); + if (targetType != null && targetType.FullyQualifiedName == "System.Int32") { + // AscW already returns int, so skip the cast + ReplaceCurrentNode(castExpression.Expression); + return null; + } } } } diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/CodeSnippetConverter.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/CodeSnippetConverter.cs index d81038101b..82deaa9dcf 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/CodeSnippetConverter.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/CodeSnippetConverter.cs @@ -39,6 +39,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver List specials; CompilationUnit compilationUnit; ParseInformation parseInfo; + bool wasExpression; #region Parsing INode Parse(SupportedLanguage sourceLanguage, string sourceCode, out string error) @@ -56,18 +57,20 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver if (parser.Errors.Count != 0) return null; + wasExpression = parser.SnippetType == SnippetType.Expression; + if (wasExpression) { + // Special case 'Expression': expressions may be replaced with other statements in the AST by the ConvertVisitor, + // but we need to return a 'stable' node so that the correct transformed AST is returned. + // Thus, we wrap any expressions into a statement block. + result = MakeBlockFromExpression((Expression)result); + } + // now create a dummy compilation unit around the snippet result switch (parser.SnippetType) { case SnippetType.CompilationUnit: compilationUnit = (CompilationUnit)result; break; case SnippetType.Expression: - compilationUnit = MakeCompilationUnitFromTypeMembers( - MakeMethodFromBlock( - MakeBlockFromExpression( - (Expression)result - ))); - break; case SnippetType.Statements: compilationUnit = MakeCompilationUnitFromTypeMembers( MakeMethodFromBlock( @@ -95,6 +98,22 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver return result; } + /// + /// Unpacks the expression from a statement block; if it was wrapped earlier. + /// + INode UnpackExpression(INode node) + { + if (wasExpression) { + BlockStatement block = node as BlockStatement; + if (block != null && block.Children.Count == 1) { + ExpressionStatement es = block.Children[0] as ExpressionStatement; + if (es != null) + return es.Expression; + } + } + return node; + } + BlockStatement MakeBlockFromExpression(Expression expr) { return new BlockStatement { @@ -146,7 +165,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver }, null); PreprocessingDirective.CSharpToVB(specials); - return CreateCode(node, new VBNetOutputVisitor()); + return CreateCode(UnpackExpression(node), new VBNetOutputVisitor()); } public string VBToCSharp(string input, out string errors) @@ -159,7 +178,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver new VBNetToCSharpConvertVisitor(project, parseInfo), null); PreprocessingDirective.VBToCSharp(specials); - return CreateCode(node, new CSharpOutputVisitor()); + return CreateCode(UnpackExpression(node), new CSharpOutputVisitor()); } string CreateCode(INode node, IOutputAstVisitor outputVisitor) diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Refactoring/CodeGenerator.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Refactoring/CodeGenerator.cs index da8c966291..82cea4c798 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Refactoring/CodeGenerator.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Refactoring/CodeGenerator.cs @@ -43,26 +43,70 @@ namespace ICSharpCode.SharpDevelop.Dom.Refactoring if (returnType == null) return TypeReference.Null; if (returnType is NullReturnType) return TypeReference.Null; - TypeReference typeRef; - if (IsPrimitiveType(returnType)) - typeRef = new TypeReference(returnType.FullyQualifiedName, true); - else if (context != null && CanUseShortTypeName(returnType, context)) - typeRef = new TypeReference(returnType.Name); - else - typeRef = new TypeReference(returnType.FullyQualifiedName); - while (returnType.IsArrayReturnType) { + ArrayReturnType arrayReturnType = returnType.CastToArrayReturnType(); + if (arrayReturnType != null) { + TypeReference typeRef = ConvertType(arrayReturnType.ArrayElementType, context); int[] rank = typeRef.RankSpecifier ?? new int[0]; Array.Resize(ref rank, rank.Length + 1); - rank[rank.Length - 1] = returnType.CastToArrayReturnType().ArrayDimensions - 1; + rank[rank.Length - 1] = arrayReturnType.ArrayDimensions - 1; typeRef.RankSpecifier = rank; - returnType = returnType.CastToArrayReturnType().ArrayElementType; + return typeRef; + } + PointerReturnType pointerReturnType = returnType.CastToDecoratingReturnType(); + if (pointerReturnType != null) { + TypeReference typeRef = ConvertType(pointerReturnType.BaseType, context); + typeRef.PointerNestingLevel++; + return typeRef; } + + IList typeArguments = EmptyList.Instance; if (returnType.IsConstructedReturnType) { - foreach (IReturnType typeArgument in returnType.CastToConstructedReturnType().TypeArguments) { + typeArguments = returnType.CastToConstructedReturnType().TypeArguments; + } + IClass c = returnType.GetUnderlyingClass(); + if (c != null) { + return CreateTypeReference(c, typeArguments, context); + } else { + TypeReference typeRef; + if (IsPrimitiveType(returnType)) + typeRef = new TypeReference(returnType.FullyQualifiedName, true); + else if (context != null && CanUseShortTypeName(returnType, context)) + typeRef = new TypeReference(returnType.Name); + else { + string fullName = returnType.FullyQualifiedName; + if (string.IsNullOrEmpty(fullName)) + fullName = returnType.Name; + typeRef = new TypeReference(fullName); + } + foreach (IReturnType typeArgument in typeArguments) { typeRef.GenericTypes.Add(ConvertType(typeArgument, context)); } + return typeRef; + } + } + + static TypeReference CreateTypeReference(IClass c, IList typeArguments, ClassFinder context) + { + if (c.DeclaringType != null) { + TypeReference outerClass = CreateTypeReference(c.DeclaringType, typeArguments, context); + List args = new List(); + for (int i = c.DeclaringType.TypeParameters.Count; i < Math.Min(c.TypeParameters.Count, typeArguments.Count); i++) { + args.Add(ConvertType(typeArguments[i], context)); + } + return new InnerClassTypeReference(outerClass, c.Name, args); + } else { + TypeReference typeRef; + if (IsPrimitiveType(c.DefaultReturnType)) + typeRef = new TypeReference(c.FullyQualifiedName, true); + else if (context != null && CanUseShortTypeName(c.DefaultReturnType, context)) + typeRef = new TypeReference(c.Name); + else + typeRef = new TypeReference(c.FullyQualifiedName); + for (int i = 0; i < Math.Min(c.TypeParameters.Count, typeArguments.Count); i++) { + typeRef.GenericTypes.Add(ConvertType(typeArguments[i], context)); + } + return typeRef; } - return typeRef; } static bool IsPrimitiveType(IReturnType returnType) @@ -78,9 +122,12 @@ namespace ICSharpCode.SharpDevelop.Dom.Refactoring /// public static bool CanUseShortTypeName(IReturnType returnType, ClassFinder context) { - int typeArgumentCount = (returnType.IsConstructedReturnType) ? returnType.CastToConstructedReturnType().TypeArguments.Count : 0; - IReturnType typeInTargetContext = context.SearchType(returnType.Name, typeArgumentCount); - return typeInTargetContext != null && typeInTargetContext.FullyQualifiedName == returnType.FullyQualifiedName; + if (returnType == null || context == null) + return false; + IReturnType typeInTargetContext = context.SearchType(returnType.Name, returnType.TypeArgumentCount); + return typeInTargetContext != null + && typeInTargetContext.FullyQualifiedName == returnType.FullyQualifiedName + && typeInTargetContext.TypeArgumentCount == returnType.TypeArgumentCount; } public static Modifiers ConvertModifier(ModifierEnum modifiers, ClassFinder targetContext) diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/CodeSnippetConverterTests.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/CodeSnippetConverterTests.cs index 5b6f7ba4b4..5830ab6e7f 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/CodeSnippetConverterTests.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/CodeSnippetConverterTests.cs @@ -103,6 +103,30 @@ namespace ICSharpCode.SharpDevelop.Dom.Tests Assert.AreEqual("CInt(-35L)", converter.CSharpToVB("(int)(-35L)", out errors)); } + [Test] + public void ConvertCharToInteger() + { + Assert.AreEqual("AscW(\"x\"C)", converter.CSharpToVB("(int)'x'", out errors)); + } + + [Test] + public void ConvertCharToByte() + { + Assert.AreEqual("CByte(AscW(\"x\"C))", converter.CSharpToVB("(byte)'x'", out errors)); + } + + [Test] + public void ConvertIntegerToChar() + { + Assert.AreEqual("ChrW(65)", converter.CSharpToVB("(char)65", out errors)); + } + + [Test] + public void ConvertByteToChar() + { + Assert.AreEqual("ChrW(CByte(65))", converter.CSharpToVB("(char)(byte)65", out errors)); + } + string Normalize(string text) { return text.Replace("\t", " ").Replace("\r", "").Trim(); diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/ICSharpCode.SharpDevelop.Dom.Tests.csproj b/src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/ICSharpCode.SharpDevelop.Dom.Tests.csproj index b2687d5318..797956af9c 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/ICSharpCode.SharpDevelop.Dom.Tests.csproj +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/ICSharpCode.SharpDevelop.Dom.Tests.csproj @@ -50,6 +50,7 @@ + diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/ImplementInterfaceTests.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/ImplementInterfaceTests.cs new file mode 100644 index 0000000000..62259e718d --- /dev/null +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/ImplementInterfaceTests.cs @@ -0,0 +1,59 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using ICSharpCode.NRefactory.Ast; +using ICSharpCode.NRefactory.PrettyPrinter; +using ICSharpCode.SharpDevelop.Dom.Refactoring; +using NUnit.Framework; + +namespace ICSharpCode.SharpDevelop.Dom.Tests +{ + [TestFixture] + public class ImplementInterfaceTests + { + [Test] + public void NestedInterfaceInGenericClass() + { + // See SD2-1626 + DefaultProjectContent pc = new DefaultProjectContent(); + pc.ReferencedContents.Add(SharedProjectContentRegistryForTests.Instance.Mscorlib); + + DefaultCompilationUnit cu = new DefaultCompilationUnit(pc); + DefaultClass container = new DefaultClass(cu, "TestClass"); + container.TypeParameters.Add(new DefaultTypeParameter(container, "T", 0)); + + DefaultClass innerClass = new DefaultClass(cu, container); + innerClass.FullyQualifiedName = "TestClass.INestedInterface"; + innerClass.ClassType = ClassType.Interface; + innerClass.TypeParameters.Add(new DefaultTypeParameter(innerClass, "T", 0)); + innerClass.Properties.Add(new DefaultProperty(innerClass, "P") { + ReturnType = new GenericReturnType(innerClass.TypeParameters[0]), + CanGet = true + }); + container.InnerClasses.Add(innerClass); + pc.AddClassToNamespaceList(container); + + DefaultClass targetClass = new DefaultClass(cu, "TargetClass"); + List nodes = new List(); + + IReturnType interf = new SearchClassReturnType(pc, targetClass, 0, 0, "TestClass.INestedInterface", 1); + interf = new ConstructedReturnType(interf, new IReturnType[] { SharedProjectContentRegistryForTests.Instance.Mscorlib.GetClass("System.String", 0).DefaultReturnType }); + + CSharpCodeGenerator codeGen = new CSharpCodeGenerator(); + codeGen.ImplementInterface(nodes, interf, true, targetClass); + + Assert.AreEqual(1, nodes.Count); + CSharpOutputVisitor output = new CSharpOutputVisitor(); + output.Options.IndentationChar = ' '; + output.Options.IndentSize = 2; + nodes[0].AcceptVisitor(output, null); + Assert.AreEqual("string TestClass.INestedInterface.P {\n get {\n throw new NotImplementedException();\n }\n}", output.Text.Replace("\r", "").Trim()); + } + } +} diff --git a/src/Setup/Files.wxs b/src/Setup/Files.wxs index 8925c4e6a2..868841eef6 100644 --- a/src/Setup/Files.wxs +++ b/src/Setup/Files.wxs @@ -1174,10 +1174,14 @@ --> - + + + - + + + @@ -1215,10 +1219,14 @@ - + + + - + + + @@ -1238,10 +1246,14 @@ - + + + - + + +