From 1538282335e7b6c59cb38c76caaee44c0818fd8f Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 21 Jan 2006 14:23:10 +0000 Subject: [PATCH] C# <-> VB converter now converts P/Invoke declarations. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@1018 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/ConvertVisitor.cs | 2 +- .../Test/MemberTests.cs | 10 + .../VBNetFormattingStrategy.cs | 6 +- .../Project/Resources/VBNET-Mode.xshd | 11 +- .../Project/Src/Lexer/VBNet/Lexer.cs | 278 +++++++++--------- .../Src/Output/CSharp/CSharpOutputVisitor.cs | 39 +-- .../Src/Output/VBNet/VBNetOutputVisitor.cs | 28 +- .../Project/Src/Parser/AST/Enums.cs | 35 +-- .../Project/Src/Parser/VBNet/Parser.cs | 8 +- .../Project/Src/Parser/VBNet/VBNET.ATG | 8 +- .../Parser/Visitors/ToVBNetConvertVisitor.cs | 119 ++++++++ .../Visitors/VBNetConstructsConvertVisitor.cs | 112 +++++++ .../Output/CSharp/VBToCSharpConverterTest.cs | 39 ++- .../Output/VBNet/CSharpToVBConverterTest.cs | 31 +- .../TypeLevel/DeclareDeclarationTests.cs | 4 +- .../TypeLevel/MethodDeclarationTests.cs | 1 + .../Project/Src/Dom/CodeCompletionOptions.cs | 2 +- .../Gui/Dialogs/SharpDevelopAboutPanels.cs | 1 + .../Base/Project/Src/Project/MSBuildEngine.cs | 4 + 19 files changed, 503 insertions(+), 235 deletions(-) diff --git a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ConvertVisitor.cs b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ConvertVisitor.cs index faf55af3e5..c85b8088ee 100644 --- a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ConvertVisitor.cs +++ b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Project/ConvertVisitor.cs @@ -129,7 +129,7 @@ namespace NRefactoryToBooConverter r |= B.TypeMemberModifiers.Partial; } if ((m & Modifier.Extern) != 0) { - AddError(node, "Extern modifier is not supported"); + // not necessary in Boo } if ((m & Modifier.Volatile) != 0) { AddError(node, "Volatile modifier is not supported"); diff --git a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Test/MemberTests.cs b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Test/MemberTests.cs index 5511af011b..0ed55fb270 100644 --- a/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Test/MemberTests.cs +++ b/src/AddIns/BackendBindings/Boo/NRefactoryToBooConverter/Test/MemberTests.cs @@ -250,5 +250,15 @@ namespace NRefactoryToBooConverter.Tests { TestInClass("[LookHere] event EventHandler Closed;", "[LookHere]\nprivate event Closed as EventHandler"); } + + [Test] + public void PInvoke() + { + TestInClass("[DllImport(\"User32.dll\", CharSet = CharSet.Auto)]\n" + + "static extern IntPtr MessageBox(int etc);", + "[DllImport('User32.dll', CharSet: CharSet.Auto)]\n" + + "private static def MessageBox(etc as System.Int32) as IntPtr:\n" + + "\tpass"); + } } } diff --git a/src/AddIns/BackendBindings/VBNetBinding/Project/Src/FormattingStrategy/VBNetFormattingStrategy.cs b/src/AddIns/BackendBindings/VBNetBinding/Project/Src/FormattingStrategy/VBNetFormattingStrategy.cs index 7b9fd3c493..d9e53af5e6 100644 --- a/src/AddIns/BackendBindings/VBNetBinding/Project/Src/FormattingStrategy/VBNetFormattingStrategy.cs +++ b/src/AddIns/BackendBindings/VBNetBinding/Project/Src/FormattingStrategy/VBNetFormattingStrategy.cs @@ -46,9 +46,9 @@ namespace VBNetBinding.FormattingStrategy statements.Add(new VBStatement("\\bstructure \\w+$", "^end structure$", "End Structure", 1)); statements.Add(new VBStatement("^while ", "^end while$", "End While", 1)); statements.Add(new VBStatement("^select case", "^end select$", "End Select", 2)); - statements.Add(new VBStatement("(? - @@ -188,7 +187,6 @@ - @@ -212,7 +210,6 @@ - @@ -236,6 +233,14 @@ + + + + + + + + diff --git a/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Lexer.cs b/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Lexer.cs index 55a32b0359..3604f26519 100644 --- a/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Lexer.cs +++ b/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Lexer.cs @@ -54,171 +54,173 @@ namespace ICSharpCode.NRefactory.Parser.VB protected override Token Next() { - int nextChar; - while ((nextChar = ReaderRead()) != -1) { - char ch = (char)nextChar; - if (Char.IsWhiteSpace(ch)) { - int x = Col - 1; - int y = Line; - if (HandleLineEnd(ch)) { - if (!lineEnd) { - lineEnd = true; - return new Token(Tokens.EOL, x, y); - } - } - continue; - } - if (ch == '_') { - if (ReaderPeek() == -1) { - errors.Error(Line, Col, String.Format("No EOF expected after _")); - return new Token(Tokens.EOF); - } - if (!Char.IsWhiteSpace((char)ReaderPeek())) { + unchecked { + int nextChar; + while ((nextChar = ReaderRead()) != -1) { + char ch = (char)nextChar; + if (Char.IsWhiteSpace(ch)) { int x = Col - 1; int y = Line; - string s = ReadIdent('_'); - lineEnd = false; - return new Token(Tokens.Identifier, x, y, s); - } - ch = (char)ReaderRead(); - - lineEnd = false; - while (Char.IsWhiteSpace(ch)) { if (HandleLineEnd(ch)) { - lineEnd = true; - break; + if (!lineEnd) { + lineEnd = true; + return new Token(Tokens.EOL, x, y); + } } - if (ReaderPeek() != -1) { - ch = (char)ReaderRead(); - } else { + continue; + } + if (ch == '_') { + if (ReaderPeek() == -1) { errors.Error(Line, Col, String.Format("No EOF expected after _")); return new Token(Tokens.EOF); } + if (!Char.IsWhiteSpace((char)ReaderPeek())) { + int x = Col - 1; + int y = Line; + string s = ReadIdent('_'); + lineEnd = false; + return new Token(Tokens.Identifier, x, y, s); + } + ch = (char)ReaderRead(); + + lineEnd = false; + while (Char.IsWhiteSpace(ch)) { + if (HandleLineEnd(ch)) { + lineEnd = true; + break; + } + if (ReaderPeek() != -1) { + ch = (char)ReaderRead(); + } else { + errors.Error(Line, Col, String.Format("No EOF expected after _")); + return new Token(Tokens.EOF); + } + } + if (!lineEnd) { + errors.Error(Line, Col, String.Format("Return expected")); + } + lineEnd = false; + continue; } - if (!lineEnd) { - errors.Error(Line, Col, String.Format("Return expected")); - } - lineEnd = false; - continue; - } - - if (ch == '#') { - while (Char.IsWhiteSpace((char)ReaderPeek())) { - ReaderRead(); + + if (ch == '#') { + while (Char.IsWhiteSpace((char)ReaderPeek())) { + ReaderRead(); + } + if (Char.IsDigit((char)ReaderPeek())) { + int x = Col - 1; + int y = Line; + string s = ReadDate(); + DateTime time = new DateTime(1, 1, 1, 0, 0, 0); + try { + time = DateTime.Parse(s, System.Globalization.CultureInfo.InvariantCulture, DateTimeStyles.NoCurrentDateDefault); + } catch (Exception e) { + errors.Error(Line, Col, String.Format("Invalid date time {0}", e)); + } + return new Token(Tokens.LiteralDate, x, y, s, time); + } else { + ReadPreprocessorDirective(); + continue; + } } - if (Char.IsDigit((char)ReaderPeek())) { + + if (ch == '[') { // Identifier + lineEnd = false; + if (ReaderPeek() == -1) { + errors.Error(Line, Col, String.Format("Identifier expected")); + } + ch = (char)ReaderRead(); + if (ch == ']' || Char.IsWhiteSpace(ch)) { + errors.Error(Line, Col, String.Format("Identifier expected")); + } int x = Col - 1; int y = Line; - string s = ReadDate(); - DateTime time = new DateTime(1, 1, 1, 0, 0, 0); - try { - time = DateTime.Parse(s, System.Globalization.CultureInfo.InvariantCulture, DateTimeStyles.NoCurrentDateDefault); - } catch (Exception e) { - errors.Error(Line, Col, String.Format("Invalid date time {0}", e)); + string s = ReadIdent(ch); + if (ReaderPeek() == -1) { + errors.Error(Line, Col, String.Format("']' expected")); } - return new Token(Tokens.LiteralDate, x, y, s, time); - } else { - ReadPreprocessorDirective(); - continue; - } - } - - if (ch == '[') { // Identifier - lineEnd = false; - if (ReaderPeek() == -1) { - errors.Error(Line, Col, String.Format("Identifier expected")); - } - ch = (char)ReaderRead(); - if (ch == ']' || Char.IsWhiteSpace(ch)) { - errors.Error(Line, Col, String.Format("Identifier expected")); + ch = (char)ReaderRead(); + if (!(ch == ']')) { + errors.Error(Line, Col, String.Format("']' expected")); + } + return new Token(Tokens.Identifier, x, y, s); } - int x = Col - 1; - int y = Line; - string s = ReadIdent(ch); - if (ReaderPeek() == -1) { - errors.Error(Line, Col, String.Format("']' expected")); + if (Char.IsLetter(ch)) { + int x = Col - 1; + int y = Line; + string s = ReadIdent(ch); + int keyWordToken = Keywords.GetToken(s); + if (keyWordToken >= 0) { + lineEnd = false; + return new Token(keyWordToken, x, y, s); + } + + // handle 'REM' comments + if (s.Equals("REM", StringComparison.InvariantCultureIgnoreCase)) { + ReadComment(); + if (!lineEnd) { + lineEnd = true; + return new Token(Tokens.EOL, Col, Line, "\n"); + } + continue; + } + + lineEnd = false; + return new Token(Tokens.Identifier, x, y, s); + } - ch = (char)ReaderRead(); - if (!(ch == ']')) { - errors.Error(Line, Col, String.Format("']' expected")); + if (Char.IsDigit(ch)) { + lineEnd = false; + return ReadDigit(ch, Col - 1); } - return new Token(Tokens.Identifier, x, y, s); - } - if (Char.IsLetter(ch)) { - int x = Col - 1; - int y = Line; - string s = ReadIdent(ch); - int keyWordToken = Keywords.GetToken(s); - if (keyWordToken >= 0) { + if (ch == '&') { lineEnd = false; - return new Token(keyWordToken, x, y, s); + if (ReaderPeek() == -1) { + return ReadOperator('&'); + } + ch = (char)ReaderPeek(); + if (Char.ToUpper(ch, CultureInfo.InvariantCulture) == 'H' || Char.ToUpper(ch, CultureInfo.InvariantCulture) == 'O') { + return ReadDigit('&', Col - 1); + } + return ReadOperator('&'); } - - // handle 'REM' comments - if (s.Equals("REM", StringComparison.InvariantCultureIgnoreCase)) { + if (ch == '\'' || ch == '\u2018' || ch == '\u2019') { + int x = Col - 1; + int y = Line; ReadComment(); if (!lineEnd) { lineEnd = true; - return new Token(Tokens.EOL, Col, Line, "\n"); + return new Token(Tokens.EOL, x, y, "\n"); } continue; } - - lineEnd = false; - return new Token(Tokens.Identifier, x, y, s); - - } - if (Char.IsDigit(ch)) { - lineEnd = false; - return ReadDigit(ch, Col - 1); - } - if (ch == '&') { - lineEnd = false; - if (ReaderPeek() == -1) { - return ReadOperator('&'); - } - ch = (char)ReaderPeek(); - if (Char.ToUpper(ch, CultureInfo.InvariantCulture) == 'H' || Char.ToUpper(ch, CultureInfo.InvariantCulture) == 'O') { - return ReadDigit('&', Col - 1); - } - return ReadOperator('&'); - } - if (ch == '\'' || ch == '\u2018' || ch == '\u2019') { - int x = Col - 1; - int y = Line; - ReadComment(); - if (!lineEnd) { - lineEnd = true; - return new Token(Tokens.EOL, x, y, "\n"); - } - continue; - } - if (ch == '"') { - lineEnd = false; - int x = Col - 1; - int y = Line; - string s = ReadString(); - if (ReaderPeek() != -1 && (ReaderPeek() == 'C' || ReaderPeek() == 'c')) { - ReaderRead(); - if (s.Length != 1) { - errors.Error(Line, Col, String.Format("Chars can only have Length 1 ")); - } - if (s.Length == 0) { - s = "\0"; + if (ch == '"') { + lineEnd = false; + int x = Col - 1; + int y = Line; + string s = ReadString(); + if (ReaderPeek() != -1 && (ReaderPeek() == 'C' || ReaderPeek() == 'c')) { + ReaderRead(); + if (s.Length != 1) { + errors.Error(Line, Col, String.Format("Chars can only have Length 1 ")); + } + if (s.Length == 0) { + s = "\0"; + } + return new Token(Tokens.LiteralCharacter, x, y, '"' + s + "\"C", s[0]); } - return new Token(Tokens.LiteralCharacter, x, y, '"' + s + "\"C", s[0]); + return new Token(Tokens.LiteralString, x, y, '"' + s + '"', s); } - return new Token(Tokens.LiteralString, x, y, '"' + s + '"', s); - } - Token token = ReadOperator(ch); - if (token != null) { - lineEnd = false; - return token; + Token token = ReadOperator(ch); + if (token != null) { + lineEnd = false; + return token; + } + errors.Error(Line, Col, String.Format("Unknown char({0}) which can't be read", ch)); } - errors.Error(Line, Col, String.Format("Unknown char({0}) which can't be read", ch)); + + return new Token(Tokens.EOF); } - - return new Token(Tokens.EOF); } string ReadIdent(char ch) diff --git a/src/Libraries/NRefactory/Project/Src/Output/CSharp/CSharpOutputVisitor.cs b/src/Libraries/NRefactory/Project/Src/Output/CSharp/CSharpOutputVisitor.cs index ee2cac3266..fb1b860413 100644 --- a/src/Libraries/NRefactory/Project/Src/Output/CSharp/CSharpOutputVisitor.cs +++ b/src/Libraries/NRefactory/Project/Src/Output/CSharp/CSharpOutputVisitor.cs @@ -794,44 +794,7 @@ namespace ICSharpCode.NRefactory.PrettyPrinter public object Visit(DeclareDeclaration declareDeclaration, object data) { - VisitAttributes(declareDeclaration.Attributes, data); - outputFormatter.Indent(); - outputFormatter.PrintText(String.Format("[System.Runtime.InteropServices.DllImport({0}", declareDeclaration.Library)); - if (declareDeclaration.Alias != null && declareDeclaration.Alias.Length >0) { - outputFormatter.PrintText(String.Format(", EntryPoint={0}", declareDeclaration.Alias)); - } - - switch (declareDeclaration.Charset) { - case CharsetModifier.ANSI: - outputFormatter.PrintText(", CharSet=System.Runtime.InteropServices.CharSet.Ansi"); - break; - case CharsetModifier.Unicode: - outputFormatter.PrintText(", CharSet=System.Runtime.InteropServices.CharSet.Unicode"); - break; - case CharsetModifier.Auto: - outputFormatter.PrintText(", CharSet=System.Runtime.InteropServices.CharSet.Auto"); - break; - } - - outputFormatter.PrintText(")]"); - outputFormatter.NewLine(); - outputFormatter.Indent(); - - OutputModifier(declareDeclaration.Modifier); - outputFormatter.PrintToken(Tokens.Static); - outputFormatter.Space(); - outputFormatter.PrintToken(Tokens.Extern); - outputFormatter.Space(); - - nodeTracker.TrackedVisit(declareDeclaration.TypeReference, data); - outputFormatter.Space(); - outputFormatter.PrintIdentifier(declareDeclaration.Name); - - outputFormatter.PrintToken(Tokens.OpenParenthesis); - AppendCommaSeparatedList(declareDeclaration.Parameters); - outputFormatter.PrintToken(Tokens.CloseParenthesis); - outputFormatter.PrintToken(Tokens.Semicolon); - outputFormatter.NewLine(); + errors.Error(-1, -1, "DeclareDeclaration is unsupported"); return null; } #endregion diff --git a/src/Libraries/NRefactory/Project/Src/Output/VBNet/VBNetOutputVisitor.cs b/src/Libraries/NRefactory/Project/Src/Output/VBNet/VBNetOutputVisitor.cs index 5f55ee0dfa..9ef70745c0 100644 --- a/src/Libraries/NRefactory/Project/Src/Output/VBNet/VBNetOutputVisitor.cs +++ b/src/Libraries/NRefactory/Project/Src/Output/VBNet/VBNetOutputVisitor.cs @@ -189,12 +189,8 @@ namespace ICSharpCode.NRefactory.PrettyPrinter outputFormatter.Space(); } Debug.Assert(attributeSection.Attributes != null); - for (int j = 0; j < attributeSection.Attributes.Count; ++j) { - nodeTracker.TrackedVisit((INode)attributeSection.Attributes[j], data); - if (j + 1 < attributeSection.Attributes.Count) { - outputFormatter.PrintToken(Tokens.Comma); - } - } + AppendCommaSeparatedList(attributeSection.Attributes); + if ("assembly".Equals(attributeSection.AttributeTarget, StringComparison.InvariantCultureIgnoreCase) || "module".Equals(attributeSection.AttributeTarget, StringComparison.InvariantCultureIgnoreCase)) { outputFormatter.PrintText(">"); @@ -209,18 +205,14 @@ namespace ICSharpCode.NRefactory.PrettyPrinter { outputFormatter.PrintIdentifier(attribute.Name); outputFormatter.PrintToken(Tokens.OpenParenthesis); - this.AppendCommaSeparatedList(attribute.PositionalArguments); + AppendCommaSeparatedList(attribute.PositionalArguments); if (attribute.NamedArguments != null && attribute.NamedArguments.Count > 0) { if (attribute.PositionalArguments.Count > 0) { outputFormatter.PrintToken(Tokens.Comma); + outputFormatter.Space(); } - for (int i = 0; i < attribute.NamedArguments.Count; ++i) { - nodeTracker.TrackedVisit((INode)attribute.NamedArguments[i], data); - if (i + 1 < attribute.NamedArguments.Count) { - outputFormatter.PrintToken(Tokens.Comma); - } - } + AppendCommaSeparatedList(attribute.NamedArguments); } outputFormatter.PrintToken(Tokens.CloseParenthesis); return null; @@ -1103,17 +1095,14 @@ namespace ICSharpCode.NRefactory.PrettyPrinter switch (declareDeclaration.Charset) { case CharsetModifier.Auto: - outputFormatter.Space(); outputFormatter.PrintToken(Tokens.Auto); outputFormatter.Space(); break; case CharsetModifier.Unicode: - outputFormatter.Space(); outputFormatter.PrintToken(Tokens.Unicode); outputFormatter.Space(); break; case CharsetModifier.ANSI: - outputFormatter.Space(); outputFormatter.PrintToken(Tokens.Ansi); outputFormatter.Space(); break; @@ -1131,13 +1120,13 @@ namespace ICSharpCode.NRefactory.PrettyPrinter outputFormatter.Space(); outputFormatter.PrintToken(Tokens.Lib); outputFormatter.Space(); - outputFormatter.PrintText('"' + declareDeclaration.Library + '"'); + outputFormatter.PrintText('"' + ConvertString(declareDeclaration.Library) + '"'); outputFormatter.Space(); if (declareDeclaration.Alias.Length > 0) { outputFormatter.PrintToken(Tokens.Alias); outputFormatter.Space(); - outputFormatter.PrintText('"' + declareDeclaration.Alias + '"'); + outputFormatter.PrintText('"' + ConvertString(declareDeclaration.Alias) + '"'); outputFormatter.Space(); } @@ -2556,9 +2545,8 @@ namespace ICSharpCode.NRefactory.PrettyPrinter outputFormatter.Space(); } - // TODO : Extern if ((modifier & Modifier.Extern) == Modifier.Extern) { - errors.Error(-1, -1, String.Format("'Extern' modifier not convertable")); + // not required in VB } // TODO : Volatile diff --git a/src/Libraries/NRefactory/Project/Src/Parser/AST/Enums.cs b/src/Libraries/NRefactory/Project/Src/Parser/AST/Enums.cs index ccea23e27f..49cf570b7c 100644 --- a/src/Libraries/NRefactory/Project/Src/Parser/AST/Enums.cs +++ b/src/Libraries/NRefactory/Project/Src/Parser/AST/Enums.cs @@ -49,18 +49,19 @@ namespace ICSharpCode.NRefactory.Parser.AST /// Only for VB properties. WriteOnly = 0x400000, // VB specific - Classes = New | Public | Protected | Internal | Private | Abstract | Sealed | Partial | Static, - VBModules = Private | Public | Protected | Internal, - VBStructures = Private | Public | Protected | Internal | New, - VBEnums = Private | Public | Protected | Internal | New, - VBInterfacs = Private | Public | Protected | Internal | New, - VBDelegates = Private | Public | Protected | Internal | New, - VBMethods = Private | Public | Protected | Internal | New | Static | Virtual | Sealed | Abstract | Override | Overloads, - VBExternalMethods = Private | Public | Protected | Internal | New | Overloads, - VBEvents = Private | Public | Protected | Internal | New | Overloads, + Visibility = Private | Public | Protected | Internal, + Classes = New | Visibility | Abstract | Sealed | Partial | Static, + VBModules = Visibility, + VBStructures = Visibility | New, + VBEnums = Visibility | New, + VBInterfacs = Visibility | New, + VBDelegates = Visibility | New, + VBMethods = Visibility | New | Static | Virtual | Sealed | Abstract | Override | Overloads, + VBExternalMethods = Visibility | New | Overloads, + VBEvents = Visibility | New | Overloads, VBProperties = VBMethods | Default | ReadOnly | WriteOnly, - VBCustomEvents = Private | Public | Protected | Internal | New | Overloads, - VBOperators = Public | Static | Overloads | New | Widening | Narrowing, + VBCustomEvents = Visibility | New | Overloads, + VBOperators = Public | Static | Overloads | New | Widening | Narrowing, // this is not documented in the spec @@ -69,15 +70,15 @@ namespace ICSharpCode.NRefactory.Parser.AST VBInterfaceProperties = New | Overloads | ReadOnly | WriteOnly | Default, VBInterfaceEnums = New, - Fields = New | Public | Protected | Internal | Private | Static | ReadOnly | Volatile, - PropertysEventsMethods = New | Public | Protected | Internal | Private | Static | Virtual | Sealed | Override | Abstract | Extern, - Indexers = New | Public | Protected | Internal | Private | Virtual | Sealed | Override | Abstract | Extern, + Fields = New | Visibility | Static | ReadOnly | Volatile, + PropertysEventsMethods = New | Visibility | Static | Virtual | Sealed | Override | Abstract | Extern, + Indexers = New | Visibility | Virtual | Sealed | Override | Abstract | Extern, Operators = Public | Static | Extern, - Constants = New | Public | Protected | Internal | Private, - StructsInterfacesEnumsDelegates = New | Public | Protected | Internal | Private | Partial, + Constants = New | Visibility, + StructsInterfacesEnumsDelegates = New | Visibility | Partial, StaticConstructors = Extern | Static | Unsafe, Destructors = Extern | Unsafe, - Constructors = Public | Protected | Internal | Private | Extern, + Constructors = Visibility | Extern, } public enum ClassType diff --git a/src/Libraries/NRefactory/Project/Src/Parser/VBNet/Parser.cs b/src/Libraries/NRefactory/Project/Src/Parser/VBNet/Parser.cs index 9d570e3eb3..9e796267b6 100644 --- a/src/Libraries/NRefactory/Project/Src/Parser/VBNet/Parser.cs +++ b/src/Libraries/NRefactory/Project/Src/Parser/VBNet/Parser.cs @@ -1913,13 +1913,13 @@ out charsetModifer); Expect(3); #line 1123 "VBNET.ATG" - library = t.val.ToString(); + library = t.literalValue.ToString(); if (la.kind == 44) { lexer.NextToken(); Expect(3); #line 1124 "VBNET.ATG" - alias = t.val.ToString(); + alias = t.literalValue.ToString(); } if (la.kind == 24) { lexer.NextToken(); @@ -1948,13 +1948,13 @@ p); Expect(3); #line 1136 "VBNET.ATG" - library = t.val; + library = t.literalValue.ToString(); if (la.kind == 44) { lexer.NextToken(); Expect(3); #line 1137 "VBNET.ATG" - alias = t.val; + alias = t.literalValue.ToString(); } if (la.kind == 24) { lexer.NextToken(); diff --git a/src/Libraries/NRefactory/Project/Src/Parser/VBNet/VBNET.ATG b/src/Libraries/NRefactory/Project/Src/Parser/VBNet/VBNET.ATG index be6e1985e3..e28f19be1b 100644 --- a/src/Libraries/NRefactory/Project/Src/Parser/VBNet/VBNET.ATG +++ b/src/Libraries/NRefactory/Project/Src/Parser/VBNet/VBNET.ATG @@ -1120,8 +1120,8 @@ StructureMemberDecl attributes> ( "Sub" Identifier (. name = t.val; .) - "Lib" LiteralString (. library = t.val.ToString(); .) - ["Alias" LiteralString (. alias = t.val.ToString(); .)] + "Lib" LiteralString (. library = t.literalValue.ToString(); .) + ["Alias" LiteralString (. alias = t.literalValue.ToString(); .)] [ "(" [ FormalParameterList

] ")" ] EOL (. @@ -1133,8 +1133,8 @@ StructureMemberDecl attributes> | "Function" Identifier (. name = t.val; .) - "Lib" LiteralString (. library = t.val; .) - ["Alias" LiteralString (. alias = t.val; .)] + "Lib" LiteralString (. library = t.literalValue.ToString(); .) + ["Alias" LiteralString (. alias = t.literalValue.ToString(); .)] [ "(" [ FormalParameterList

] ")" ] ["As" TypeName ] EOL diff --git a/src/Libraries/NRefactory/Project/Src/Parser/Visitors/ToVBNetConvertVisitor.cs b/src/Libraries/NRefactory/Project/Src/Parser/Visitors/ToVBNetConvertVisitor.cs index 8aa4b18291..abf437c711 100644 --- a/src/Libraries/NRefactory/Project/Src/Parser/Visitors/ToVBNetConvertVisitor.cs +++ b/src/Libraries/NRefactory/Project/Src/Parser/Visitors/ToVBNetConvertVisitor.cs @@ -13,6 +13,7 @@ using System.Diagnostics; using ICSharpCode.NRefactory.Parser; using ICSharpCode.NRefactory.Parser.AST; +using Attribute = ICSharpCode.NRefactory.Parser.AST.Attribute; namespace ICSharpCode.NRefactory.Parser { @@ -146,5 +147,123 @@ namespace ICSharpCode.NRefactory.Parser } return base.Visit(assignmentExpression, data); } + + public override object Visit(MethodDeclaration methodDeclaration, object data) + { + if ((methodDeclaration.Modifier & Modifier.Visibility) == 0) + methodDeclaration.Modifier |= Modifier.Private; + + base.Visit(methodDeclaration, data); + + const Modifier externStatic = Modifier.Static | Modifier.Extern; + if ((methodDeclaration.Modifier & externStatic) == externStatic + && methodDeclaration.Body.IsNull) + { + foreach (AttributeSection sec in methodDeclaration.Attributes) { + foreach (Attribute att in sec.Attributes) { + if ("DllImport".Equals(att.Name, StringComparison.InvariantCultureIgnoreCase)) { + if (ConvertPInvoke(methodDeclaration, att)) { + sec.Attributes.Remove(att); + break; + } + } + } + if (sec.Attributes.Count == 0) { + methodDeclaration.Attributes.Remove(sec); + break; + } + } + } + return null; + } + + bool ConvertPInvoke(MethodDeclaration method, ICSharpCode.NRefactory.Parser.AST.Attribute att) + { + if (att.PositionalArguments.Count != 1) + return false; + PrimitiveExpression pe = att.PositionalArguments[0] as PrimitiveExpression; + if (pe == null || !(pe.Value is string)) + return false; + string libraryName = (string)pe.Value; + string alias = null; + bool setLastError = false; + bool exactSpelling = false; + CharsetModifier charSet = CharsetModifier.Auto; + foreach (NamedArgumentExpression arg in att.NamedArguments) { + switch (arg.Name) { + case "SetLastError": + pe = arg.Expression as PrimitiveExpression; + if (pe != null && pe.Value is bool) + setLastError = (bool)pe.Value; + else + return false; + break; + case "ExactSpelling": + pe = arg.Expression as PrimitiveExpression; + if (pe != null && pe.Value is bool) + exactSpelling = (bool)pe.Value; + else + return false; + break; + case "CharSet": + { + FieldReferenceExpression fre = arg.Expression as FieldReferenceExpression; + if (fre == null || !(fre.TargetObject is IdentifierExpression)) + return false; + if ((fre.TargetObject as IdentifierExpression).Identifier != "CharSet") + return false; + switch (fre.FieldName) { + case "Unicode": + charSet = CharsetModifier.Unicode; + break; + case "Auto": + charSet = CharsetModifier.Auto; + break; + case "Ansi": + charSet = CharsetModifier.ANSI; + break; + default: + return false; + } + } + break; + case "EntryPoint": + pe = arg.Expression as PrimitiveExpression; + if (pe != null) + alias = pe.Value as string; + break; + default: + return false; + } + } + if (setLastError && exactSpelling) { + // Only P/Invokes with SetLastError and ExactSpelling can be converted to a DeclareDeclaration + const Modifier removeModifiers = Modifier.Static | Modifier.Extern; + DeclareDeclaration decl = new DeclareDeclaration(method.Name, method.Modifier &~ removeModifiers, + method.TypeReference, + method.Parameters, + method.Attributes, + libraryName, alias, charSet); + ReplaceCurrentNode(decl); + base.Visit(decl, null); + return true; + } else { + return false; + } + } + + public override object Visit(PropertyDeclaration propertyDeclaration, object data) + { + if ((propertyDeclaration.Modifier & Modifier.Visibility) == 0) + propertyDeclaration.Modifier |= Modifier.Private; + return base.Visit(propertyDeclaration, data); + } + + public override object Visit(ConstructorDeclaration constructorDeclaration, object data) + { + if ((constructorDeclaration.Modifier & Modifier.Visibility) == 0) + constructorDeclaration.Modifier |= Modifier.Private; + return base.Visit(constructorDeclaration, data); + } } } diff --git a/src/Libraries/NRefactory/Project/Src/Parser/Visitors/VBNetConstructsConvertVisitor.cs b/src/Libraries/NRefactory/Project/Src/Parser/Visitors/VBNetConstructsConvertVisitor.cs index 5a5fd8af3d..7d63318cf6 100644 --- a/src/Libraries/NRefactory/Project/Src/Parser/Visitors/VBNetConstructsConvertVisitor.cs +++ b/src/Libraries/NRefactory/Project/Src/Parser/Visitors/VBNetConstructsConvertVisitor.cs @@ -14,6 +14,7 @@ using System.Diagnostics; using ICSharpCode.NRefactory.Parser; using ICSharpCode.NRefactory.Parser.VB; using ICSharpCode.NRefactory.Parser.AST; +using Attribute = ICSharpCode.NRefactory.Parser.AST.Attribute; namespace ICSharpCode.NRefactory.Parser { @@ -24,12 +25,46 @@ namespace ICSharpCode.NRefactory.Parser { // The following conversions are implemented: // MyBase.New() and MyClass.New() calls inside the constructor are converted to :base() and :this() + // Add Public Modifier to methods and properties // The following conversions should be implemented in the future: // Function A() \n A = SomeValue \n End Function -> convert to return statement + Dictionary usings; + List addedUsings; + + public override object Visit(CompilationUnit compilationUnit, object data) + { + usings = new Dictionary(StringComparer.InvariantCultureIgnoreCase); + addedUsings = new List(); + base.Visit(compilationUnit, data); + int i; + for (i = 0; i < compilationUnit.Children.Count; i++) { + if (!(compilationUnit.Children[i] is UsingDeclaration)) + break; + } + foreach (UsingDeclaration decl in addedUsings) { + decl.Parent = compilationUnit; + compilationUnit.Children.Insert(i++, decl); + } + usings = null; + addedUsings = null; + return null; + } + + public override object Visit(Using @using, object data) + { + if (!@using.IsAlias) { + usings[@using.Name] = @using.Name; + } + return base.Visit(@using, data); + } + public override object Visit(ConstructorDeclaration constructorDeclaration, object data) { + if ((constructorDeclaration.Modifier & Modifier.Visibility) == 0) + constructorDeclaration.Modifier = Modifier.Public; + // MyBase.New() and MyClass.New() calls inside the constructor are converted to :base() and :this() BlockStatement body = constructorDeclaration.Body; if (body != null && body.Children.Count > 0) { @@ -55,5 +90,82 @@ namespace ICSharpCode.NRefactory.Parser } return base.Visit(constructorDeclaration, data); } + + public override object Visit(DeclareDeclaration declareDeclaration, object data) + { + if (!usings.ContainsKey("System.Runtime.InteropServices")) { + UsingDeclaration @using = new UsingDeclaration("System.Runtime.InteropServices"); + addedUsings.Add(@using); + base.Visit(@using, data); + } + + MethodDeclaration method = new MethodDeclaration(declareDeclaration.Name, declareDeclaration.Modifier, + declareDeclaration.TypeReference, declareDeclaration.Parameters, + declareDeclaration.Attributes); + method.Modifier |= Modifier.Extern | Modifier.Static; + ICSharpCode.NRefactory.Parser.AST.Attribute att = new Attribute("DllImport", null, null); + att.PositionalArguments.Add(CreateStringLiteral(declareDeclaration.Library)); + if (declareDeclaration.Alias.Length > 0) { + att.NamedArguments.Add(new NamedArgumentExpression("EntryPoint", CreateStringLiteral(declareDeclaration.Alias))); + } + switch (declareDeclaration.Charset) { + case CharsetModifier.Auto: + att.NamedArguments.Add(new NamedArgumentExpression("CharSet", + new FieldReferenceExpression(new IdentifierExpression("CharSet"), + "Auto"))); + break; + case CharsetModifier.Unicode: + att.NamedArguments.Add(new NamedArgumentExpression("CharSet", + new FieldReferenceExpression(new IdentifierExpression("CharSet"), + "Unicode"))); + break; + default: + att.NamedArguments.Add(new NamedArgumentExpression("CharSet", + new FieldReferenceExpression(new IdentifierExpression("CharSet"), + "Ansi"))); + break; + } + att.NamedArguments.Add(new NamedArgumentExpression("SetLastError", new PrimitiveExpression(true, true.ToString()))); + att.NamedArguments.Add(new NamedArgumentExpression("ExactSpelling", new PrimitiveExpression(true, true.ToString()))); + AttributeSection sec = new AttributeSection(null, null); + sec.Attributes.Add(att); + method.Attributes.Add(sec); + ReplaceCurrentNode(method); + return base.Visit(method, data); + } + + static PrimitiveExpression CreateStringLiteral(string text) + { + return new PrimitiveExpression(text, text); + } + + public override object Visit(MethodDeclaration methodDeclaration, object data) + { + if ((methodDeclaration.Modifier & Modifier.Visibility) == 0) + methodDeclaration.Modifier |= Modifier.Public; + + if ((methodDeclaration.Modifier & (Modifier.Static | Modifier.Extern)) == Modifier.Static + && methodDeclaration.Body.Children.Count == 0) + { + foreach (AttributeSection sec in methodDeclaration.Attributes) { + foreach (Attribute att in sec.Attributes) { + if ("DllImport".Equals(att.Name, StringComparison.InvariantCultureIgnoreCase)) { + methodDeclaration.Modifier |= Modifier.Extern; + methodDeclaration.Body = null; + } + } + } + } + + return base.Visit(methodDeclaration, data); + } + + public override object Visit(PropertyDeclaration propertyDeclaration, object data) + { + if ((propertyDeclaration.Modifier & Modifier.Visibility) == 0) + propertyDeclaration.Modifier = Modifier.Public; + + return base.Visit(propertyDeclaration, data); + } } } diff --git a/src/Libraries/NRefactory/Test/Output/CSharp/VBToCSharpConverterTest.cs b/src/Libraries/NRefactory/Test/Output/CSharp/VBToCSharpConverterTest.cs index e8937f6c7c..5d4f688961 100644 --- a/src/Libraries/NRefactory/Test/Output/CSharp/VBToCSharpConverterTest.cs +++ b/src/Libraries/NRefactory/Test/Output/CSharp/VBToCSharpConverterTest.cs @@ -31,8 +31,18 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter } public void TestMember(string input, string expectedOutput) + { + TestMember(input, expectedOutput, null); + } + + public void TestMember(string input, string expectedOutput, string expectedAutomaticImport) { StringBuilder b = new StringBuilder(); + if (expectedAutomaticImport != null) { + b.Append("using "); + b.Append(expectedAutomaticImport); + b.AppendLine(";"); + } b.AppendLine("class tmp1"); b.AppendLine("{"); using (StringReader r = new StringReader(expectedOutput)) { @@ -51,7 +61,7 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter StringBuilder b = new StringBuilder(); b.AppendLine("class tmp1"); b.AppendLine("{"); - b.AppendLine("\tvoid tmp2()"); + b.AppendLine("\tpublic void tmp2()"); b.AppendLine("\t{"); using (StringReader r = new StringReader(expectedOutput)) { string line; @@ -89,5 +99,32 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter TestStatement("RaiseEvent someEvent(Me, EventArgs.Empty)", "if (someEvent != null) {\n\tsomeEvent(this, EventArgs.Empty);\n}"); } + + [Test] + public void StaticMethod() + { + TestMember("Shared Sub A()\nEnd Sub", + "public static void A()\n{\n}"); + } + + [Test] + public void PInvoke() + { + TestMember("Declare Function SendMessage Lib \"user32.dll\" (ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As UIntPtr, ByVal lParam As IntPtr) As IntPtr", + "[DllImport(\"user32.dll\", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]\n" + + "static extern IntPtr SendMessage(IntPtr hWnd, int Msg, UIntPtr wParam, IntPtr lParam);", + "System.Runtime.InteropServices"); + + TestMember("Declare Unicode Function SendMessage Lib \"user32.dll\" Alias \"SendMessageW\" (ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As UIntPtr, ByVal lParam As IntPtr) As IntPtr", + "[DllImport(\"user32.dll\", EntryPoint = \"SendMessageW\", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]\n" + + "static extern IntPtr SendMessage(IntPtr hWnd, int Msg, UIntPtr wParam, IntPtr lParam);", + "System.Runtime.InteropServices"); + + TestMember(" _\n" + + "Shared Function MessageBox(ByVal hwnd As IntPtr, ByVal t As String, ByVal caption As String, ByVal t2 As UInt32) As Integer\n" + + "End Function", + "[DllImport(\"user32.dll\", CharSet = CharSet.Auto)]\n" + + "public static extern int MessageBox(IntPtr hwnd, string t, string caption, UInt32 t2);"); + } } } diff --git a/src/Libraries/NRefactory/Test/Output/VBNet/CSharpToVBConverterTest.cs b/src/Libraries/NRefactory/Test/Output/VBNet/CSharpToVBConverterTest.cs index ad2ccd1ab0..74827f7321 100644 --- a/src/Libraries/NRefactory/Test/Output/VBNet/CSharpToVBConverterTest.cs +++ b/src/Libraries/NRefactory/Test/Output/VBNet/CSharpToVBConverterTest.cs @@ -49,7 +49,7 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter { StringBuilder b = new StringBuilder(); b.AppendLine("Class tmp1"); - b.AppendLine("\tSub tmp2()"); + b.AppendLine("\tPrivate Sub tmp2()"); using (StringReader r = new StringReader(expectedOutput)) { string line; while ((line = r.ReadLine()) != null) { @@ -158,7 +158,7 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter public void AnonymousMethod() { TestMember("void A() { someEvent += delegate(int argument) { return argument * 2; }; }", - "Sub A()\n" + + "Private Sub A()\n" + "\tAddHandler someEvent, AddressOf ConvertedAnonymousMethod1\n" + "End Sub\n" + "Private Sub ConvertedAnonymousMethod1(ByVal argument As Integer)\n" + @@ -170,7 +170,7 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter public void AnonymousMethodInVarDeclaration() { TestMember("void A() { SomeDelegate i = delegate(int argument) { return argument * 2; }; }", - "Sub A()\n" + + "Private Sub A()\n" + "\tDim i As SomeDelegate = AddressOf ConvertedAnonymousMethod1\n" + "End Sub\n" + "Private Sub ConvertedAnonymousMethod1(ByVal argument As Integer)\n" + @@ -190,5 +190,30 @@ namespace ICSharpCode.NRefactory.Tests.PrettyPrinter TestStatement("someEvent += new SomeDelegate(this.tmp2);", "AddHandler someEvent, AddressOf tmp2"); } + + [Test] + public void StaticMethod() + { + TestMember("static void A() {}", + "Private Shared Sub A()\nEnd Sub"); + } + + [Test] + public void PInvoke() + { + TestMember("[DllImport(\"user32.dll\", CharSet = CharSet.Auto)]\n" + + "public static extern int MessageBox(IntPtr hwnd, string t, string caption, UInt32 t2);", + " _\n" + + "Public Shared Function MessageBox(ByVal hwnd As IntPtr, ByVal t As String, ByVal caption As String, ByVal t2 As UInt32) As Integer\n" + + "End Function"); + + TestMember("[DllImport(\"user32.dll\", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]\n" + + "public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, UIntPtr wParam, IntPtr lParam);", + "Public Declare Ansi Function SendMessage Lib \"user32.dll\" (ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As UIntPtr, ByVal lParam As IntPtr) As IntPtr"); + + TestMember("[DllImport(\"user32.dll\", SetLastError = true, ExactSpelling = true, EntryPoint = \"SendMessageW\")]\n" + + "public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, UIntPtr wParam, IntPtr lParam);", + "Public Declare Auto Function SendMessage Lib \"user32.dll\" Alias \"SendMessageW\" (ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As UIntPtr, ByVal lParam As IntPtr) As IntPtr"); + } } } diff --git a/src/Libraries/NRefactory/Test/Parser/TypeLevel/DeclareDeclarationTests.cs b/src/Libraries/NRefactory/Test/Parser/TypeLevel/DeclareDeclarationTests.cs index 4d3dcda918..8ab011d065 100644 --- a/src/Libraries/NRefactory/Test/Parser/TypeLevel/DeclareDeclarationTests.cs +++ b/src/Libraries/NRefactory/Test/Parser/TypeLevel/DeclareDeclarationTests.cs @@ -31,8 +31,8 @@ namespace ICSharpCode.NRefactory.Tests.AST DeclareDeclaration dd = ParseUtilVBNet.ParseTypeMember(program); Assert.AreEqual("System.Int32", dd.TypeReference.SystemType); Assert.AreEqual("GetUserName", dd.Name); - Assert.AreEqual("\"advapi32.dll\"", dd.Library); - Assert.AreEqual("\"GetUserNameA\"", dd.Alias); + Assert.AreEqual("advapi32.dll", dd.Library); + Assert.AreEqual("GetUserNameA", dd.Alias); Assert.AreEqual(CharsetModifier.ANSI, dd.Charset); } #endregion diff --git a/src/Libraries/NRefactory/Test/Parser/TypeLevel/MethodDeclarationTests.cs b/src/Libraries/NRefactory/Test/Parser/TypeLevel/MethodDeclarationTests.cs index d56bd44e40..e2c374c229 100644 --- a/src/Libraries/NRefactory/Test/Parser/TypeLevel/MethodDeclarationTests.cs +++ b/src/Libraries/NRefactory/Test/Parser/TypeLevel/MethodDeclarationTests.cs @@ -227,6 +227,7 @@ namespace ICSharpCode.NRefactory.Tests.AST end sub"; MethodDeclaration md = ParseUtilVBNet.ParseTypeMember(program); + Assert.AreEqual(Modifier.Public | Modifier.Static, md.Modifier); Assert.AreEqual(2, md.StartLocation.Y, "StartLocation.Y"); Assert.AreEqual(2, md.EndLocation.Y, "EndLocation.Y"); Assert.AreEqual(2, md.StartLocation.X, "StartLocation.X"); diff --git a/src/Main/Base/Project/Src/Dom/CodeCompletionOptions.cs b/src/Main/Base/Project/Src/Dom/CodeCompletionOptions.cs index e49dbaedbe..9fcc6d07e5 100644 --- a/src/Main/Base/Project/Src/Dom/CodeCompletionOptions.cs +++ b/src/Main/Base/Project/Src/Dom/CodeCompletionOptions.cs @@ -43,7 +43,7 @@ namespace ICSharpCode.SharpDevelop.Dom public static int DataUsageCacheItemCount { get { - return properties.Get("DataUsageCacheItemCount", 200); + return properties.Get("DataUsageCacheItemCount", 500); } set { properties.Set("DataUsageCacheItemCount", value); diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/SharpDevelopAboutPanels.cs b/src/Main/Base/Project/Src/Gui/Dialogs/SharpDevelopAboutPanels.cs index d1efbc91eb..50e552045e 100644 --- a/src/Main/Base/Project/Src/Gui/Dialogs/SharpDevelopAboutPanels.cs +++ b/src/Main/Base/Project/Src/Gui/Dialogs/SharpDevelopAboutPanels.cs @@ -71,6 +71,7 @@ namespace ICSharpCode.SharpDevelop.Gui Dock = DockStyle.Fill; throwExceptionButton.Location = new System.Drawing.Point(8, sponsorLabel.Bounds.Bottom + 1); + throwExceptionButton.AutoSize = true; throwExceptionButton.Text = ResourceService.GetString("Dialog.About.ThrowExceptionButton"); throwExceptionButton.Size = new System.Drawing.Size(96, 24); throwExceptionButton.Click += new EventHandler(ThrowExceptionButtonClick); diff --git a/src/Main/Base/Project/Src/Project/MSBuildEngine.cs b/src/Main/Base/Project/Src/Project/MSBuildEngine.cs index aac29d092f..c4f08a4699 100644 --- a/src/Main/Base/Project/Src/Project/MSBuildEngine.cs +++ b/src/Main/Base/Project/Src/Project/MSBuildEngine.cs @@ -301,9 +301,13 @@ namespace ICSharpCode.SharpDevelop.Project if (string.Equals(file, activeTaskName, StringComparison.InvariantCultureIgnoreCase)) { file = ""; } else { + bool isShortFileName = file == Path.GetFileNameWithoutExtension(file); if (projectFiles.Count > 0) { file = Path.Combine(Path.GetDirectoryName(projectFiles.Peek()), file); } + if (isShortFileName && !File.Exists(file)) { + file = ""; + } } CompilerError error = new CompilerError(file, lineNumber, columnNumber, code, message); error.IsWarning = isWarning;