Browse Source

Merge branch 'master' into newdecompiler

pull/728/head
Daniel Grunwald 9 years ago
parent
commit
dd20d43cf0
  1. 5
      BuildTools/Automated.proj
  2. 2
      BuildTools/buildAndCreatePackage.bat
  3. 30
      BuildTools/tidy.py
  4. 26
      ICSharpCode.Decompiler/Ast/AstBuilder.cs
  5. 34
      ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
  6. 16
      ICSharpCode.Decompiler/Ast/DecompilerContext.cs
  7. 2
      ICSharpCode.Decompiler/Ast/NameVariables.cs
  8. 4
      ICSharpCode.Decompiler/Ast/TextTokenWriter.cs
  9. 2
      ICSharpCode.Decompiler/CSharp/Transforms/DelegateConstruction.cs
  10. 56
      ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs
  11. 22
      ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
  12. 4
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  13. 1
      ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs
  14. 1
      ICSharpCode.Decompiler/ILAst/ILAstTypes.cs
  15. 19
      ICSharpCode.Decompiler/ILAst/StateRange.cs
  16. 17
      ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs
  17. 4
      ICSharpCode.Decompiler/Tests/Async.cs
  18. 5
      ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributes.cs
  19. 30
      ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpPatternTests.cs
  20. 38
      ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs
  21. 64
      ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs.Debug.cs
  22. 344
      ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs.Debug.il
  23. 64
      ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs.Release.cs
  24. 311
      ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs.Release.il
  25. 87
      ICSharpCode.Decompiler/Tests/FSharpPatterns/TestHelpers.cs
  26. 99
      ICSharpCode.Decompiler/Tests/FSharpPatterns/ToolLocator.cs
  27. 30
      ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
  28. 28
      ICSharpCode.Decompiler/Tests/NotUsingBlock.cs
  29. 1
      ICSharpCode.Decompiler/Tests/packages.config
  30. 269
      ILSpy.AddIn/CodeElementXmlDocKeyProvider.cs
  31. 14
      ILSpy.AddIn/ILSpy.AddIn.csproj
  32. 14
      ILSpy.AddIn/ILSpyAddIn.vsct
  33. 141
      ILSpy.AddIn/ILSpyAddInPackage.cs
  34. 1
      ILSpy.AddIn/PkgCmdID.cs
  35. 4
      ILSpy.AddIn/Properties/AssemblyInfo.cs
  36. 414
      ILSpy.AddIn/Samples/ILSpyAddInSamples.cs
  37. 6
      ILSpy.AddIn/Utils.cs
  38. 2
      ILSpy.AddIn/license.txt
  39. 6
      ILSpy.AddIn/source.extension.vsixmanifest
  40. 19
      ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs
  41. 16
      ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj
  42. 4
      ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlReader.cs
  43. 8
      ILSpy.BamlDecompiler/Tests/ILSpy.BamlDecompiler.Tests.csproj
  44. 1
      ILSpy.BamlDecompiler/Tests/TestRunner.cs
  45. 41
      ILSpy/AboutPage.cs
  46. 22
      ILSpy/AssemblyList.cs
  47. 31
      ILSpy/Commands/CheckForUpdatesCommand.cs
  48. 2
      ILSpy/Commands/OpenCommand.cs
  49. 2
      ILSpy/Commands/OpenFromGacCommand.cs
  50. 2
      ILSpy/Commands/OpenListCommand.cs
  51. 2
      ILSpy/Commands/RefreshCommand.cs
  52. 39
      ILSpy/Commands/SortAssemblyListCommand.cs
  53. 23
      ILSpy/ILSpy.csproj
  54. 3
      ILSpy/ILSpySettings.cs
  55. BIN
      ILSpy/Images/Sort.png
  56. 82
      ILSpy/Languages/CSharpLanguage.cs
  57. 30
      ILSpy/Languages/IResourceFileHandler.cs
  58. 89
      ILSpy/Languages/Language.cs
  59. 8
      ILSpy/MainWindow.xaml
  60. 72
      ILSpy/MainWindow.xaml.cs
  61. 10
      ILSpy/OpenListDialog.xaml.cs
  62. 15
      ILSpy/Options/DisplaySettings.cs
  63. 1
      ILSpy/Options/DisplaySettingsPanel.xaml
  64. 2
      ILSpy/Options/DisplaySettingsPanel.xaml.cs
  65. 2
      ILSpy/Options/OptionsDialog.xaml.cs
  66. 2
      ILSpy/Properties/AssemblyInfo.template.cs
  67. 12
      ILSpy/Properties/WPFAssemblyInfo.cs
  68. 6
      ILSpy/Properties/app.config.template
  69. 48
      ILSpy/SearchPane.cs
  70. 2
      ILSpy/SearchPane.xaml
  71. 106
      ILSpy/SearchStrategies.cs
  72. 5
      ILSpy/TextView/DecompilerTextView.cs
  73. 2
      ILSpy/TextView/DecompilerTextView.xaml
  74. 28
      ILSpy/TextView/EditorCommands.cs
  75. 6
      ILSpy/TreeNodes/Analyzer/RemoveAnalyzeContextMenuEntry.cs
  76. 48
      ILSpy/TreeNodes/AssemblyListTreeNode.cs
  77. 36
      ILSpy/TreeNodes/AssemblyTreeNode.cs
  78. 30
      ILSpy/TreeNodes/PropertyTreeNode.cs
  79. 40
      ILSpy/VB/ILSpyEnvironmentProvider.cs
  80. 86
      ILSpy/VB/VBLanguage.cs
  81. 63
      ILSpy/VB/VBTextOutputFormatter.cs
  82. 2
      NRefactory
  83. 35
      NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/AssemblyInfo.cs
  84. 102
      NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/General/UnitTest.cs
  85. 109
      NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/ICSharpCode.NRefactory.VB.Tests.csproj
  86. 118
      NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Lexer/CustomLexerTests.cs
  87. 230
      NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Lexer/ImplicitLineContinuationTests.cs
  88. 35
      NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Lexer/LATextReaderTests.cs
  89. 575
      NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Lexer/LexerContextTests.cs
  90. 87
      NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Lexer/LexerPositionTests.cs
  91. 1538
      NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Lexer/LexerTests.cs
  92. 194
      NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Lexer/LiteralsTests.cs
  93. 23
      NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Lexer/TokenTests.cs
  94. 993
      NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Lexer/XmlModeLexerTests.cs
  95. 22
      NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Output/CodeDOM/CodeDOMParenthesizedExpressionTest.cs
  96. 23
      NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Output/CodeDOM/CodeDOMPrimitiveExpressionTest.cs
  97. 30
      NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Output/CodeDOM/CodeDOMTypeReferenceTest.cs
  98. 59
      NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Output/CodeDOM/InvocationExpressionTest.cs
  99. 79
      NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Output/SpecialOutputVisitorTest.cs
  100. 670
      NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Output/VBNet/VBNetOutputTest.cs
  101. Some files were not shown because too many files have changed in this diff Show More

5
BuildTools/Automated.proj

@ -9,6 +9,7 @@ @@ -9,6 +9,7 @@
<ProjectDir Condition=" '$(ProjectDir)' == '' ">$(MSBuildProjectDirectory)\..</ProjectDir>
<ILSpyBin>$(ProjectDir)\ILSpy\bin\Release</ILSpyBin>
<VsixBin>$(ProjectDir)\ILSpy.AddIn\bin\Release</VsixBin>
<MSBuildCommunityTasksPath>$(ProjectDir)\BuildTools\MSBuildCommunityTasks</MSBuildCommunityTasksPath>
<ArtefactPrefix>ILSpy_</ArtefactPrefix>
@ -17,7 +18,7 @@ @@ -17,7 +18,7 @@
properties available for the projects inside the solution
(but this works using the command line) -->
<!-- C) We need to use MSBuild 4.0, but the build server uses MSBuild 2.0 -->
<MSBuildExecutable>&quot;$(MSBuildBinPath)\..\v4.0.30319\msbuild.exe&quot;</MSBuildExecutable>
<MSBuildExecutable>&quot;$(MSBuildBinPath)\msbuild.exe&quot;</MSBuildExecutable>
<BuildProperties>/p:Configuration=Release &quot;/p:Platform=Any CPU&quot;</BuildProperties>
<BuildProperties>$(BuildProperties) &quot;/p:BranchName=$(BranchName)&quot;</BuildProperties>
<BuildProperties>$(BuildProperties) $(AdditionalBuildProperties)</BuildProperties>
@ -92,6 +93,8 @@ @@ -92,6 +93,8 @@
ZipLevel="9"
WorkingDirectory="$(ILSpyBin)"
ZipFileName="$(ArtefactsOutputDir)\$(ArtefactPrefix)$(BuildNumber)_Binaries.zip"/>
<Copy SourceFiles="$(VsixBin)\ILSpy.AddIn.vsix"
DestinationFiles="$(ArtefactsOutputDir)\$(ArtefactPrefix)$(BuildNumber)_Addin.vsix"/>
</Target>
<Target Name="zipsource">

2
BuildTools/buildAndCreatePackage.bat

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
@echo This script simulates what the build server is doing
@rem /p:AdditionalBuildProperties="/v:d /p:MSBuildTargetsVerbose=true"
%windir%\microsoft.net\framework\v4.0.30319\msbuild Automated.proj /p:ArtefactsOutputDir="%CD%\build" /p:TestReportsDir="%CD%\build"
"%ProgramFiles(x86)%\MSBuild\14.0\Bin\msbuild.exe" Automated.proj /p:ArtefactsOutputDir="%CD%\build" /p:TestReportsDir="%CD%\build"
@IF %ERRORLEVEL% NEQ 0 GOTO err
@exit /B 0
:err

30
BuildTools/tidy.py

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
import os, sys
def check(filename):
ok = True
with open(filename, 'r') as f:
for i, line in enumerate(f):
if line.startswith(' '):
print('{}:{}: Line starting with spaces. Use tabs for indentation instead!'.format(filename, i+1))
ok = False
return ok
def main():
root_dir = os.path.normpath(os.path.join(os.path.dirname(__file__), '..'))
dirs_to_check = (
os.path.join(root_dir, subdir)
for subdir in ('ICSharpCode.Decompiler', 'ILSpy', 'ILSpy.BamlDecompiler'))
ok = True
for dir in dirs_to_check:
for root, dirs, files in os.walk(dir):
if '\\obj\\' in root:
continue
for filename in files:
if filename.lower().endswith('.cs'):
if not check(os.path.join(root, filename)):
ok = False
print('Tidy check: {}'.format('successful' if ok else 'failed'))
return 0 if ok else 1
if __name__ == '__main__':
sys.exit(main())

26
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -181,7 +181,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -181,7 +181,7 @@ namespace ICSharpCode.Decompiler.Ast
Type = new SimpleType("AssemblyVersion")
.WithAnnotation(new TypeReference(
"System.Reflection", "AssemblyVersionAttribute",
moduleDefinition, moduleDefinition.TypeSystem.Corlib)),
moduleDefinition, moduleDefinition.TypeSystem.CoreLibrary)),
Arguments = {
new PrimitiveExpression(moduleDefinition.Assembly.Name.Version.ToString())
}
@ -225,7 +225,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -225,7 +225,7 @@ namespace ICSharpCode.Decompiler.Ast
Type = new SimpleType("TypeForwardedTo")
.WithAnnotation(new TypeReference(
"System.Runtime.CompilerServices", "TypeForwardedToAttribute",
module, module.TypeSystem.Corlib)),
module, module.TypeSystem.CoreLibrary)),
Arguments = { forwardedType }
}
}
@ -331,6 +331,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -331,6 +331,7 @@ namespace ICSharpCode.Decompiler.Ast
}
} else {
EnumMemberDeclaration enumMember = new EnumMemberDeclaration();
ConvertCustomAttributes(enumMember, field);
enumMember.AddAnnotation(field);
enumMember.Name = CleanName(field.Name);
long memberValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.Constant, false);
@ -770,6 +771,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -770,6 +771,7 @@ namespace ICSharpCode.Decompiler.Ast
astMethod.Name = CleanName(methodDef.Name);
astMethod.TypeParameters.AddRange(MakeTypeParameters(methodDef.GenericParameters));
astMethod.Parameters.AddRange(MakeParameters(methodDef));
bool createMethodBody = false;
// constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly
if (!methodDef.IsVirtual || (methodDef.IsNewSlot && !methodDef.IsPrivate)) astMethod.Constraints.AddRange(MakeConstraints(methodDef.GenericParameters));
if (!methodDef.DeclaringType.IsInterface) {
@ -780,6 +782,13 @@ namespace ICSharpCode.Decompiler.Ast @@ -780,6 +782,13 @@ namespace ICSharpCode.Decompiler.Ast
if (methodDef.IsVirtual == methodDef.IsNewSlot)
SetNewModifier(astMethod);
}
createMethodBody = true;
} else if (methodDef.IsStatic) {
// decompile static method in interface
astMethod.Modifiers = ConvertModifiers(methodDef);
createMethodBody = true;
}
if (createMethodBody) {
astMethod.Body = CreateMethodBody(methodDef, astMethod.Parameters);
if (context.CurrentMethodIsAsync) {
astMethod.Modifiers |= Modifiers.Async;
@ -1255,7 +1264,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -1255,7 +1264,7 @@ namespace ICSharpCode.Decompiler.Ast
Ast.Attribute methodImpl = CreateNonCustomAttribute(typeof(MethodImplAttribute));
TypeReference methodImplOptions = new TypeReference(
"System.Runtime.CompilerServices", "MethodImplOptions",
methodDefinition.Module, methodDefinition.Module.TypeSystem.Corlib);
methodDefinition.Module, methodDefinition.Module.TypeSystem.CoreLibrary);
methodImpl.Arguments.Add(MakePrimitive((long)implAttributes, methodImplOptions));
attributedNode.Attributes.Add(new AttributeSection(methodImpl));
}
@ -1302,7 +1311,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -1302,7 +1311,7 @@ namespace ICSharpCode.Decompiler.Ast
{
MarshalInfo marshalInfo = marshalInfoProvider.MarshalInfo;
Ast.Attribute attr = CreateNonCustomAttribute(typeof(MarshalAsAttribute), module);
var unmanagedType = new TypeReference("System.Runtime.InteropServices", "UnmanagedType", module, module.TypeSystem.Corlib);
var unmanagedType = new TypeReference("System.Runtime.InteropServices", "UnmanagedType", module, module.TypeSystem.CoreLibrary);
attr.Arguments.Add(MakePrimitive((int)marshalInfo.NativeType, unmanagedType));
FixedArrayMarshalInfo fami = marshalInfo as FixedArrayMarshalInfo;
@ -1313,7 +1322,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -1313,7 +1322,7 @@ namespace ICSharpCode.Decompiler.Ast
}
SafeArrayMarshalInfo sami = marshalInfo as SafeArrayMarshalInfo;
if (sami != null && sami.ElementType != VariantType.None) {
var varEnum = new TypeReference("System.Runtime.InteropServices", "VarEnum", module, module.TypeSystem.Corlib);
var varEnum = new TypeReference("System.Runtime.InteropServices", "VarEnum", module, module.TypeSystem.CoreLibrary);
attr.AddNamedArgument("SafeArraySubType", MakePrimitive((int)sami.ElementType, varEnum));
}
ArrayMarshalInfo ami = marshalInfo as ArrayMarshalInfo;
@ -1350,7 +1359,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -1350,7 +1359,7 @@ namespace ICSharpCode.Decompiler.Ast
Ast.Attribute attr = new Ast.Attribute();
attr.Type = new SimpleType(attributeType.Name.Substring(0, attributeType.Name.Length - "Attribute".Length));
if (module != null) {
attr.Type.AddAnnotation(new TypeReference(attributeType.Namespace, attributeType.Name, module, module.TypeSystem.Corlib));
attr.Type.AddAnnotation(new TypeReference(attributeType.Namespace, attributeType.Name, module, module.TypeSystem.CoreLibrary));
}
return attr;
}
@ -1452,7 +1461,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -1452,7 +1461,7 @@ namespace ICSharpCode.Decompiler.Ast
}
var module = secAttribute.AttributeType.Module;
var securityActionType = new TypeReference("System.Security.Permissions", "SecurityAction", module, module.TypeSystem.Corlib);
var securityActionType = new TypeReference("System.Security.Permissions", "SecurityAction", module, module.TypeSystem.CoreLibrary);
attribute.Arguments.Add(MakePrimitive((int)secDecl.Action, securityActionType));
if (secAttribute.HasProperties) {
@ -1512,7 +1521,8 @@ namespace ICSharpCode.Decompiler.Ast @@ -1512,7 +1521,8 @@ namespace ICSharpCode.Decompiler.Ast
}
var type = argument.Type.Resolve();
if (type != null && type.IsEnum) {
return MakePrimitive(Convert.ToInt64(argument.Value), type);
long val = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, argument.Value, false);
return MakePrimitive(val, type);
} else if (argument.Value is TypeReference) {
return CreateTypeOfExpression((TypeReference)argument.Value);
} else {

34
ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs

@ -715,7 +715,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -715,7 +715,7 @@ namespace ICSharpCode.Decompiler.Ast
}
return new StackAllocExpression {
Type = AstBuilder.ConvertType(type),
CountExpression = arg1
CountExpression = arg1
};
}
case ILCode.Mkrefany:
@ -754,26 +754,28 @@ namespace ICSharpCode.Decompiler.Ast @@ -754,26 +754,28 @@ namespace ICSharpCode.Decompiler.Ast
return ace;
}
}
if (declaringType.IsAnonymousType()) {
MethodDefinition ctor = ((MethodReference)operand).Resolve();
if (methodDef != null) {
AnonymousTypeCreateExpression atce = new AnonymousTypeCreateExpression();
if (CanInferAnonymousTypePropertyNamesFromArguments(args, ctor.Parameters)) {
atce.Initializers.AddRange(args);
} else {
for (int i = 0; i < args.Count; i++) {
atce.Initializers.Add(
new NamedExpression {
Name = ctor.Parameters[i].Name,
Expression = args[i]
});
}
MethodDefinition ctor = ((MethodReference)operand).Resolve();
if (declaringType.IsAnonymousType() && methodDef != null) {
AnonymousTypeCreateExpression atce = new AnonymousTypeCreateExpression();
if (CanInferAnonymousTypePropertyNamesFromArguments(args, ctor.Parameters)) {
atce.Initializers.AddRange(args);
} else {
for (int i = 0; i < args.Count; i++) {
atce.Initializers.Add(
new NamedExpression {
Name = ctor.Parameters[i].Name,
Expression = args[i]
});
}
return atce;
}
return atce;
}
var oce = new Ast.ObjectCreateExpression();
oce.Type = AstBuilder.ConvertType(declaringType);
// seems like IsIn/IsOut information for parameters is only correct on the ctor's MethodDefinition
if (ctor != null) {
AdjustArgumentsForMethodCall(ctor, args);
}
oce.Arguments.AddRange(args);
return oce.WithAnnotation(operand);
}

16
ICSharpCode.Decompiler/Ast/DecompilerContext.cs

@ -35,25 +35,11 @@ namespace ICSharpCode.Decompiler @@ -35,25 +35,11 @@ namespace ICSharpCode.Decompiler
public DecompilerSettings Settings = new DecompilerSettings();
public bool CurrentMethodIsAsync;
// public ITypeResolveContext TypeResolveContext;
// public IProjectContent ProjectContent;
public DecompilerContext(ModuleDefinition currentModule)
{
if (currentModule == null)
throw new ArgumentNullException("currentModule");
throw new ArgumentNullException(nameof(currentModule));
this.CurrentModule = currentModule;
// this.ProjectContent = new CecilTypeResolveContext(currentModule);
// List<ITypeResolveContext> resolveContexts = new List<ITypeResolveContext>();
// resolveContexts.Add(this.ProjectContent);
// foreach (AssemblyNameReference r in currentModule.AssemblyReferences) {
// AssemblyDefinition d = currentModule.AssemblyResolver.Resolve(r);
// if (d != null) {
// resolveContexts.Add(new CecilTypeResolveContext(d.MainModule));
// }
// }
// this.TypeResolveContext = new CompositeTypeResolveContext(resolveContexts);
}
/// <summary>

2
ICSharpCode.Decompiler/Ast/NameVariables.cs

@ -335,7 +335,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -335,7 +335,7 @@ namespace ICSharpCode.Decompiler.Ast
// remove field prefix:
if (name.Length > 2 && name.StartsWith("m_", StringComparison.Ordinal))
name = name.Substring(2);
else if (name.Length > 1 && name[0] == '_')
else if (name.Length > 1 && name[0] == '_' && (char.IsLetter(name[1]) || name[1] == '_'))
name = name.Substring(1);
if (name.Length == 0)

4
ICSharpCode.Decompiler/Ast/TextTokenWriter.cs

@ -53,6 +53,10 @@ namespace ICSharpCode.Decompiler.Ast @@ -53,6 +53,10 @@ namespace ICSharpCode.Decompiler.Ast
public override void WriteIdentifier(Identifier identifier)
{
if (identifier.IsVerbatim || CSharpOutputVisitor.IsKeyword(identifier.Name, identifier)) {
output.Write('@');
}
var definition = GetCurrentDefinition();
if (definition != null) {
output.WriteDefinition(identifier.Name, definition, false);

2
ICSharpCode.Decompiler/CSharp/Transforms/DelegateConstruction.cs

@ -194,7 +194,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -194,7 +194,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
ame.Body = body;
replacement = ame;
}
var expectedType = objectCreateExpression.Annotation<TypeInformation>().ExpectedType.Resolve();
var expectedType = objectCreateExpression.Annotation<TypeInformation>()?.ExpectedType?.Resolve();
if (expectedType != null && !expectedType.IsDelegate()) {
var simplifiedDelegateCreation = (ObjectCreateExpression)objectCreateExpression.Clone();
simplifiedDelegateCreation.Arguments.Clear();

56
ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs

@ -58,11 +58,12 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -58,11 +58,12 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
public override AstNode VisitExpressionStatement(ExpressionStatement expressionStatement, object data)
{
AstNode result;
if (context.Settings.UsingStatement) {
result = TransformUsings(expressionStatement);
if (context.Settings.UsingStatement)
{
result = TransformNonGenericForEach(expressionStatement);
if (result != null)
return result;
result = TransformNonGenericForEach(expressionStatement);
result = TransformUsings(expressionStatement);
if (result != null)
return result;
}
@ -156,7 +157,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -156,7 +157,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
};
}
static readonly AstNode usingTryCatchPattern = new TryCatchStatement {
static readonly AstNode usingTryCatchPattern = new Choice {
{ "c#/vb",
new TryCatchStatement {
TryBlock = new AnyNode(),
FinallyBlock = new BlockStatement {
new Choice {
@ -177,6 +180,33 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -177,6 +180,33 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
}
}.ToStatement()
}
}
},
{ "f#",
new TryCatchStatement {
TryBlock = new AnyNode(),
FinallyBlock =
new BlockStatement {
new ExpressionStatement(
new AssignmentExpression(left: new NamedNode("disposable", new IdentifierExpression(Pattern.AnyString)),
right: new AsExpression(expression: new NamedNode("ident", new IdentifierExpression(Pattern.AnyString)),
type: new TypePattern(typeof(IDisposable))
)
)
),
new IfElseStatement {
Condition = new BinaryOperatorExpression(
new Backreference("disposable"),
BinaryOperatorType.InEquality,
new NullReferenceExpression()
),
TrueStatement = new BlockStatement {
new ExpressionStatement(InvokeDispose(new Backreference("disposable")))
}
}
}
}
}
};
public UsingStatement TransformUsings(ExpressionStatement node)
@ -214,6 +244,17 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -214,6 +244,17 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
if (!IsVariableValueUnused(varDecl, tryCatch))
return null;
if (m2.Has("f#")) {
string variableNameDisposable = m2.Get<IdentifierExpression>("disposable").Single().Identifier;
VariableDeclarationStatement varDeclDisposable = FindVariableDeclaration(node, variableNameDisposable);
if (varDeclDisposable == null || !(varDeclDisposable.Parent is BlockStatement))
return null;
// Validate that the variable is not used after the using statement:
if (!IsVariableValueUnused(varDeclDisposable, tryCatch))
return null;
}
node.Remove();
UsingStatement usingStatement = new UsingStatement();
@ -379,6 +420,13 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -379,6 +420,13 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
if (declarationPoint != loop)
return null;
// Make sure that the enumerator variable is not used inside the body
var enumeratorId = Identifier.Create(enumeratorVar.Name);
foreach (Statement stmt in m.Get<Statement>("statement")) {
if (stmt.Descendants.OfType<Identifier>().Any(id => enumeratorId.IsMatch(id)))
return null;
}
BlockStatement newBody = new BlockStatement();
foreach (Statement stmt in m.Get<Statement>("variablesInsideLoop"))
newBody.Add(stmt.Detach());

22
ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs

@ -32,7 +32,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -32,7 +32,7 @@ namespace ICSharpCode.Decompiler.Disassembler
/// </summary>
public sealed class ReflectionDisassembler
{
ITextOutput output;
readonly ITextOutput output;
CancellationToken cancellationToken;
bool isInType; // whether we are currently disassembling a whole type (-> defaultCollapsed for foldings)
MethodBodyDisassembler methodBodyDisassembler;
@ -220,8 +220,9 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -220,8 +220,9 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteLine();
}
}
WriteParameterAttributes(0, method.MethodReturnType, method.MethodReturnType);
foreach (var p in method.Parameters) {
WriteParameterAttributes(p);
WriteParameterAttributes(p.Index + 1, p, p);
}
WriteSecurityDeclarations(method);
@ -615,22 +616,17 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -615,22 +616,17 @@ namespace ICSharpCode.Decompiler.Disassembler
}
}
bool HasParameterAttributes(ParameterDefinition p)
void WriteParameterAttributes(int index, IConstantProvider cp, ICustomAttributeProvider cap)
{
return p.HasConstant || p.HasCustomAttributes;
}
void WriteParameterAttributes(ParameterDefinition p)
{
if (!HasParameterAttributes(p))
if (!cp.HasConstant && !cap.HasCustomAttributes)
return;
output.Write(".param [{0}]", p.Index + 1);
if (p.HasConstant) {
output.Write(".param [{0}]", index);
if (cp.HasConstant) {
output.Write(" = ");
WriteConstant(p.Constant);
WriteConstant(cp.Constant);
}
output.WriteLine();
WriteAttributes(p.CustomAttributes);
WriteAttributes(cap.CustomAttributes);
}
void WriteConstant(object constant)

4
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -172,11 +172,11 @@ @@ -172,11 +172,11 @@
<Name>ICSharpCode.NRefactory.Cecil</Name>
</ProjectReference>
<ProjectReference Include="..\NRefactory\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory.CSharp.csproj">
<Project>{53DCA265-3C3C-42F9-B647-F72BA678122B}</Project>
<Project>{53dca265-3c3c-42f9-b647-f72ba678122b}</Project>
<Name>ICSharpCode.NRefactory.CSharp</Name>
</ProjectReference>
<ProjectReference Include="..\NRefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">
<Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project>
<Project>{3b2a5653-ec97-4001-bb9b-d90f1af2c371}</Project>
<Name>ICSharpCode.NRefactory</Name>
</ProjectReference>
</ItemGroup>

1
ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs

@ -24,7 +24,6 @@ using ICSharpCode.Decompiler.FlowAnalysis; @@ -24,7 +24,6 @@ using ICSharpCode.Decompiler.FlowAnalysis;
using ICSharpCode.NRefactory.Utils;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.CSharp;
namespace ICSharpCode.Decompiler.ILAst
{

1
ICSharpCode.Decompiler/ILAst/ILAstTypes.cs

@ -27,7 +27,6 @@ using ICSharpCode.Decompiler.Disassembler; @@ -27,7 +27,6 @@ using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.NRefactory.Utils;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.CSharp;
using Cecil = Mono.Cecil;
namespace ICSharpCode.Decompiler.ILAst

19
ICSharpCode.Decompiler/ILAst/StateRange.cs

@ -273,14 +273,23 @@ namespace ICSharpCode.Decompiler.ILAst @@ -273,14 +273,23 @@ namespace ICSharpCode.Decompiler.ILAst
{
if (pos > 0 && body[pos - 1] is ILLabel) {
pos--;
return; // label found
}
// ensure that the first element at body[pos] is a label:
ILLabel newLabel = new ILLabel();
newLabel.Name = "YieldReturnEntryPoint";
ILExpression expr = pos == 1 && body.Count == 1 ? body[0] as ILExpression : null;
if (expr != null && expr.Code == ILCode.Leave && expr.Operand is ILLabel) {
ranges[newLabel] = ranges[(ILLabel)expr.Operand];
pos = 0;
} else {
// ensure that the first element at body[pos] is a label:
ILLabel newLabel = new ILLabel();
newLabel.Name = "YieldReturnEntryPoint";
ranges[newLabel] = ranges[body[pos]]; // give the label the range of the instruction at body[pos]
body.Insert(pos, newLabel);
bodyLength++;
}
body.Insert(pos, newLabel);
bodyLength++;
}
public LabelRangeMapping CreateLabelRangeMapping(List<ILNode> body, int pos, int bodyLength)

17
ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

@ -478,7 +478,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -478,7 +478,7 @@ namespace ICSharpCode.Decompiler.ILAst
if (forceInferChildren) {
InferTypeForExpression(expr.Arguments[0], typeSystem.TypedReference);
}
return new TypeReference("System", "RuntimeTypeHandle", module, module.TypeSystem.Corlib, true);
return new TypeReference("System", "RuntimeTypeHandle", module, module.TypeSystem.CoreLibrary, true);
case ILCode.Refanyval:
if (forceInferChildren) {
InferTypeForExpression(expr.Arguments[0], typeSystem.TypedReference);
@ -607,16 +607,16 @@ namespace ICSharpCode.Decompiler.ILAst @@ -607,16 +607,16 @@ namespace ICSharpCode.Decompiler.ILAst
case ILCode.Ldc_R8:
return typeSystem.Double;
case ILCode.Ldc_Decimal:
return new TypeReference("System", "Decimal", module, module.TypeSystem.Corlib, true);
return new TypeReference("System", "Decimal", module, module.TypeSystem.CoreLibrary, true);
case ILCode.Ldtoken:
if (expr.Operand is TypeReference)
return new TypeReference("System", "RuntimeTypeHandle", module, module.TypeSystem.Corlib, true);
return new TypeReference("System", "RuntimeTypeHandle", module, module.TypeSystem.CoreLibrary, true);
else if (expr.Operand is FieldReference)
return new TypeReference("System", "RuntimeFieldHandle", module, module.TypeSystem.Corlib, true);
return new TypeReference("System", "RuntimeFieldHandle", module, module.TypeSystem.CoreLibrary, true);
else
return new TypeReference("System", "RuntimeMethodHandle", module, module.TypeSystem.Corlib, true);
return new TypeReference("System", "RuntimeMethodHandle", module, module.TypeSystem.CoreLibrary, true);
case ILCode.Arglist:
return new TypeReference("System", "RuntimeArgumentHandle", module, module.TypeSystem.Corlib, true);
return new TypeReference("System", "RuntimeArgumentHandle", module, module.TypeSystem.CoreLibrary, true);
#endregion
#region Array instructions
case ILCode.Newarr:
@ -996,7 +996,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -996,7 +996,7 @@ namespace ICSharpCode.Decompiler.ILAst
GenericInstanceType CreateNullableType(TypeReference type)
{
if (type == null) return null;
var t = new GenericInstanceType(new TypeReference("System", "Nullable`1", module, module.TypeSystem.Corlib, true));
var t = new GenericInstanceType(new TypeReference("System", "Nullable`1", module, module.TypeSystem.CoreLibrary, true));
t.GenericArguments.Add(type);
return t;
}
@ -1266,6 +1266,9 @@ namespace ICSharpCode.Decompiler.ILAst @@ -1266,6 +1266,9 @@ namespace ICSharpCode.Decompiler.ILAst
return TypeCode.Double;
case MetadataType.String:
return TypeCode.String;
case MetadataType.RequiredModifier:
case MetadataType.OptionalModifier:
return GetTypeCode(((IModifierType)type).ElementType);
default:
return TypeCode.Object;
}

4
ICSharpCode.Decompiler/Tests/Async.cs

@ -37,6 +37,10 @@ public class Async @@ -37,6 +37,10 @@ public class Async
Console.WriteLine("No Await");
}
public async void EmptyVoidMethod()
{
}
public async void AwaitYield()
{
await Task.Yield();

5
ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributes.cs

@ -39,6 +39,11 @@ namespace aa @@ -39,6 +39,11 @@ namespace aa
{
}
}
[CustomAttributes.MyAttribute(CustomAttributes.ULongEnum.MaxUInt64)]
public enum ULongEnum : ulong
{
MaxUInt64 = 18446744073709551615uL
}
[My(EnumWithFlag.Item1 | EnumWithFlag.Item2)]
private static int field;
[My(EnumWithFlag.All)]

30
ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpPatternTests.cs

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.Tests.FSharpPatterns
{
[TestFixture]
public class FSharpPatternTests
{
[Test]
public void FSharpUsingDecompilesToCSharpUsing_Debug()
{
var ilCode = TestHelpers.FuzzyReadResource("FSharpUsing.fs.Debug.il");
var csharpCode = TestHelpers.FuzzyReadResource("FSharpUsing.fs.Debug.cs");
TestHelpers.RunIL(ilCode, csharpCode);
}
[Test]
public void FSharpUsingDecompilesToCSharpUsing_Release()
{
var ilCode = TestHelpers.FuzzyReadResource("FSharpUsing.fs.Release.il");
var csharpCode = TestHelpers.FuzzyReadResource("FSharpUsing.fs.Release.cs");
TestHelpers.RunIL(ilCode, csharpCode);
}
}
}

38
ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs

@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
module FSharpUsingPatterns
open System
open System.IO
let sample1() =
use fs = File.Create("x.txt")
fs.WriteByte(byte 1)
let sample2() =
Console.WriteLine("some text")
use fs = File.Create("x.txt")
fs.WriteByte(byte 2)
Console.WriteLine("some text")
let sample3() =
Console.WriteLine("some text")
do use fs = File.Create("x.txt")
fs.WriteByte(byte 3)
Console.WriteLine("some text")
let sample4() =
Console.WriteLine("some text")
let firstByte =
use fs = File.OpenRead("x.txt")
fs.ReadByte()
Console.WriteLine("read:" + firstByte.ToString())
let sample5() =
Console.WriteLine("some text")
let firstByte =
use fs = File.OpenRead("x.txt")
fs.ReadByte()
let secondByte =
use fs = File.OpenRead("x.txt")
fs.ReadByte() |> ignore
fs.ReadByte()
Console.WriteLine("read: {0}, {1}", firstByte, secondByte)

64
ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs.Debug.cs

@ -0,0 +1,64 @@ @@ -0,0 +1,64 @@
using System;
using System.IO;
public static class FSharpUsingPatterns
{
public static void sample1()
{
using (FileStream fs = File.Create("x.txt"))
{
fs.WriteByte((byte)1);
}
}
public static void sample2()
{
Console.WriteLine("some text");
using (FileStream fs = File.Create("x.txt"))
{
fs.WriteByte((byte)2);
Console.WriteLine("some text");
}
}
public static void sample3()
{
Console.WriteLine("some text");
using (FileStream fs = File.Create("x.txt"))
{
fs.WriteByte((byte)3);
}
Console.WriteLine("some text");
}
public static void sample4()
{
Console.WriteLine("some text");
int num;
using (FileStream fs = File.OpenRead("x.txt"))
{
num = fs.ReadByte();
}
int firstByte = num;
Console.WriteLine("read:" + firstByte.ToString());
}
public static void sample5()
{
Console.WriteLine("some text");
int num;
using (FileStream fs = File.OpenRead("x.txt"))
{
num = fs.ReadByte();
}
int firstByte = num;
int num3;
using (FileStream fs = File.OpenRead("x.txt"))
{
int num2 = fs.ReadByte();
num3 = fs.ReadByte();
}
int secondByte = num3;
Console.WriteLine("read: {0}, {1}", firstByte, secondByte);
}
}

344
ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs.Debug.il

@ -0,0 +1,344 @@ @@ -0,0 +1,344 @@
.class public auto ansi abstract sealed FSharpUsingPatterns
extends [mscorlib]System.Object
{
// Methods
.method public static
void sample1 () cil managed
{
// Method begins at RVA 0x2050
// Code size 53 (0x35)
.maxstack 4
.locals init (
[0] class [mscorlib]System.IO.FileStream fs,
[1] class [mscorlib]System.Object,
[2] class [mscorlib]System.IDisposable
)
IL_0000: nop
IL_0001: ldstr "x.txt"
IL_0006: call class [mscorlib]System.IO.FileStream [mscorlib]System.IO.File::Create(string)
IL_000b: stloc.0
.try
{
IL_000c: ldloc.0
IL_000d: ldc.i4.1
IL_000e: conv.u1
IL_000f: callvirt instance void [mscorlib]System.IO.Stream::WriteByte(uint8)
IL_0014: ldnull
IL_0015: stloc.1
IL_0016: leave.s IL_0032
} // end .try
finally
{
IL_0018: ldloc.0
IL_0019: isinst [mscorlib]System.IDisposable
IL_001e: stloc.2
IL_001f: ldloc.2
IL_0020: brfalse.s IL_0024
IL_0022: br.s IL_0026
IL_0024: br.s IL_002f
IL_0026: ldloc.2
IL_0027: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_002c: ldnull
IL_002d: pop
IL_002e: endfinally
IL_002f: ldnull
IL_0030: pop
IL_0031: endfinally
} // end handler
IL_0032: ldloc.1
IL_0033: pop
IL_0034: ret
} // end of method FSharpUsingPatterns::sample1
.method public static
void sample2 () cil managed
{
// Method begins at RVA 0x20a4
// Code size 73 (0x49)
.maxstack 4
.locals init (
[0] class [mscorlib]System.IO.FileStream fs,
[1] class [mscorlib]System.Object,
[2] class [mscorlib]System.IDisposable
)
IL_0000: nop
IL_0001: ldstr "some text"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: ldstr "x.txt"
IL_0010: call class [mscorlib]System.IO.FileStream [mscorlib]System.IO.File::Create(string)
IL_0015: stloc.0
.try
{
IL_0016: ldloc.0
IL_0017: ldc.i4.2
IL_0018: conv.u1
IL_0019: callvirt instance void [mscorlib]System.IO.Stream::WriteByte(uint8)
IL_001e: ldstr "some text"
IL_0023: call void [mscorlib]System.Console::WriteLine(string)
IL_0028: ldnull
IL_0029: stloc.1
IL_002a: leave.s IL_0046
} // end .try
finally
{
IL_002c: ldloc.0
IL_002d: isinst [mscorlib]System.IDisposable
IL_0032: stloc.2
IL_0033: ldloc.2
IL_0034: brfalse.s IL_0038
IL_0036: br.s IL_003a
IL_0038: br.s IL_0043
IL_003a: ldloc.2
IL_003b: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0040: ldnull
IL_0041: pop
IL_0042: endfinally
IL_0043: ldnull
IL_0044: pop
IL_0045: endfinally
} // end handler
IL_0046: ldloc.1
IL_0047: pop
IL_0048: ret
} // end of method FSharpUsingPatterns::sample2
.method public static
void sample3 () cil managed
{
// Method begins at RVA 0x210c
// Code size 73 (0x49)
.maxstack 4
.locals init (
[0] class [mscorlib]System.IO.FileStream fs,
[1] class [mscorlib]System.Object,
[2] class [mscorlib]System.IDisposable
)
IL_0000: nop
IL_0001: ldstr "some text"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: ldstr "x.txt"
IL_0010: call class [mscorlib]System.IO.FileStream [mscorlib]System.IO.File::Create(string)
IL_0015: stloc.0
.try
{
IL_0016: ldloc.0
IL_0017: ldc.i4.3
IL_0018: conv.u1
IL_0019: callvirt instance void [mscorlib]System.IO.Stream::WriteByte(uint8)
IL_001e: ldnull
IL_001f: stloc.1
IL_0020: leave.s IL_003c
} // end .try
finally
{
IL_0022: ldloc.0
IL_0023: isinst [mscorlib]System.IDisposable
IL_0028: stloc.2
IL_0029: ldloc.2
IL_002a: brfalse.s IL_002e
IL_002c: br.s IL_0030
IL_002e: br.s IL_0039
IL_0030: ldloc.2
IL_0031: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0036: ldnull
IL_0037: pop
IL_0038: endfinally
IL_0039: ldnull
IL_003a: pop
IL_003b: endfinally
} // end handler
IL_003c: ldloc.1
IL_003d: pop
IL_003e: ldstr "some text"
IL_0043: call void [mscorlib]System.Console::WriteLine(string)
IL_0048: ret
} // end of method FSharpUsingPatterns::sample3
.method public static
void sample4 () cil managed
{
// Method begins at RVA 0x2174
// Code size 89 (0x59)
.maxstack 4
.locals init (
[0] int32 firstByte,
[1] class [mscorlib]System.IO.FileStream fs,
[2] int32,
[3] class [mscorlib]System.IDisposable
)
IL_0000: nop
IL_0001: ldstr "some text"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ldstr "x.txt"
IL_0011: call class [mscorlib]System.IO.FileStream [mscorlib]System.IO.File::OpenRead(string)
IL_0016: stloc.1
.try
{
IL_0017: ldloc.1
IL_0018: callvirt instance int32 [mscorlib]System.IO.Stream::ReadByte()
IL_001d: stloc.2
IL_001e: leave.s IL_003a
} // end .try
finally
{
IL_0020: ldloc.1
IL_0021: isinst [mscorlib]System.IDisposable
IL_0026: stloc.3
IL_0027: ldloc.3
IL_0028: brfalse.s IL_002c
IL_002a: br.s IL_002e
IL_002c: br.s IL_0037
IL_002e: ldloc.3
IL_002f: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0034: ldnull
IL_0035: pop
IL_0036: endfinally
IL_0037: ldnull
IL_0038: pop
IL_0039: endfinally
} // end handler
IL_003a: ldloc.2
IL_003b: stloc.0
IL_003c: ldstr "read:"
IL_0041: ldloca.s firstByte
IL_0043: constrained. [mscorlib]System.Int32
IL_0049: callvirt instance string [mscorlib]System.Object::ToString()
IL_004e: call string [mscorlib]System.String::Concat(string, string)
IL_0053: call void [mscorlib]System.Console::WriteLine(string)
IL_0058: ret
} // end of method FSharpUsingPatterns::sample4
.method public static
void sample5 () cil managed
{
// Method begins at RVA 0x21ec
// Code size 155 (0x9b)
.maxstack 5
.locals init (
[0] int32 firstByte,
[1] class [mscorlib]System.IO.FileStream fs,
[2] int32,
[3] class [mscorlib]System.IDisposable,
[4] int32 secondByte,
[5] class [mscorlib]System.IO.FileStream fs,
[6] int32,
[7] int32,
[8] int32,
[9] class [mscorlib]System.IDisposable
)
IL_0000: nop
IL_0001: ldstr "some text"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ldstr "x.txt"
IL_0011: call class [mscorlib]System.IO.FileStream [mscorlib]System.IO.File::OpenRead(string)
IL_0016: stloc.1
.try
{
IL_0017: ldloc.1
IL_0018: callvirt instance int32 [mscorlib]System.IO.Stream::ReadByte()
IL_001d: stloc.2
IL_001e: leave.s IL_003a
} // end .try
finally
{
IL_0020: ldloc.1
IL_0021: isinst [mscorlib]System.IDisposable
IL_0026: stloc.3
IL_0027: ldloc.3
IL_0028: brfalse.s IL_002c
IL_002a: br.s IL_002e
IL_002c: br.s IL_0037
IL_002e: ldloc.3
IL_002f: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0034: ldnull
IL_0035: pop
IL_0036: endfinally
IL_0037: ldnull
IL_0038: pop
IL_0039: endfinally
} // end handler
IL_003a: ldloc.2
IL_003b: stloc.0
IL_003c: nop
IL_003d: ldstr "x.txt"
IL_0042: call class [mscorlib]System.IO.FileStream [mscorlib]System.IO.File::OpenRead(string)
IL_0047: stloc.s fs
.try
{
IL_0049: ldloc.s fs
IL_004b: callvirt instance int32 [mscorlib]System.IO.Stream::ReadByte()
IL_0050: stloc.s 7
IL_0052: ldloc.s 7
IL_0054: stloc.s 8
IL_0056: ldloc.s fs
IL_0058: callvirt instance int32 [mscorlib]System.IO.Stream::ReadByte()
IL_005d: stloc.s 6
IL_005f: leave.s IL_007f
} // end .try
finally
{
IL_0061: ldloc.s fs
IL_0063: isinst [mscorlib]System.IDisposable
IL_0068: stloc.s 9
IL_006a: ldloc.s 9
IL_006c: brfalse.s IL_0070
IL_006e: br.s IL_0072
IL_0070: br.s IL_007c
IL_0072: ldloc.s 9
IL_0074: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0079: ldnull
IL_007a: pop
IL_007b: endfinally
IL_007c: ldnull
IL_007d: pop
IL_007e: endfinally
} // end handler
IL_007f: ldloc.s 6
IL_0081: stloc.s secondByte
IL_0083: ldstr "read: {0}, {1}"
IL_0088: ldloc.0
IL_0089: box [mscorlib]System.Int32
IL_008e: ldloc.s secondByte
IL_0090: box [mscorlib]System.Int32
IL_0095: call void [mscorlib]System.Console::WriteLine(string, object, object)
IL_009a: ret
} // end of method FSharpUsingPatterns::sample5
} // end of class FSharpUsingPatterns

64
ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs.Release.cs

@ -0,0 +1,64 @@ @@ -0,0 +1,64 @@
using System;
using System.IO;
public static class FSharpUsingPatterns
{
public static void sample1()
{
using (FileStream fs = File.Create("x.txt"))
{
fs.WriteByte(1);
}
}
public static void sample2()
{
Console.WriteLine("some text");
using (FileStream fs = File.Create("x.txt"))
{
fs.WriteByte(2);
Console.WriteLine("some text");
}
}
public static void sample3()
{
Console.WriteLine("some text");
using (FileStream fs = File.Create("x.txt"))
{
fs.WriteByte(3);
}
Console.WriteLine("some text");
}
public static void sample4()
{
Console.WriteLine("some text");
int num;
using (FileStream fs = File.OpenRead("x.txt"))
{
num = fs.ReadByte();
}
int firstByte = num;
Console.WriteLine("read:" + firstByte.ToString());
}
public static void sample5()
{
Console.WriteLine("some text");
int secondByte;
using (FileStream fs = File.OpenRead("x.txt"))
{
secondByte = fs.ReadByte();
}
int firstByte = secondByte;
int num2;
using (FileStream fs = File.OpenRead("x.txt"))
{
int num = fs.ReadByte();
num2 = fs.ReadByte();
}
secondByte = num2;
Console.WriteLine("read: {0}, {1}", firstByte, secondByte);
}
}

311
ICSharpCode.Decompiler/Tests/FSharpPatterns/FSharpUsing.fs.Release.il

@ -0,0 +1,311 @@ @@ -0,0 +1,311 @@
.class public auto ansi abstract sealed FSharpUsingPatterns
extends [mscorlib]System.Object
{
// Methods
.method public static
void sample1 () cil managed
{
// Method begins at RVA 0x2050
// Code size 48 (0x30)
.maxstack 4
.locals init (
[0] class [mscorlib]System.IO.FileStream fs,
[1] class [mscorlib]System.Object,
[2] class [mscorlib]System.IDisposable
)
IL_0000: nop
IL_0001: ldstr "x.txt"
IL_0006: call class [mscorlib]System.IO.FileStream [mscorlib]System.IO.File::Create(string)
IL_000b: stloc.0
.try
{
IL_000c: ldloc.0
IL_000d: ldc.i4.1
IL_000e: callvirt instance void [mscorlib]System.IO.Stream::WriteByte(uint8)
IL_0013: ldnull
IL_0014: stloc.1
IL_0015: leave.s IL_002d
} // end .try
finally
{
IL_0017: ldloc.0
IL_0018: isinst [mscorlib]System.IDisposable
IL_001d: stloc.2
IL_001e: ldloc.2
IL_001f: brfalse.s IL_002a
IL_0021: ldloc.2
IL_0022: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0027: ldnull
IL_0028: pop
IL_0029: endfinally
IL_002a: ldnull
IL_002b: pop
IL_002c: endfinally
} // end handler
IL_002d: ldloc.1
IL_002e: pop
IL_002f: ret
} // end of method FSharpUsingPatterns::sample1
.method public static
void sample2 () cil managed
{
// Method begins at RVA 0x209c
// Code size 68 (0x44)
.maxstack 4
.locals init (
[0] class [mscorlib]System.IO.FileStream fs,
[1] class [mscorlib]System.Object,
[2] class [mscorlib]System.IDisposable
)
IL_0000: nop
IL_0001: ldstr "some text"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: ldstr "x.txt"
IL_0010: call class [mscorlib]System.IO.FileStream [mscorlib]System.IO.File::Create(string)
IL_0015: stloc.0
.try
{
IL_0016: ldloc.0
IL_0017: ldc.i4.2
IL_0018: callvirt instance void [mscorlib]System.IO.Stream::WriteByte(uint8)
IL_001d: ldstr "some text"
IL_0022: call void [mscorlib]System.Console::WriteLine(string)
IL_0027: ldnull
IL_0028: stloc.1
IL_0029: leave.s IL_0041
} // end .try
finally
{
IL_002b: ldloc.0
IL_002c: isinst [mscorlib]System.IDisposable
IL_0031: stloc.2
IL_0032: ldloc.2
IL_0033: brfalse.s IL_003e
IL_0035: ldloc.2
IL_0036: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_003b: ldnull
IL_003c: pop
IL_003d: endfinally
IL_003e: ldnull
IL_003f: pop
IL_0040: endfinally
} // end handler
IL_0041: ldloc.1
IL_0042: pop
IL_0043: ret
} // end of method FSharpUsingPatterns::sample2
.method public static
void sample3 () cil managed
{
// Method begins at RVA 0x20fc
// Code size 68 (0x44)
.maxstack 4
.locals init (
[0] class [mscorlib]System.IO.FileStream fs,
[1] class [mscorlib]System.Object,
[2] class [mscorlib]System.IDisposable
)
IL_0000: nop
IL_0001: ldstr "some text"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: ldstr "x.txt"
IL_0010: call class [mscorlib]System.IO.FileStream [mscorlib]System.IO.File::Create(string)
IL_0015: stloc.0
.try
{
IL_0016: ldloc.0
IL_0017: ldc.i4.3
IL_0018: callvirt instance void [mscorlib]System.IO.Stream::WriteByte(uint8)
IL_001d: ldnull
IL_001e: stloc.1
IL_001f: leave.s IL_0037
} // end .try
finally
{
IL_0021: ldloc.0
IL_0022: isinst [mscorlib]System.IDisposable
IL_0027: stloc.2
IL_0028: ldloc.2
IL_0029: brfalse.s IL_0034
IL_002b: ldloc.2
IL_002c: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0031: ldnull
IL_0032: pop
IL_0033: endfinally
IL_0034: ldnull
IL_0035: pop
IL_0036: endfinally
} // end handler
IL_0037: ldloc.1
IL_0038: pop
IL_0039: ldstr "some text"
IL_003e: call void [mscorlib]System.Console::WriteLine(string)
IL_0043: ret
} // end of method FSharpUsingPatterns::sample3
.method public static
void sample4 () cil managed
{
// Method begins at RVA 0x215c
// Code size 85 (0x55)
.maxstack 4
.locals init (
[0] int32 firstByte,
[1] class [mscorlib]System.IO.FileStream fs,
[2] int32,
[3] class [mscorlib]System.IDisposable
)
IL_0000: nop
IL_0001: ldstr "some text"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ldstr "x.txt"
IL_0011: call class [mscorlib]System.IO.FileStream [mscorlib]System.IO.File::OpenRead(string)
IL_0016: stloc.1
.try
{
IL_0017: ldloc.1
IL_0018: callvirt instance int32 [mscorlib]System.IO.Stream::ReadByte()
IL_001d: stloc.2
IL_001e: leave.s IL_0036
} // end .try
finally
{
IL_0020: ldloc.1
IL_0021: isinst [mscorlib]System.IDisposable
IL_0026: stloc.3
IL_0027: ldloc.3
IL_0028: brfalse.s IL_0033
IL_002a: ldloc.3
IL_002b: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0030: ldnull
IL_0031: pop
IL_0032: endfinally
IL_0033: ldnull
IL_0034: pop
IL_0035: endfinally
} // end handler
IL_0036: ldloc.2
IL_0037: stloc.0
IL_0038: ldstr "read:"
IL_003d: ldloca.s firstByte
IL_003f: constrained. [mscorlib]System.Int32
IL_0045: callvirt instance string [mscorlib]System.Object::ToString()
IL_004a: call string [mscorlib]System.String::Concat(string, string)
IL_004f: call void [mscorlib]System.Console::WriteLine(string)
IL_0054: ret
} // end of method FSharpUsingPatterns::sample4
.method public static
void sample5 () cil managed
{
// Method begins at RVA 0x21d0
// Code size 134 (0x86)
.maxstack 5
.locals init (
[0] int32 firstByte,
[1] class [mscorlib]System.IO.FileStream fs,
[2] int32 secondByte,
[3] class [mscorlib]System.IDisposable,
[4] int32,
[5] int32
)
IL_0000: nop
IL_0001: ldstr "some text"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ldstr "x.txt"
IL_0011: call class [mscorlib]System.IO.FileStream [mscorlib]System.IO.File::OpenRead(string)
IL_0016: stloc.1
.try
{
IL_0017: ldloc.1
IL_0018: callvirt instance int32 [mscorlib]System.IO.Stream::ReadByte()
IL_001d: stloc.2
IL_001e: leave.s IL_0036
} // end .try
finally
{
IL_0020: ldloc.1
IL_0021: isinst [mscorlib]System.IDisposable
IL_0026: stloc.3
IL_0027: ldloc.3
IL_0028: brfalse.s IL_0033
IL_002a: ldloc.3
IL_002b: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0030: ldnull
IL_0031: pop
IL_0032: endfinally
IL_0033: ldnull
IL_0034: pop
IL_0035: endfinally
} // end handler
IL_0036: ldloc.2
IL_0037: stloc.0
IL_0038: nop
IL_0039: ldstr "x.txt"
IL_003e: call class [mscorlib]System.IO.FileStream [mscorlib]System.IO.File::OpenRead(string)
IL_0043: stloc.1
.try
{
IL_0044: ldloc.1
IL_0045: callvirt instance int32 [mscorlib]System.IO.Stream::ReadByte()
IL_004a: stloc.s 5
IL_004c: ldloc.1
IL_004d: callvirt instance int32 [mscorlib]System.IO.Stream::ReadByte()
IL_0052: stloc.s 4
IL_0054: leave.s IL_006c
} // end .try
finally
{
IL_0056: ldloc.1
IL_0057: isinst [mscorlib]System.IDisposable
IL_005c: stloc.3
IL_005d: ldloc.3
IL_005e: brfalse.s IL_0069
IL_0060: ldloc.3
IL_0061: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0066: ldnull
IL_0067: pop
IL_0068: endfinally
IL_0069: ldnull
IL_006a: pop
IL_006b: endfinally
} // end handler
IL_006c: ldloc.s 4
IL_006e: stloc.2
IL_006f: ldstr "read: {0}, {1}"
IL_0074: ldloc.0
IL_0075: box [mscorlib]System.Int32
IL_007a: ldloc.2
IL_007b: box [mscorlib]System.Int32
IL_0080: call void [mscorlib]System.Console::WriteLine(string, object, object)
IL_0085: ret
} // end of method FSharpUsingPatterns::sample5
} // end of class FSharpUsingPatterns

87
ICSharpCode.Decompiler/Tests/FSharpPatterns/TestHelpers.cs

@ -0,0 +1,87 @@ @@ -0,0 +1,87 @@
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.Decompiler.Tests.Helpers;
using ICSharpCode.NRefactory.CSharp;
using Mono.Cecil;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.Tests.FSharpPatterns
{
public class TestHelpers
{
public static string FuzzyReadResource(string resourceName)
{
var asm = Assembly.GetExecutingAssembly();
var allResources = asm.GetManifestResourceNames();
var fullResourceName = allResources.Single(r => r.EndsWith(resourceName, StringComparison.OrdinalIgnoreCase));
return new StreamReader(asm.GetManifestResourceStream(fullResourceName)).ReadToEnd();
}
static Lazy<string> ilasm = new Lazy<string>(() => ToolLocator.FindTool("ilasm.exe"));
static Lazy<string> ildasm = new Lazy<string>(() => ToolLocator.FindTool("ildasm.exe"));
public static string CompileIL(string source)
{
if (ilasm.Value == null)
Assert.NotNull(ilasm.Value, "Could not find ILASM.exe");
var tmp = Path.GetTempFileName();
File.Delete(tmp);
var sourceFile = Path.ChangeExtension(tmp, ".il");
File.WriteAllText(sourceFile, source);
var asmFile = Path.ChangeExtension(sourceFile, ".dll");
var args = string.Format("{0} /dll /debug /output:{1}", sourceFile, asmFile);
using (var proc = Process.Start(new ProcessStartInfo(ilasm.Value, args) { UseShellExecute = false, }))
{
proc.WaitForExit();
Assert.AreEqual(0, proc.ExitCode);
}
File.Delete(sourceFile);
Assert.True(File.Exists(asmFile), "Assembly File does not exist");
return asmFile;
}
public static void RunIL(string ilCode, string expectedCSharpCode)
{
var asmFilePath = CompileIL(ilCode);
CompareAssemblyAgainstCSharp(expectedCSharpCode, asmFilePath);
}
private static void CompareAssemblyAgainstCSharp(string expectedCSharpCode, string asmFilePath)
{
var module = ModuleDefinition.ReadModule(asmFilePath);
try
{
try { module.ReadSymbols(); } catch { }
AstBuilder decompiler = new AstBuilder(new DecompilerContext(module));
decompiler.AddAssembly(module);
new Helpers.RemoveCompilerAttribute().Run(decompiler.SyntaxTree);
StringWriter output = new StringWriter();
// the F# assembly contains a namespace `<StartupCode$tmp6D55>` where the part after tmp is randomly generated.
// remove this from the ast to simplify the diff
var startupCodeNode = decompiler.SyntaxTree.Children.OfType<NamespaceDeclaration>().SingleOrDefault(d => d.Name.StartsWith("<StartupCode$", StringComparison.Ordinal));
if (startupCodeNode != null)
startupCodeNode.Remove();
decompiler.GenerateCode(new PlainTextOutput(output));
var fullCSharpCode = output.ToString();
CodeAssert.AreEqual(expectedCSharpCode, output.ToString());
}
finally
{
File.Delete(asmFilePath);
File.Delete(Path.ChangeExtension(asmFilePath, ".pdb"));
}
}
}
}

99
ICSharpCode.Decompiler/Tests/FSharpPatterns/ToolLocator.cs

@ -0,0 +1,99 @@ @@ -0,0 +1,99 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.Tests.FSharpPatterns
{
public class ToolLocator
{
public static string FindTool(string fileName)
{
var allPaths = FindPathForDotNetFramework().Concat(FindPathForWindowsSdk());
return allPaths.Select(dir => Path.Combine(dir, fileName)).FirstOrDefault(File.Exists);
}
private static IEnumerable<string> FindPathForWindowsSdk()
{
string[] windowsSdkPaths = new[]
{
@"Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\",
@"Microsoft SDKs\Windows\v8.0A\bin\",
@"Microsoft SDKs\Windows\v8.0\bin\NETFX 4.0 Tools\",
@"Microsoft SDKs\Windows\v8.0\bin\",
@"Microsoft SDKs\Windows\v7.1A\bin\NETFX 4.0 Tools\",
@"Microsoft SDKs\Windows\v7.1A\bin\",
@"Microsoft SDKs\Windows\v7.0A\bin\NETFX 4.0 Tools\",
@"Microsoft SDKs\Windows\v7.0A\bin\",
@"Microsoft SDKs\Windows\v6.1A\bin\",
@"Microsoft SDKs\Windows\v6.0A\bin\",
@"Microsoft SDKs\Windows\v6.0\bin\",
@"Microsoft.NET\FrameworkSDK\bin"
};
foreach (var possiblePath in windowsSdkPaths)
{
string fullPath = string.Empty;
// Check alternate program file paths as well as 64-bit versions.
if (Environment.Is64BitProcess)
{
fullPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), possiblePath, "x64");
if (Directory.Exists(fullPath))
{
yield return fullPath;
}
fullPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), possiblePath, "x64");
if (Directory.Exists(fullPath))
{
yield return fullPath;
}
}
fullPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), possiblePath);
if (Directory.Exists(fullPath))
{
yield return fullPath;
}
fullPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), possiblePath);
if (Directory.Exists(fullPath))
{
yield return fullPath;
}
}
}
private static IEnumerable<string> FindPathForDotNetFramework()
{
string[] frameworkPaths = new[]
{
@"Microsoft.NET\Framework\v4.0.30319",
@"Microsoft.NET\Framework\v2.0.50727"
};
foreach (var possiblePath in frameworkPaths)
{
string fullPath = string.Empty;
if (Environment.Is64BitProcess)
{
fullPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), possiblePath.Replace(@"\Framework\", @"\Framework64\"));
if (Directory.Exists(fullPath))
{
yield return fullPath;
}
}
fullPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), possiblePath);
if (Directory.Exists(fullPath))
{
yield return fullPath;
}
}
}
}
}

30
ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj

@ -54,6 +54,14 @@ @@ -54,6 +54,14 @@
<Reference Include="DiffLib">
<HintPath>..\..\packages\DiffLib.1.0.0.55\lib\net35-Client\DiffLib.dll</HintPath>
</Reference>
<Reference Include="nunit.core, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<HintPath>..\..\packages\NUnitTestAdapter.2.0.0\lib\nunit.core.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="nunit.core.interfaces, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<HintPath>..\..\packages\NUnitTestAdapter.2.0.0\lib\nunit.core.interfaces.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="nunit.framework">
<HintPath>..\..\packages\NUnit.2.6.3\lib\nunit.framework.dll</HintPath>
</Reference>
@ -62,6 +70,15 @@ @@ -62,6 +70,15 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\packages\Microsoft.Bcl.Immutable.1.1.22-beta\lib\portable-net45+win8+wpa81\System.Collections.Immutable.dll</HintPath>
</Reference>
<Reference Include="nunit.util, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<HintPath>..\..\packages\NUnitTestAdapter.2.0.0\lib\nunit.util.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="NUnit.VisualStudio.TestAdapter, Version=2.0.0.0, Culture=neutral, PublicKeyToken=4cb40d35494691ac, processorArchitecture=MSIL">
<HintPath>..\..\packages\NUnitTestAdapter.2.0.0\lib\NUnit.VisualStudio.TestAdapter.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
@ -75,23 +92,20 @@ @@ -75,23 +92,20 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\cecil\Mono.Cecil.csproj">
<Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project>
<Project>{d68133bd-1e63-496e-9ede-4fbdbf77b486}</Project>
<Name>Mono.Cecil</Name>
</ProjectReference>
<ProjectReference Include="..\..\NRefactory\ICSharpCode.NRefactory.Cecil\ICSharpCode.NRefactory.Cecil.csproj">
<Project>{2B8F4F83-C2B3-4E84-A27B-8DEE1BE0E006}</Project>
<Name>ICSharpCode.NRefactory.Cecil</Name>
</ProjectReference>
<ProjectReference Include="..\..\NRefactory\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory.CSharp.csproj">
<Project>{53DCA265-3C3C-42F9-B647-F72BA678122B}</Project>
<Project>{53dca265-3c3c-42f9-b647-f72ba678122b}</Project>
<Name>ICSharpCode.NRefactory.CSharp</Name>
</ProjectReference>
<ProjectReference Include="..\..\NRefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">
<Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project>
<Project>{3b2a5653-ec97-4001-bb9b-d90f1af2c371}</Project>
<Name>ICSharpCode.NRefactory</Name>
</ProjectReference>
<ProjectReference Include="..\ICSharpCode.Decompiler.csproj">
<Project>{984CC812-9470-4A13-AFF9-CC44068D666C}</Project>
<Project>{984cc812-9470-4a13-aff9-cc44068d666c}</Project>
<Name>ICSharpCode.Decompiler</Name>
</ProjectReference>
</ItemGroup>

28
ICSharpCode.Decompiler/Tests/NotUsingBlock.cs

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
using System;
using System.IO;
namespace ICSharpCode.Decompiler.Tests
{
public class NotUsingBlock
{
public void ThisIsNotAUsingBlock()
{
object obj = File.OpenRead("...");
IDisposable disposable;
try
{
(obj as FileStream).WriteByte(2);
Console.WriteLine("some text");
}
finally
{
disposable = (obj as IDisposable);
if (disposable != null)
{
disposable.Dispose();
}
}
Console.WriteLine(disposable);
}
}
}

1
ICSharpCode.Decompiler/Tests/packages.config

@ -3,4 +3,5 @@ @@ -3,4 +3,5 @@
<package id="DiffLib" version="1.0.0.55" />
<package id="Microsoft.Bcl.Immutable" version="1.1.22-beta" targetFramework="net45" />
<package id="NUnit" version="2.6.3" targetFramework="net45" />
<package id="NUnitTestAdapter" version="2.0.0" targetFramework="net45" />
</packages>

269
ILSpy.AddIn/CodeElementXmlDocKeyProvider.cs

@ -0,0 +1,269 @@ @@ -0,0 +1,269 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ICSharpCode.ILSpy.AddIn
{
/// <summary>
/// Provides XML documentation tags for Visual Studio CodeElements.
/// </summary>
/// <remarks>
/// Used to support the "/navigateTo" command line option when opening ILSpy. Must match
/// the logic of ICSharpCode.ILSpy.XmlDoc.XmlDocKeyProvider, which does the same thing for
/// a Mono.Cecil.MemberReference. See "ID string format" in Appendix A of the C# language
/// specification for formatting requirements, and Samples/ILSpyAddInSamples.cs for examples.
/// </remarks>
public static class CodeElementXmlDocKeyProvider
{
#region GetKey
public static string GetKey(EnvDTE.CodeElement member)
{
StringBuilder b = new StringBuilder();
if ((member.Kind == EnvDTE.vsCMElement.vsCMElementDelegate) ||
(member.Kind == EnvDTE.vsCMElement.vsCMElementEnum) ||
(member.Kind == EnvDTE.vsCMElement.vsCMElementInterface) ||
(member.Kind == EnvDTE.vsCMElement.vsCMElementStruct) ||
(member.Kind == EnvDTE.vsCMElement.vsCMElementClass)) {
b.Append("T:");
AppendTypeName(b, member.FullName, true, false);
}
else if (member.Kind == EnvDTE.vsCMElement.vsCMElementNamespace){
b.Append("N:");
b.Append(member.FullName);
}
else {
if (member.Kind == EnvDTE.vsCMElement.vsCMElementVariable)
b.Append("F:");
else if (member.Kind == EnvDTE.vsCMElement.vsCMElementProperty)
b.Append("P:");
else if (member.Kind == EnvDTE.vsCMElement.vsCMElementEvent)
b.Append("E:");
else if (member.Kind == EnvDTE.vsCMElement.vsCMElementFunction)
b.Append("M:");
int nameIndex = member.FullName.LastIndexOf(member.Name);
string typeName = member.FullName.Substring(0, nameIndex - 1);
string memberName = member.FullName.Substring(nameIndex);
// Name substitutions for special cases.
if (member.Kind == EnvDTE.vsCMElement.vsCMElementFunction) {
EnvDTE80.CodeFunction2 mr = (EnvDTE80.CodeFunction2)member;
if (mr.FunctionKind == EnvDTE.vsCMFunction.vsCMFunctionConstructor) {
memberName = memberName.Replace(member.Name, "#ctor");
}
else if (mr.FunctionKind == EnvDTE.vsCMFunction.vsCMFunctionDestructor) {
memberName = memberName.Replace(member.Name, "Finalize");
}
else if (mr.FunctionKind == EnvDTE.vsCMFunction.vsCMFunctionOperator) {
if (memberName.StartsWith("implicit operator")) {
memberName = "op_Implicit";
}
else if (memberName.StartsWith("explicit operator")) {
memberName = "op_Explicit";
}
else {
// NRefactory has a handy mapping we can make use of, just need to extract the operator sybol first.
string[] memberNameWords = member.Name.Split(' ');
if (memberNameWords.Length >= 2) {
string operatorSymbol = memberNameWords[1];
string operatorName = ICSharpCode.NRefactory.MonoCSharp.Operator.GetMetadataName(operatorSymbol);
if (operatorName != null) {
memberName = memberName.Replace(member.Name, operatorName);
}
}
}
}
}
else if (member.Kind == EnvDTE.vsCMElement.vsCMElementProperty) {
if (member.Name == "this") {
memberName = memberName.Replace(member.Name, "Item");
}
}
string[] genericTypeParameters = AppendTypeName(b, typeName, true, false);
b.Append('.');
string[] genericMethodParameters = AppendTypeName(b, memberName.Replace('.', '#'), true, true);
EnvDTE.CodeElements parameters;
EnvDTE.CodeTypeRef explicitReturnType = null;
if (member.Kind == EnvDTE.vsCMElement.vsCMElementProperty) {
parameters = ((EnvDTE.CodeProperty)member).Getter.Parameters;
}
else if (member.Kind == EnvDTE.vsCMElement.vsCMElementFunction) {
EnvDTE80.CodeFunction2 mr = (EnvDTE80.CodeFunction2)member;
parameters = mr.Parameters;
if (memberName == "op_Implicit" || memberName == "op_Explicit") {
explicitReturnType = mr.Type;
}
}
else {
parameters = null;
}
if (parameters != null && parameters.Count > 0) {
b.Append('(');
int i = 0;
foreach (EnvDTE80.CodeParameter2 parameter in parameters) {
if (i > 0) b.Append(',');
AppendParameterTypeName(b, parameter, genericTypeParameters, genericMethodParameters);
++i;
}
b.Append(')');
}
if (explicitReturnType != null) {
b.Append('~');
AppendTypeName(b, explicitReturnType.AsFullName, true, false);
}
}
return b.ToString();
}
static string[] AppendTypeName(StringBuilder b, string typeName, bool appendGenericParameterCount, bool isMethod)
{
List<string> allGenericParameters = new List<string>();
StringBuilder genericParameterName = new StringBuilder();
bool inGenericParameters = false;
int genericParameterCount = 0;
foreach (char ch in typeName) {
if (inGenericParameters) {
switch (ch) {
case ',':
++genericParameterCount;
allGenericParameters.Add(genericParameterName.ToString());
genericParameterName.Clear();
break;
case '>':
++genericParameterCount;
allGenericParameters.Add(genericParameterName.ToString());
genericParameterName.Clear();
if (appendGenericParameterCount) {
b.Append(genericParameterCount);
}
inGenericParameters = false;
break;
case ' ':
break;
default:
genericParameterName.Append(ch);
break;
}
}
else {
switch (ch) {
case '<':
if (appendGenericParameterCount) {
b.Append('`');
if (isMethod) {
b.Append('`');
}
}
inGenericParameters = true;
genericParameterCount = 0;
break;
case '[':
case ']':
break;
default:
b.Append(ch);
break;
}
}
}
return allGenericParameters.ToArray();
}
private static void AppendParameterTypeName(StringBuilder b, EnvDTE80.CodeParameter2 parameter, string[] genericTypeParameters, string[] genericMethodParameters)
{
EnvDTE80.CodeTypeRef2 parameterTypeRef = (EnvDTE80.CodeTypeRef2)parameter.Type;
string parameterTypeString = parameterTypeRef.AsFullName;
int substringStart = 0;
for (int i = 0; i < parameterTypeString.Length; ++i) {
char ch = parameterTypeString[i];
switch (ch) {
case '<':
AppendParameterTypeSubstring(b, parameterTypeString, substringStart, i, genericTypeParameters, genericMethodParameters);
substringStart = i + 1;
b.Append('{');
break;
case '>':
AppendParameterTypeSubstring(b, parameterTypeString, substringStart, i, genericTypeParameters, genericMethodParameters);
substringStart = i + 1;
b.Append('}');
break;
case '[':
AppendParameterTypeSubstring(b, parameterTypeString, substringStart, i, genericTypeParameters, genericMethodParameters);
b.Append('[');
// Skip ahead to the closing bracket, counting commas to determine array rank.
int rank = 1;
do {
++i;
ch = parameterTypeString[i];
if (ch == ',') {
++rank;
}
}
while (ch != ']');
substringStart = i + 1;
// For multi-dimensional arrays, add "0:" default array bounds. Note that non-standard bounds are not possible via C# declaration.
if (rank > 1) {
for (int r = 0; r < rank; ++r) {
if (r != 0) {
b.Append(',');
}
b.Append("0:");
}
}
b.Append(']');
break;
case ',':
AppendParameterTypeSubstring(b, parameterTypeString, substringStart, i, genericTypeParameters, genericMethodParameters);
substringStart = i + 1;
// Skip space after comma if present. (e.g. System.Collections.Generic.KeyValuePair`2{System.String,System.String}.)
if (parameterTypeString[substringStart] == ' ') {
++substringStart;
}
b.Append(',');
break;
}
}
AppendParameterTypeSubstring(b, parameterTypeString, substringStart, parameterTypeString.Length, genericTypeParameters, genericMethodParameters);
// Append ref / out indicator if needed.
if ((parameter.ParameterKind == EnvDTE80.vsCMParameterKind.vsCMParameterKindRef) ||
(parameter.ParameterKind == EnvDTE80.vsCMParameterKind.vsCMParameterKindOut)) {
b.Append('@');
}
// Note there is no need to append a '*' for pointers, as this is included in the full name of the type.
// Multi-dimensional and jagged arrays are handled above during string parsing.
}
private static void AppendParameterTypeSubstring(StringBuilder b, string parameterTypeString, int substringStart, int substringStop, string[] genericTypeParameters, string[] genericMethodParameters)
{
if (substringStart < substringStop) {
string substring = parameterTypeString.Substring(substringStart, substringStop - substringStart);
int indexOfGenericTypeParameter = Array.IndexOf(genericTypeParameters, substring);
int indexOfGenericMethodParameter = Array.IndexOf(genericMethodParameters, substring);
if (indexOfGenericTypeParameter >= 0) {
b.Append("`");
b.Append(indexOfGenericTypeParameter);
}
else if (indexOfGenericMethodParameter >= 0) {
b.Append("``");
b.Append(indexOfGenericMethodParameter);
}
else {
b.Append(substring);
}
}
}
#endregion
}
}

14
ILSpy.AddIn/ILSpy.AddIn.csproj

@ -141,6 +141,7 @@ @@ -141,6 +141,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Guids.cs" />
<Compile Include="CodeElementXmlDocKeyProvider.cs" />
<Compile Include="Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
@ -150,6 +151,7 @@ @@ -150,6 +151,7 @@
<Compile Include="ILSpyAddInPackage.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="PkgCmdID.cs" />
<None Include="Samples\ILSpyAddInSamples.cs" />
<Compile Include="Utils.cs" />
</ItemGroup>
<ItemGroup>
@ -209,20 +211,24 @@ @@ -209,20 +211,24 @@
<Project>{1E85EFF9-E370-4683-83E4-8A3D063FF791}</Project>
<Name>ILSpy</Name>
</ProjectReference>
<ProjectReference Include="..\cecil\Mono.Cecil.csproj">
<Project>{d68133bd-1e63-496e-9ede-4fbdbf77b486}</Project>
<Name>Mono.Cecil</Name>
</ProjectReference>
<ProjectReference Include="..\cecil\symbols\pdb\Mono.Cecil.Pdb.csproj">
<Project>{63E6915C-7EA4-4D76-AB28-0D7191EEA626}</Project>
<Project>{63e6915c-7ea4-4d76-ab28-0d7191eea626}</Project>
<Name>Mono.Cecil.Pdb</Name>
</ProjectReference>
<ProjectReference Include="..\NRefactory\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory.CSharp.csproj">
<Project>{53DCA265-3C3C-42F9-B647-F72BA678122B}</Project>
<Project>{53dca265-3c3c-42f9-b647-f72ba678122b}</Project>
<Name>ICSharpCode.NRefactory.CSharp</Name>
</ProjectReference>
<ProjectReference Include="..\NRefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">
<Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project>
<Project>{3b2a5653-ec97-4001-bb9b-d90f1af2c371}</Project>
<Name>ICSharpCode.NRefactory</Name>
</ProjectReference>
<ProjectReference Include="..\SharpTreeView\ICSharpCode.TreeView.csproj">
<Project>{DDE2A481-8271-4EAC-A330-8FA6A38D13D1}</Project>
<Project>{dde2a481-8271-4eac-a330-8fa6a38d13d1}</Project>
<Name>ICSharpCode.TreeView</Name>
</ProjectReference>
</ItemGroup>

14
ILSpy.AddIn/ILSpyAddIn.vsct

@ -47,6 +47,10 @@ @@ -47,6 +47,10 @@
<Group guid="guidILSpyAddInCmdSet" id="OpenILSpyProjGroup" priority="0x0200">
<Parent guid="guidSHLMainMenu" id="IDM_VS_CTXT_PROJNODE"/>
</Group>
<Group guid="guidILSpyAddInCmdSet" id="OpenILSpyCodeItemGroup" priority="0x0200">
<Parent guid="guidSHLMainMenu" id="IDM_VS_CTXT_CODEWIN"/>
</Group>
</Groups>
<!--Buttons section. -->
@ -77,6 +81,14 @@ @@ -77,6 +81,14 @@
</Strings>
</Button>
<Button guid="guidILSpyAddInCmdSet" id="cmdidOpenCodeItemInILSpy" priority="0x0600" type="Button">
<Parent guid="guidILSpyAddInCmdSet" id="OpenILSpyCodeItemGroup" />
<Icon guid="guidImages" id="bmpLogo" />
<Strings>
<ButtonText>Open code in ILSpy</ButtonText>
</Strings>
</Button>
<Button guid="guidILSpyAddInCmdSet" id="cmdidOpenILSpy" priority="0x0600" type="Button">
<Parent guid="guidILSpyAddInCmdSet" id="OpenILSpyGroup" />
<Icon guid="guidImages" id="bmpLogo" />
@ -114,9 +126,11 @@ @@ -114,9 +126,11 @@
<IDSymbol name="OpenILSpyGroup" value="0x1010" />
<IDSymbol name="OpenILSpyRefGroup" value="0x1020" />
<IDSymbol name="OpenILSpyProjGroup" value="0x1030" />
<IDSymbol name="OpenILSpyCodeItemGroup" value="0x1040" />
<IDSymbol name="cmdidOpenILSpy" value="0x0100" />
<IDSymbol name="cmdidOpenReferenceInILSpy" value="0x0200" />
<IDSymbol name="cmdidOpenProjectOutputInILSpy" value="0x0300" />
<IDSymbol name="cmdidOpenCodeItemInILSpy" value="0x0400" />
</GuidSymbol>
<GuidSymbol name="guidImages" value="{2f654db9-4641-4638-9937-27c6202b2a6a}" >

141
ILSpy.AddIn/ILSpyAddInPackage.cs

@ -66,20 +66,26 @@ namespace ICSharpCode.ILSpy.AddIn @@ -66,20 +66,26 @@ namespace ICSharpCode.ILSpy.AddIn
// Add our command handlers for menu (commands must exist in the .vsct file)
OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
if (null != mcs) {
// Create the command for the menu item.
// Create the command for the References context menu.
CommandID menuCommandID = new CommandID(GuidList.guidILSpyAddInCmdSet, (int)PkgCmdIDList.cmdidOpenReferenceInILSpy);
MenuCommand menuItem = new MenuCommand(OpenReferenceInILSpyCallback, menuCommandID);
mcs.AddCommand(menuItem);
// Create the command for the menu item.
// Create the command for the Project context menu, to open the output assembly.
CommandID menuCommandID2 = new CommandID(GuidList.guidILSpyAddInCmdSet, (int)PkgCmdIDList.cmdidOpenProjectOutputInILSpy);
MenuCommand menuItem2 = new MenuCommand(OpenProjectOutputInILSpyCallback, menuCommandID2);
mcs.AddCommand(menuItem2);
// Create the command for the menu item.
CommandID menuCommandID3 = new CommandID(GuidList.guidILSpyAddInCmdSet, (int)PkgCmdIDList.cmdidOpenILSpy);
MenuCommand menuItem3 = new MenuCommand(OpenILSpyCallback, menuCommandID3);
// Create the command for the code window context menu.
CommandID menuCommandID3 = new CommandID(GuidList.guidILSpyAddInCmdSet, (int)PkgCmdIDList.cmdidOpenCodeItemInILSpy);
OleMenuCommand menuItem3 = new OleMenuCommand(OpenCodeItemInILSpyCallback, menuCommandID3);
menuItem3.BeforeQueryStatus += OpenCodeItemInILSpyCallback_BeforeQueryStatus;
mcs.AddCommand(menuItem3);
// Create the command for the Tools menu item.
CommandID menuCommandID4 = new CommandID(GuidList.guidILSpyAddInCmdSet, (int)PkgCmdIDList.cmdidOpenILSpy);
MenuCommand menuItem4 = new MenuCommand(OpenILSpyCallback, menuCommandID4);
mcs.AddCommand(menuItem4);
}
}
#endregion
@ -92,14 +98,14 @@ namespace ICSharpCode.ILSpy.AddIn @@ -92,14 +98,14 @@ namespace ICSharpCode.ILSpy.AddIn
private void OpenReferenceInILSpyCallback(object sender, EventArgs e)
{
var explorer = ((EnvDTE80.DTE2)GetGlobalService(typeof(EnvDTE.DTE))).ToolWindows.SolutionExplorer;
var items =(object[]) explorer.SelectedItems;
var items = (object[])explorer.SelectedItems;
foreach (EnvDTE.UIHierarchyItem item in items) {
dynamic reference = item.Object;
var reference = GetReference(item.Object);
string path = null;
if (reference.PublicKeyToken != "") {
if (!string.IsNullOrEmpty(reference.PublicKeyToken)) {
var token = Utils.HexStringToBytes(reference.PublicKeyToken);
path = GacInterop.FindAssemblyInNetGac(new AssemblyNameReference(reference.Identity, new Version(reference.Version)) { PublicKeyToken = token });
path = GacInterop.FindAssemblyInNetGac(new AssemblyNameReference(reference.Name, reference.Version) { PublicKeyToken = token });
}
if (path == null)
path = reference.Path;
@ -107,6 +113,38 @@ namespace ICSharpCode.ILSpy.AddIn @@ -107,6 +113,38 @@ namespace ICSharpCode.ILSpy.AddIn
}
}
class ReferenceInfo
{
public string Name { get; set; }
public string PublicKeyToken { get; set; }
public string Path { get; set; }
public Version Version { get; set; }
}
private ReferenceInfo GetReference(object o)
{
dynamic obj = o;
string referenceType = o.GetType().FullName;
// C++
if (referenceType.StartsWith("Microsoft.VisualStudio.PlatformUI", StringComparison.Ordinal)) {
return new ReferenceInfo { Path = obj.Name };
}
// F#
if (referenceType.StartsWith("Microsoft.VisualStudio.FSharp", StringComparison.Ordinal)) {
obj = obj.Object;
}
// C# and VB
return new ReferenceInfo {
Name = obj.Identity,
PublicKeyToken = obj.PublicKeyToken,
Path = obj.Path,
Version = new Version(obj.Version)
};
}
private void OpenProjectOutputInILSpyCallback(object sender, EventArgs e)
{
var explorer = ((EnvDTE80.DTE2)GetGlobalService(typeof(EnvDTE.DTE))).ToolWindows.SolutionExplorer;
@ -114,14 +152,70 @@ namespace ICSharpCode.ILSpy.AddIn @@ -114,14 +152,70 @@ namespace ICSharpCode.ILSpy.AddIn
foreach (EnvDTE.UIHierarchyItem item in items) {
EnvDTE.Project project = (EnvDTE.Project)item.Object;
EnvDTE.Configuration config = project.ConfigurationManager.ActiveConfiguration;
string projectPath = Path.GetDirectoryName(project.FileName);
string outputPath = config.Properties.Item("OutputPath").Value.ToString();
string assemblyFileName = project.Properties.Item("OutputFileName").Value.ToString();
OpenAssemblyInILSpy(Path.Combine(projectPath, outputPath, assemblyFileName));
OpenProjectInILSpy(project);
}
}
// Called when the menu is popped, determines whether "Open code in ILSpy" option is available.
private void OpenCodeItemInILSpyCallback_BeforeQueryStatus(object sender, EventArgs e)
{
OleMenuCommand menuItem = sender as OleMenuCommand;
if (menuItem != null) {
var document = (EnvDTE.Document)(((EnvDTE80.DTE2)GetGlobalService(typeof(EnvDTE.DTE))).ActiveDocument);
menuItem.Enabled =
(document != null) &&
(document.ProjectItem != null) &&
(document.ProjectItem.ContainingProject != null) &&
(document.ProjectItem.ContainingProject.ConfigurationManager != null) &&
!string.IsNullOrEmpty(document.ProjectItem.ContainingProject.FileName);
}
}
private void OpenCodeItemInILSpyCallback(object sender, EventArgs e)
{
var document = (EnvDTE.Document)(((EnvDTE80.DTE2)GetGlobalService(typeof(EnvDTE.DTE))).ActiveDocument);
var selection = (EnvDTE.TextPoint)((EnvDTE.TextSelection)document.Selection).ActivePoint;
// Search code elements in desired order, working from innermost to outermost.
// Should eventually find something, and if not we'll just open the assembly itself.
var codeElement = GetSelectedCodeElement(selection,
EnvDTE.vsCMElement.vsCMElementFunction,
EnvDTE.vsCMElement.vsCMElementEvent,
EnvDTE.vsCMElement.vsCMElementVariable, // There is no vsCMElementField, fields are just variables outside of function scope.
EnvDTE.vsCMElement.vsCMElementProperty,
EnvDTE.vsCMElement.vsCMElementDelegate,
EnvDTE.vsCMElement.vsCMElementEnum,
EnvDTE.vsCMElement.vsCMElementInterface,
EnvDTE.vsCMElement.vsCMElementStruct,
EnvDTE.vsCMElement.vsCMElementClass,
EnvDTE.vsCMElement.vsCMElementNamespace);
if (codeElement != null) {
OpenCodeItemInILSpy(codeElement);
}
else {
OpenProjectInILSpy(document.ProjectItem.ContainingProject);
}
}
private EnvDTE.CodeElement GetSelectedCodeElement(EnvDTE.TextPoint selection, params EnvDTE.vsCMElement[] elementTypes)
{
foreach (var elementType in elementTypes) {
var codeElement = selection.CodeElement[elementType];
if (codeElement != null) {
return codeElement;
}
}
return null;
}
private void OpenCodeItemInILSpy(EnvDTE.CodeElement codeElement)
{
string codeElementKey = CodeElementXmlDocKeyProvider.GetKey(codeElement);
OpenProjectInILSpy(codeElement.ProjectItem.ContainingProject, "/navigateTo:" + codeElementKey);
}
private void OpenILSpyCallback(object sender, EventArgs e)
{
Process.Start(GetILSpyPath());
@ -133,13 +227,28 @@ namespace ICSharpCode.ILSpy.AddIn @@ -133,13 +227,28 @@ namespace ICSharpCode.ILSpy.AddIn
return Path.Combine(basePath, "ILSpy.exe");
}
private void OpenAssemblyInILSpy(string assemblyFileName)
private void OpenProjectInILSpy(EnvDTE.Project project, params string[] arguments)
{
EnvDTE.Configuration config = project.ConfigurationManager.ActiveConfiguration;
string projectPath = Path.GetDirectoryName(project.FileName);
string outputPath = config.Properties.Item("OutputPath").Value.ToString();
string assemblyFileName = project.Properties.Item("OutputFileName").Value.ToString();
OpenAssemblyInILSpy(Path.Combine(projectPath, outputPath, assemblyFileName), arguments);
}
private void OpenAssemblyInILSpy(string assemblyFileName, params string[] arguments)
{
if (!File.Exists(assemblyFileName)) {
ShowMessage("Could not find assembly '{0}', please ensure the project and all references were built correctly!", assemblyFileName);
return;
}
Process.Start(GetILSpyPath(), Utils.ArgumentArrayToCommandLine(assemblyFileName));
string commandLineArguments = Utils.ArgumentArrayToCommandLine(assemblyFileName);
if (arguments != null) {
commandLineArguments = string.Concat(commandLineArguments, " ", Utils.ArgumentArrayToCommandLine(arguments));
}
Process.Start(GetILSpyPath(), commandLineArguments);
}
private void ShowMessage(string format, params object[] items)

1
ILSpy.AddIn/PkgCmdID.cs

@ -9,5 +9,6 @@ namespace ICSharpCode.ILSpy.AddIn @@ -9,5 +9,6 @@ namespace ICSharpCode.ILSpy.AddIn
public const uint cmdidOpenILSpy = 0x100;
public const uint cmdidOpenReferenceInILSpy = 0x200;
public const uint cmdidOpenProjectOutputInILSpy = 0x300;
public const uint cmdidOpenCodeItemInILSpy = 0x0400;
};
}

4
ILSpy.AddIn/Properties/AssemblyInfo.cs

@ -29,8 +29,8 @@ using System.Runtime.InteropServices; @@ -29,8 +29,8 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("1.5.0.0")]
[assembly: AssemblyFileVersion("1.5.0.0")]
[assembly: InternalsVisibleTo("ILSpy.AddIn_IntegrationTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100653c4a319be4f524972c3c5bba5fd243330f8e900287d9022d7821a63fd0086fd3801e3683dbe9897f2ecc44727023e9b40adcf180730af70c81c54476b3e5ba8b0f07f5132b2c3cc54347a2c1a9d64ebaaaf3cbffc1a18c427981e2a51d53d5ab02536b7550e732f795121c38a0abfdb38596353525d034baf9e6f1fd8ac4ac")]
[assembly: InternalsVisibleTo("ILSpy.AddIn_UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100653c4a319be4f524972c3c5bba5fd243330f8e900287d9022d7821a63fd0086fd3801e3683dbe9897f2ecc44727023e9b40adcf180730af70c81c54476b3e5ba8b0f07f5132b2c3cc54347a2c1a9d64ebaaaf3cbffc1a18c427981e2a51d53d5ab02536b7550e732f795121c38a0abfdb38596353525d034baf9e6f1fd8ac4ac")]

414
ILSpy.AddIn/Samples/ILSpyAddInSamples.cs

@ -0,0 +1,414 @@ @@ -0,0 +1,414 @@
using System;
using System.Collections;
using System.Collections.Generic;
/// Sample source file indicating a wide variety of code elements that should work
/// with the "Open code in ILSpy" Visual Studio add-in feature. Each code element is
/// commented with the string generated by CodeElementXmlDocKeyProvider.GetKey and
/// used with the ILSpy /navigateTo command line option.
///
/// Note that this code is not compiled or used in the project in any way, it is
/// only provided for reference.
// N:ILSpy.AddIn.Tests
namespace ILSpy.AddIn.Tests
{
// T:ILSpy.AddIn.Tests.SomeClass
public class SomeClass
{
// E:ILSpy.AddIn.Tests.SomeClass.OnEvent
public event Action OnEvent;
// F:ILSpy.AddIn.Tests.SomeClass.mField
private int mField;
// P:ILSpy.AddIn.Tests.SomeClass.Property
private int Property
{
get
{
return mField;
}
set
{
mField = value;
}
}
// P:ILSpy.AddIn.Tests.SomeClass.Item(System.Int32,System.Int32)
public int this[int x, int y]
{
get { return x + y + mField; }
}
// M:ILSpy.AddIn.Tests.SomeClass.#ctor
public SomeClass()
{
mField = 0;
}
// M:ILSpy.AddIn.Tests.SomeClass.#ctor(System.Int32)
public SomeClass(int x)
{
mField = x;
}
// M:ILSpy.AddIn.Tests.SomeClass.#ctor(System.Int32,System.Int32)
public SomeClass(int x, int y)
{
mField = x + y;
}
// M:ILSpy.AddIn.Tests.SomeClass.Method
public int Method()
{
return mField;
}
// M:ILSpy.AddIn.Tests.SomeClass.MethodWithGenericParameter(System.IEquatable{System.String})
public void MethodWithGenericParameter(IEquatable<string> x)
{
}
// M:ILSpy.AddIn.Tests.SomeClass.MethodWithGenericParameter(System.IEquatable{System.String},System.Int32)
public void MethodWithGenericParameter(IEquatable<string> x, int y)
{
}
// M:ILSpy.AddIn.Tests.SomeClass.GenericMethod``1(``0)
public int GenericMethod<T>(T x)
{
return mField + x.GetHashCode();
}
// M:ILSpy.AddIn.Tests.SomeClass.GenericOverloadedMethod``1(System.Int32,``0)
public int GenericOverloadedMethod<T1>(int x, T1 y)
{
return mField + x + y.GetHashCode();
}
// M:ILSpy.AddIn.Tests.SomeClass.GenericOverloadedMethod``2(System.Int32,``0,``1)
public int GenericOverloadedMethod<T1, T2>(int x, T1 y, T2 z)
{
return mField + x + y.GetHashCode() + z.GetHashCode();
}
// M:ILSpy.AddIn.Tests.SomeClass.OverloadedMethod
public int OverloadedMethod()
{
return mField * mField;
}
// M:ILSpy.AddIn.Tests.SomeClass.OverloadedMethod(System.Int32)
public int OverloadedMethod(int m)
{
return mField * m;
}
// M:ILSpy.AddIn.Tests.SomeClass.OverloadedMethod(System.Int32,System.Int32)
public int OverloadedMethod(int m1, int m2)
{
return mField * m1 * m2;
}
// M:ILSpy.AddIn.Tests.SomeClass.OverloadedGenericMethod``1
public int OverloadedGenericMethod<T>()
{
return mField * mField;
}
// M:ILSpy.AddIn.Tests.SomeClass.OverloadedGenericMethod``1(System.Int32)
public int OverloadedGenericMethod<T>(int m)
{
return mField * m;
}
// M:ILSpy.AddIn.Tests.SomeClass.OverloadedGenericMethod``1(System.Int32,System.Int32)
public int OverloadedGenericMethod<T>(int m1, int m2)
{
return mField * m1 * m2;
}
// M:ILSpy.AddIn.Tests.SomeClass.OverloadedGenericMethod``1(System.Int32,System.Int32,System.Collections.IEnumerable)
public int OverloadedGenericMethod<T>(int m1, int m2, IEnumerable m3)
{
return mField * m1 * m2;
}
// M:ILSpy.AddIn.Tests.SomeClass.OverloadedGenericMethod``1(System.Int32,System.Int32,System.Collections.Generic.IEnumerable{``0})
public int OverloadedGenericMethod<T>(int m1, int m2, IEnumerable<T> m3)
{
return mField * m1 * m2;
}
// M:ILSpy.AddIn.Tests.SomeClass.OverloadedGenericMethod``1(System.Int32,System.Int32,System.Collections.Generic.IEnumerable{System.String})
public int OverloadedGenericMethod<T>(int m1, int m2, IEnumerable<string> m3)
{
return mField * m1 * m2;
}
// M:ILSpy.AddIn.Tests.SomeClass.OverloadedGenericMethod``1(System.Collections.Generic.IEnumerable{System.Collections.Generic.IEnumerable{ILSpy.AddIn.Tests.SomeGenericClass{System.String,``0}}})
public int OverloadedGenericMethod<T>(IEnumerable<IEnumerable<SomeGenericClass<string, T>>> m3)
{
return mField;
}
// M:ILSpy.AddIn.Tests.SomeClass.OverloadedGenericMethod``1(ILSpy.AddIn.Tests.SomeGenericClass{``0,ILSpy.AddIn.Tests.SomeGenericClass{``0,``0}}.NestedGeneric{System.String,``0})
public void OverloadedGenericMethod<T>(SomeGenericClass<T, SomeGenericClass<T, T>>.NestedGeneric<string, T> wow)
{
}
// T:ILSpy.AddIn.Tests.SomeClass.NestedEnum
public enum NestedEnum
{
// F:ILSpy.AddIn.Tests.SomeClass.NestedEnum.First
First = 1,
Second = 2,
Third = 3
}
// T:ILSpy.AddIn.Tests.SomeClass.NestedInterface
public interface NestedInterface
{
// P:ILSpy.AddIn.Tests.SomeClass.NestedInterface.SomeProperty
int SomeProperty { get; }
// M:ILSpy.AddIn.Tests.SomeClass.NestedInterface.SomeMethod
int SomeMethod();
}
// T:ILSpy.AddIn.Tests.SomeClass.NestedClass
public class NestedClass : NestedInterface
{
// F:ILSpy.AddIn.Tests.SomeClass.NestedClass.mX
private int mX;
// M:ILSpy.AddIn.Tests.SomeClass.NestedClass.#ctor(System.Int32)
public NestedClass(int x)
{
mX = x;
}
// M:ILSpy.AddIn.Tests.SomeClass.NestedClass.#ctor(ILSpy.AddIn.Tests.SomeClass.NestedEnum)
public NestedClass(NestedEnum x)
{
mX = (int)x;
}
// P:ILSpy.AddIn.Tests.SomeClass.NestedClass.SomeProperty
public int SomeProperty
{
get { return mX; }
}
// M:ILSpy.AddIn.Tests.SomeClass.NestedClass.SomeMethod
public int SomeMethod()
{
return mX * mX;
}
}
// T:ILSpy.AddIn.Tests.SomeClass.NestedStruct
public struct NestedStruct : NestedInterface
{
// F:ILSpy.AddIn.Tests.SomeClass.NestedStruct.X
public int X;
// F:ILSpy.AddIn.Tests.SomeClass.NestedStruct.Y
public int Y;
// P:ILSpy.AddIn.Tests.SomeClass.NestedStruct.SomeProperty
public int SomeProperty
{
get { return X + Y; }
}
// M:ILSpy.AddIn.Tests.SomeClass.NestedStruct.SomeMethod
public int SomeMethod()
{
return X * Y;
}
}
}
// T:ILSpy.AddIn.Tests.SomeGenericClass`2
public class SomeGenericClass<T1, T2>
{
// F:ILSpy.AddIn.Tests.SomeGenericClass`2.mField1
T1 mField1;
// F:ILSpy.AddIn.Tests.SomeGenericClass`2.mField2
T2 mField2;
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.#ctor(`0,`1)
public SomeGenericClass(T1 a, T2 b)
{
mField1 = a;
mField2 = b;
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.#ctor(`0)
public SomeGenericClass(T1 a)
{
mField1 = a;
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.#ctor
public SomeGenericClass()
{
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.Finalize
~SomeGenericClass()
{
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.GenericClassMethod(`0,`1)
public void GenericClassMethod(T1 a, T2 b)
{
mField1 = a;
mField2 = b;
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.GenericClassMethod(System.Int32*)
unsafe public void GenericClassMethod(int* x)
{
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.GenericClassMethod(System.Int32*[])
unsafe public void GenericClassMethod(int*[] x)
{
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.GenericClassMethod(`0[]@)
unsafe public void GenericClassMethod(out T1[] x)
{
x = null;
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.GenericClassMethod(System.Int32@)
public void GenericClassMethod(ref int a)
{
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.GenericClassGenericMethod``1(``0@)
public T3 GenericClassGenericMethod<T3>(ref T3 x)
{
return x;
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.GenericClassGenericMethod``1
public T3 GenericClassGenericMethod<T3>()
{
return default(T3);
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.GenericClassGenericMethod``1(System.Int32)
public void GenericClassGenericMethod<T3>(int x)
{
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.GenericClassGenericMethod``2(`0,``1,System.Int32,`1@)
public T4 GenericClassGenericMethod<T3, T4>(T1 x, T4 y, int z, out T2 result)
{
mField1 = x;
string foo = y.ToString() + z.ToString();
result = mField2;
return y;
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.GenericClassGenericMethod``2(`0,``0,System.Int32[])
public T3 GenericClassGenericMethod<T3, T4>(T1 x, T3 y, int[] z)
{
mField1 = x;
string foo = y.ToString() + z.ToString();
return y;
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.ArrayMethod(`0[],System.Int32[])
public void ArrayMethod(T1[] x, int[] y)
{
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.ArrayMethod(`0[0:,0:],System.Int32[0:,0:])
public void ArrayMethod(T1[,] x, int[,] y)
{
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.ArrayMethod(System.Int32[0:,0:],System.Int32[0:,0:])
public void ArrayMethod(int[,] x, int[,] y)
{
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.ArrayMethod(`0[][],System.Int32[][])
public void ArrayMethod(T1[][] x, int[][] y)
{
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.GenericClassGenericMethod``2(`0,``0,ILSpy.AddIn.Tests.SomeClass)
public T3 GenericClassGenericMethod<T3, T4>(T1 x, T3 y, SomeClass z)
{
return y;
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.GenericClassGenericMethod``2(`0,``0,ILSpy.AddIn.Tests.SomeClass[]@)
public T3 GenericClassGenericMethod<T3, T4>(T1 x, T3 y, out SomeClass[] z)
{
z = null;
return y;
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.GenericClassGenericMethod``2(System.Int32[],ILSpy.AddIn.Tests.SomeGenericClass{``0[],``1[0:,0:,0:]}[0:,0:,0:])
public void GenericClassGenericMethod<T3, T4>(int[] x, SomeGenericClass<T3[], T4[,,]>[,,] y)
{
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.op_Addition(ILSpy.AddIn.Tests.SomeGenericClass{`0,`1},ILSpy.AddIn.Tests.SomeGenericClass{`0,`1})
public static SomeGenericClass<T1, T2> operator +(SomeGenericClass<T1, T2> a, SomeGenericClass<T1, T2> b)
{
return new SomeGenericClass<T1, T2>();
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.op_Explicit(ILSpy.AddIn.Tests.SomeGenericClass{`0,`1})~ILSpy.AddIn.Tests.SomeGenericClass`2.NestedGeneric`2
public static explicit operator NestedGeneric<T1, T2>(SomeGenericClass<T1, T2> sgc)
{
return new NestedGeneric<T1, T2>();
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.op_Implicit(ILSpy.AddIn.Tests.SomeGenericClass{`0,`1})~ILSpy.AddIn.Tests.SomeGenericClass`2.NestedGeneric`2
public static implicit operator NestedGeneric<T2, T1>(SomeGenericClass<T1, T2> sgc)
{
return new NestedGeneric<T2, T1>();
}
// T:ILSpy.AddIn.Tests.SomeGenericClass`2.NestedGeneric`2
public class NestedGeneric<T3, T4>
{
// T:ILSpy.AddIn.Tests.SomeGenericClass`2.NestedGeneric`2.NestedDelegate
public delegate int NestedDelegate(T3 x, IEnumerable<T4> y);
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.NestedGeneric`2.NestedGenericMethod``1(`0,``0)
public void NestedGenericMethod<T5>(T1 x, T5 y)
{
}
// M:ILSpy.AddIn.Tests.SomeGenericClass`2.NestedGeneric`2.NestedGenericMethod``3(`0,`3,``0[],System.Collections.Generic.IEnumerable{``2})
public void NestedGenericMethod<T5, T6, T7>(T1 x, T4 y, T5[] z, IEnumerable<T7> w)
{
}
}
}
}
// T:SpaceFreeClass
class SpaceFreeClass
{
// F:SpaceFreeClass.mField
int mField;
// M:SpaceFreeClass.Method
private void Method()
{
}
}

6
ILSpy.AddIn/Utils.cs

@ -74,6 +74,10 @@ namespace ICSharpCode.ILSpy.AddIn @@ -74,6 +74,10 @@ namespace ICSharpCode.ILSpy.AddIn
static void AppendArgument(StringBuilder b, string arg)
{
if (arg == null) {
return;
}
if (arg.Length > 0 && arg.IndexOfAny(charsNeedingQuoting) < 0) {
b.Append(arg);
} else {
@ -102,6 +106,8 @@ namespace ICSharpCode.ILSpy.AddIn @@ -102,6 +106,8 @@ namespace ICSharpCode.ILSpy.AddIn
public static byte[] HexStringToBytes(string hex)
{
if (hex == null)
throw new ArgumentNullException(nameof(hex));
var result = new byte[hex.Length / 2];
for (int i = 0; i < hex.Length / 2; i++) {
result[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);

2
ILSpy.AddIn/license.txt

@ -3,7 +3,7 @@ The following MIT license applies to ILSpy, NRefactory and ICSharpCode.Decompile @@ -3,7 +3,7 @@ The following MIT license applies to ILSpy, NRefactory and ICSharpCode.Decompile
MIT license:
Copyright (c) 2011-2014 AlphaSierraPapa for the SharpDevelop team
Copyright (c) 2011-2016 AlphaSierraPapa for the SharpDevelop team
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

6
ILSpy.AddIn/source.extension.vsixmanifest

@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
<Identifier Id="a9120dbe-164a-4891-842f-fb7829273838">
<Name>ILSpy</Name>
<Author>IC#Code</Author>
<Version>1.2</Version>
<Version>1.5</Version>
<Description xml:space="preserve">Integrates the ILSpy decompiler into Visual Studio.</Description>
<Icon>ILSpy-Large.ico</Icon>
<License>license.txt</License>
@ -24,6 +24,10 @@ @@ -24,6 +24,10 @@
<VisualStudio Version="14.0">
<Edition>Pro</Edition>
</VisualStudio>
<VisualStudio Version="15.0">
<Edition>Pro</Edition>
<Edition>Community</Edition>
</VisualStudio>
</SupportedProducts>
</Identifier>
<Content>

19
ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs

@ -7,6 +7,10 @@ using System.ComponentModel.Composition; @@ -7,6 +7,10 @@ using System.ComponentModel.Composition;
using System.IO;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy;
using System.Resources;
using System.Collections;
using System.Linq;
namespace ILSpy.BamlDecompiler
{
@ -26,4 +30,19 @@ namespace ILSpy.BamlDecompiler @@ -26,4 +30,19 @@ namespace ILSpy.BamlDecompiler
return null;
}
}
[Export(typeof(IResourceFileHandler))]
public sealed class BamlResourceFileHandler : IResourceFileHandler
{
public string EntryType => "Page";
public bool CanHandle(string name, DecompilationOptions options) => name.EndsWith(".baml", StringComparison.OrdinalIgnoreCase);
public string WriteResourceToFile(LoadedAssembly assembly, string fileName, Stream stream, DecompilationOptions options)
{
var document = BamlResourceEntryNode.LoadIntoDocument(assembly.GetAssemblyResolver(), assembly.AssemblyDefinition, stream);
fileName = Path.ChangeExtension(fileName, ".xaml");
document.Save(Path.Combine(options.SaveAsProjectDirectory, fileName));
return fileName;
}
}
}

16
ILSpy.BamlDecompiler/ILSpy.BamlDecompiler.csproj

@ -117,22 +117,24 @@ @@ -117,22 +117,24 @@
</ItemGroup>
<ItemGroup />
<ItemGroup>
<ProjectReference Include="..\cecil\Mono.Cecil.csproj">
<Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project>
<Name>Mono.Cecil</Name>
</ProjectReference>
<ProjectReference Include="..\ICSharpCode.Decompiler\ICSharpCode.Decompiler.csproj">
<Project>{984CC812-9470-4A13-AFF9-CC44068D666C}</Project>
<Project>{984cc812-9470-4a13-aff9-cc44068d666c}</Project>
<Name>ICSharpCode.Decompiler</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\ILSpy\ILSpy.csproj">
<Project>{1E85EFF9-E370-4683-83E4-8A3D063FF791}</Project>
<Project>{1e85eff9-e370-4683-83e4-8a3d063ff791}</Project>
<Name>ILSpy</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\cecil\Mono.Cecil.csproj">
<Project>{d68133bd-1e63-496e-9ede-4fbdbf77b486}</Project>
<Name>Mono.Cecil</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\SharpTreeView\ICSharpCode.TreeView.csproj">
<Project>{DDE2A481-8271-4EAC-A330-8FA6A38D13D1}</Project>
<Project>{dde2a481-8271-4eac-a330-8fa6a38d13d1}</Project>
<Name>ICSharpCode.TreeView</Name>
<Private>False</Private>
</ProjectReference>

4
ILSpy.BamlDecompiler/Ricciolo.StylesExplorer.MarkupReflection/XmlBamlReader.cs

@ -488,6 +488,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -488,6 +488,9 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
case BamlRecordType.PresentationOptionsAttribute:
this.ReadPresentationOptionsAttribute();
break;
case BamlRecordType.TypeSerializerInfo:
this.ReadTypeInfo();
break;
default:
throw new NotImplementedException("UnsupportedNode: " + currentType);
}
@ -526,6 +529,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection @@ -526,6 +529,7 @@ namespace Ricciolo.StylesExplorer.MarkupReflection
case BamlRecordType.TypeInfo:
case BamlRecordType.AttributeInfo:
case BamlRecordType.StringInfo:
case BamlRecordType.TypeSerializerInfo:
bytesToSkip = reader.ReadCompressedInt32();
break;
}

8
ILSpy.BamlDecompiler/Tests/ILSpy.BamlDecompiler.Tests.csproj

@ -101,19 +101,19 @@ @@ -101,19 +101,19 @@
<Name>Mono.Cecil</Name>
</ProjectReference>
<ProjectReference Include="..\..\ICSharpCode.Decompiler\Tests\ICSharpCode.Decompiler.Tests.csproj">
<Project>{FEC0DA52-C4A6-4710-BE36-B484A20C5E22}</Project>
<Project>{fec0da52-c4a6-4710-be36-b484a20c5e22}</Project>
<Name>ICSharpCode.Decompiler.Tests</Name>
</ProjectReference>
<ProjectReference Include="..\..\ILSpy\ILSpy.csproj">
<Project>{1E85EFF9-E370-4683-83E4-8A3D063FF791}</Project>
<Project>{1e85eff9-e370-4683-83e4-8a3d063ff791}</Project>
<Name>ILSpy</Name>
</ProjectReference>
<ProjectReference Include="..\..\SharpTreeView\ICSharpCode.TreeView.csproj">
<Project>{DDE2A481-8271-4EAC-A330-8FA6A38D13D1}</Project>
<Project>{dde2a481-8271-4eac-a330-8fa6a38d13d1}</Project>
<Name>ICSharpCode.TreeView</Name>
</ProjectReference>
<ProjectReference Include="..\ILSpy.BamlDecompiler.csproj">
<Project>{A6BAD2BA-76BA-461C-8B6D-418607591247}</Project>
<Project>{a6bad2ba-76ba-461c-8b6d-418607591247}</Project>
<Name>ILSpy.BamlDecompiler</Name>
</ProjectReference>
</ItemGroup>

1
ILSpy.BamlDecompiler/Tests/TestRunner.cs

@ -39,6 +39,7 @@ namespace ILSpy.BamlDecompiler.Tests @@ -39,6 +39,7 @@ namespace ILSpy.BamlDecompiler.Tests
}
[Test]
[Ignore("Broken on AppVeyor CI (extra x:ConnectionId attribute)")]
public void SimpleNames()
{
RunTest("cases/simplenames");

41
ILSpy/AboutPage.cs

@ -289,20 +289,7 @@ namespace ICSharpCode.ILSpy @@ -289,20 +289,7 @@ namespace ICSharpCode.ILSpy
|| s.LastSuccessfulUpdateCheck < DateTime.UtcNow.AddDays(-7)
|| s.LastSuccessfulUpdateCheck > DateTime.UtcNow)
{
GetLatestVersionAsync().ContinueWith(
delegate (Task<AvailableVersionInfo> task) {
try {
s.LastSuccessfulUpdateCheck = DateTime.UtcNow;
AvailableVersionInfo v = task.Result;
if (v.Version > currentVersion)
tcs.SetResult(v.DownloadUrl);
else
tcs.SetResult(null);
} catch (AggregateException) {
// ignore errors getting the version info
tcs.SetResult(null);
}
});
CheckForUpdateInternal(tcs, s);
} else {
tcs.SetResult(null);
}
@ -311,6 +298,32 @@ namespace ICSharpCode.ILSpy @@ -311,6 +298,32 @@ namespace ICSharpCode.ILSpy
}
return tcs.Task;
}
public static Task<string> CheckForUpdatesAsync(ILSpySettings spySettings)
{
var tcs = new TaskCompletionSource<string>();
UpdateSettings s = new UpdateSettings(spySettings);
CheckForUpdateInternal(tcs, s);
return tcs.Task;
}
static void CheckForUpdateInternal(TaskCompletionSource<string> tcs, UpdateSettings s)
{
GetLatestVersionAsync().ContinueWith(
delegate (Task<AvailableVersionInfo> task) {
try {
s.LastSuccessfulUpdateCheck = DateTime.UtcNow;
AvailableVersionInfo v = task.Result;
if (v.Version > currentVersion)
tcs.SetResult(v.DownloadUrl);
else
tcs.SetResult(null);
} catch (AggregateException) {
// ignore errors getting the version info
tcs.SetResult(null);
}
});
}
}
/// <summary>

22
ILSpy/AssemblyList.cs

@ -178,8 +178,26 @@ namespace ICSharpCode.ILSpy @@ -178,8 +178,26 @@ namespace ICSharpCode.ILSpy
var index = this.assemblies.IndexOf(target);
var newAsm = new LoadedAssembly(this, file, stream);
newAsm.IsAutoLoaded = target.IsAutoLoaded;
lock (assemblies)
{
lock (assemblies) {
this.assemblies.Remove(target);
this.assemblies.Insert(index, newAsm);
}
return newAsm;
}
public LoadedAssembly ReloadAssembly(string file)
{
App.Current.Dispatcher.VerifyAccess();
file = Path.GetFullPath(file);
var target = this.assemblies.FirstOrDefault(asm => file.Equals(asm.FileName, StringComparison.OrdinalIgnoreCase));
if (target == null)
return null;
var index = this.assemblies.IndexOf(target);
var newAsm = new LoadedAssembly(this, file);
newAsm.IsAutoLoaded = target.IsAutoLoaded;
lock (assemblies) {
this.assemblies.Remove(target);
this.assemblies.Insert(index, newAsm);
}

31
ILSpy/Commands/CheckForUpdatesCommand.cs

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.ILSpy
{
[ExportMainMenuCommand(Menu = "_Help", Header = "_Check for Updates", MenuOrder = 5000)]
sealed class CheckForUpdatesCommand : SimpleCommand
{
public override void Execute(object parameter)
{
MainWindow.Instance.ShowMessageIfUpdatesAvailableAsync(ILSpySettings.Load(), forceCheck: true);
}
}
}

2
ILSpy/Commands/OpenCommand.cs

@ -22,7 +22,7 @@ using System.Windows.Input; @@ -22,7 +22,7 @@ using System.Windows.Input;
namespace ICSharpCode.ILSpy
{
[ExportToolbarCommand(ToolTip = "Open", ToolbarIcon = "Images/Open.png", ToolbarCategory = "Open", ToolbarOrder = 0)]
[ExportMainMenuCommand(Menu = "_File", MenuIcon = "Images/Open.png", MenuCategory = "Open", MenuOrder = 0)]
[ExportMainMenuCommand(Menu = "_File", Header = "_Open...", MenuIcon = "Images/Open.png", MenuCategory = "Open", MenuOrder = 0)]
sealed class OpenCommand : CommandWrapper
{
public OpenCommand()

2
ILSpy/Commands/OpenFromGacCommand.cs

@ -20,7 +20,7 @@ using System; @@ -20,7 +20,7 @@ using System;
namespace ICSharpCode.ILSpy
{
[ExportMainMenuCommand(Menu = "_File", Header = "Open from _GAC", MenuIcon = "Images/AssemblyListGAC.png", MenuCategory = "Open", MenuOrder = 1)]
[ExportMainMenuCommand(Menu = "_File", Header = "Open from _GAC...", MenuIcon = "Images/AssemblyListGAC.png", MenuCategory = "Open", MenuOrder = 1)]
sealed class OpenFromGacCommand : SimpleCommand
{
public override void Execute(object parameter)

2
ILSpy/Commands/OpenListCommand.cs

@ -20,7 +20,7 @@ using System; @@ -20,7 +20,7 @@ using System;
namespace ICSharpCode.ILSpy
{
[ExportMainMenuCommand(Menu = "_File", Header = "Open _List", MenuIcon = "Images/AssemblyList.png", MenuCategory = "Open", MenuOrder = 1.7)]
[ExportMainMenuCommand(Menu = "_File", Header = "Open _List...", MenuIcon = "Images/AssemblyList.png", MenuCategory = "Open", MenuOrder = 1.7)]
sealed class OpenListCommand : SimpleCommand
{
public override void Execute(object parameter)

2
ILSpy/Commands/RefreshCommand.cs

@ -22,7 +22,7 @@ using System.Windows.Input; @@ -22,7 +22,7 @@ using System.Windows.Input;
namespace ICSharpCode.ILSpy
{
[ExportToolbarCommand(ToolTip = "Reload all assemblies", ToolbarIcon = "Images/Refresh.png", ToolbarCategory = "Open", ToolbarOrder = 2)]
[ExportMainMenuCommand(Menu = "_File", Header = "Reload", MenuIcon = "Images/Refresh.png", MenuCategory = "Open", MenuOrder = 2)]
[ExportMainMenuCommand(Menu = "_File", Header = "_Reload", MenuIcon = "Images/Refresh.png", MenuCategory = "Open", MenuOrder = 2)]
sealed class RefreshCommand : CommandWrapper
{
public RefreshCommand()

39
ILSpy/Commands/SortAssemblyListCommand.cs

@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace ICSharpCode.ILSpy
{
[ExportMainMenuCommand(Menu = "_View", Header = "Sort assembly list by name", MenuIcon = "Images/Sort.png", MenuCategory = "View")]
[ExportToolbarCommand(ToolTip = "Sort assembly list by name", ToolbarIcon = "Images/Sort.png", ToolbarCategory = "View")]
class SortAssemblyListCommand : SimpleCommand, IComparer<LoadedAssembly>
{
public override void Execute(object parameter)
{
using (MainWindow.Instance.treeView.LockUpdates())
MainWindow.Instance.CurrentAssemblyList.Sort(this);
}
int IComparer<LoadedAssembly>.Compare(LoadedAssembly x, LoadedAssembly y)
{
return string.Compare(x.ShortName, y.ShortName, StringComparison.CurrentCulture);
}
}
}

23
ILSpy/ILSpy.csproj

@ -123,12 +123,14 @@ @@ -123,12 +123,14 @@
<Compile Include="AssemblyListManager.cs" />
<Compile Include="AvalonEdit\ITextMarker.cs" />
<Compile Include="AvalonEdit\TextMarkerService.cs" />
<Compile Include="Commands\CheckForUpdatesCommand.cs" />
<Compile Include="Commands\BrowseBackCommand.cs" />
<Compile Include="Commands\BrowseForwardCommand.cs" />
<Compile Include="CommandLineArguments.cs" />
<Compile Include="Commands\ExitCommand.cs" />
<Compile Include="Commands\CommandWrapper.cs" />
<Compile Include="Commands\OpenListCommand.cs" />
<Compile Include="Commands\SortAssemblyListCommand.cs" />
<Compile Include="Controls\MarkupExtensions.cs" />
<Compile Include="Controls\ResourceObjectTable.xaml.cs">
<DependentUpon>ResourceObjectTable.xaml</DependentUpon>
@ -159,6 +161,7 @@ @@ -159,6 +161,7 @@
<Compile Include="ISmartTextOutput.cs" />
<Compile Include="Images\Images.cs" />
<Compile Include="Languages\ILLanguage.cs" />
<Compile Include="Languages\IResourceFileHandler.cs" />
<Compile Include="Languages\Language.cs" />
<Compile Include="Languages\Languages.cs" />
<Compile Include="LoadedAssembly.cs" />
@ -389,24 +392,24 @@ @@ -389,24 +392,24 @@
<Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project>
<Name>Mono.Cecil</Name>
</ProjectReference>
<ProjectReference Include="..\ICSharpCode.Decompiler\ICSharpCode.Decompiler.csproj">
<Project>{984CC812-9470-4A13-AFF9-CC44068D666C}</Project>
<Name>ICSharpCode.Decompiler</Name>
</ProjectReference>
<ProjectReference Include="..\cecil\symbols\pdb\Mono.Cecil.Pdb.csproj">
<Project>{63E6915C-7EA4-4D76-AB28-0D7191EEA626}</Project>
<Project>{63e6915c-7ea4-4d76-ab28-0d7191eea626}</Project>
<Name>Mono.Cecil.Pdb</Name>
</ProjectReference>
<ProjectReference Include="..\ICSharpCode.Decompiler\ICSharpCode.Decompiler.csproj">
<Project>{984cc812-9470-4a13-aff9-cc44068d666c}</Project>
<Name>ICSharpCode.Decompiler</Name>
</ProjectReference>
<ProjectReference Include="..\NRefactory\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory.CSharp.csproj">
<Project>{53DCA265-3C3C-42F9-B647-F72BA678122B}</Project>
<Project>{53dca265-3c3c-42f9-b647-f72ba678122b}</Project>
<Name>ICSharpCode.NRefactory.CSharp</Name>
</ProjectReference>
<ProjectReference Include="..\NRefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">
<Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project>
<Project>{3b2a5653-ec97-4001-bb9b-d90f1af2c371}</Project>
<Name>ICSharpCode.NRefactory</Name>
</ProjectReference>
<ProjectReference Include="..\SharpTreeView\ICSharpCode.TreeView.csproj">
<Project>{DDE2A481-8271-4EAC-A330-8FA6A38D13D1}</Project>
<Project>{dde2a481-8271-4eac-a330-8fa6a38d13d1}</Project>
<Name>ICSharpCode.TreeView</Name>
</ProjectReference>
</ItemGroup>
@ -416,6 +419,8 @@ @@ -416,6 +419,8 @@
<Resource Include="Images\ResourceXsd.png" />
<Resource Include="Images\ResourceXslt.png" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<Resource Include="Images\Sort.png" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
</Project>

3
ILSpy/ILSpySettings.cs

@ -115,6 +115,9 @@ namespace ICSharpCode.ILSpy @@ -115,6 +115,9 @@ namespace ICSharpCode.ILSpy
static string GetConfigFile()
{
string localPath = Path.Combine(Path.GetDirectoryName(typeof(MainWindow).Assembly.Location), "ILSpy.xml");
if (File.Exists(localPath))
return localPath;
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ICSharpCode\\ILSpy.xml");
}

BIN
ILSpy/Images/Sort.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 380 B

82
ILSpy/Languages/CSharpLanguage.cs

@ -17,12 +17,10 @@ @@ -17,12 +17,10 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
using System.Resources;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml;
@ -536,85 +534,7 @@ namespace ICSharpCode.ILSpy @@ -536,85 +534,7 @@ namespace ICSharpCode.ILSpy
return files.Select(f => Tuple.Create("Compile", f.Key)).Concat(WriteAssemblyInfo(ts, options, directories));
}
#endregion
#region WriteResourceFilesInProject
IEnumerable<Tuple<string, string>> WriteResourceFilesInProject(LoadedAssembly assembly, DecompilationOptions options, HashSet<string> directories)
{
//AppDomain bamlDecompilerAppDomain = null;
//try {
foreach (EmbeddedResource r in assembly.ModuleDefinition.Resources.OfType<EmbeddedResource>()) {
string fileName;
Stream s = r.GetResourceStream();
s.Position = 0;
if (r.Name.EndsWith(".g.resources", StringComparison.OrdinalIgnoreCase)) {
IEnumerable<DictionaryEntry> rs = null;
try {
rs = new ResourceSet(s).Cast<DictionaryEntry>();
}
catch (ArgumentException) {
}
if (rs != null && rs.All(e => e.Value is Stream)) {
foreach (var pair in rs) {
fileName = Path.Combine(((string)pair.Key).Split('/').Select(p => TextView.DecompilerTextView.CleanUpName(p)).ToArray());
string dirName = Path.GetDirectoryName(fileName);
if (!string.IsNullOrEmpty(dirName) && directories.Add(dirName)) {
Directory.CreateDirectory(Path.Combine(options.SaveAsProjectDirectory, dirName));
}
Stream entryStream = (Stream)pair.Value;
entryStream.Position = 0;
if (fileName.EndsWith(".baml", StringComparison.OrdinalIgnoreCase)) {
// MemoryStream ms = new MemoryStream();
// entryStream.CopyTo(ms);
// TODO implement extension point
// var decompiler = Baml.BamlResourceEntryNode.CreateBamlDecompilerInAppDomain(ref bamlDecompilerAppDomain, assembly.FileName);
// string xaml = null;
// try {
// xaml = decompiler.DecompileBaml(ms, assembly.FileName, new ConnectMethodDecompiler(assembly), new AssemblyResolver(assembly));
// }
// catch (XamlXmlWriterException) { } // ignore XAML writer exceptions
// if (xaml != null) {
// File.WriteAllText(Path.Combine(options.SaveAsProjectDirectory, Path.ChangeExtension(fileName, ".xaml")), xaml);
// yield return Tuple.Create("Page", Path.ChangeExtension(fileName, ".xaml"));
// continue;
// }
}
using (FileStream fs = new FileStream(Path.Combine(options.SaveAsProjectDirectory, fileName), FileMode.Create, FileAccess.Write)) {
entryStream.CopyTo(fs);
}
yield return Tuple.Create("Resource", fileName);
}
continue;
}
}
fileName = GetFileNameForResource(r.Name, directories);
using (FileStream fs = new FileStream(Path.Combine(options.SaveAsProjectDirectory, fileName), FileMode.Create, FileAccess.Write)) {
s.CopyTo(fs);
}
yield return Tuple.Create("EmbeddedResource", fileName);
}
//}
//finally {
// if (bamlDecompilerAppDomain != null)
// AppDomain.Unload(bamlDecompilerAppDomain);
//}
}
string GetFileNameForResource(string fullName, HashSet<string> directories)
{
string[] splitName = fullName.Split('.');
string fileName = TextView.DecompilerTextView.CleanUpName(fullName);
for (int i = splitName.Length - 1; i > 0; i--) {
string ns = string.Join(".", splitName, 0, i);
if (directories.Contains(ns)) {
string name = string.Join(".", splitName, i, splitName.Length - i);
fileName = Path.Combine(ns, TextView.DecompilerTextView.CleanUpName(name));
break;
}
}
return fileName;
}
#endregion
/*
/*
AstBuilder CreateAstBuilder(DecompilationOptions options, ModuleDefinition currentModule = null, TypeDefinition currentType = null, bool isSingleMember = false)
{
if (currentModule == null)

30
ILSpy/Languages/IResourceFileHandler.cs

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.IO;
namespace ICSharpCode.ILSpy
{
public interface IResourceFileHandler
{
string EntryType { get; }
bool CanHandle(string name, DecompilationOptions options);
string WriteResourceToFile(LoadedAssembly assembly, string fileName, Stream stream, DecompilationOptions options);
}
}

89
ILSpy/Languages/Language.cs

@ -17,7 +17,11 @@ @@ -17,7 +17,11 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Resources;
using ICSharpCode.Decompiler;
using Mono.Cecil;
@ -162,5 +166,90 @@ namespace ICSharpCode.ILSpy @@ -162,5 +166,90 @@ namespace ICSharpCode.ILSpy
{
return member;
}
#region WriteResourceFilesInProject
protected virtual IEnumerable<Tuple<string, string>> WriteResourceFilesInProject(LoadedAssembly assembly, DecompilationOptions options, HashSet<string> directories)
{
foreach (EmbeddedResource r in assembly.ModuleDefinition.Resources.OfType<EmbeddedResource>()) {
Stream stream = r.GetResourceStream();
stream.Position = 0;
IEnumerable<DictionaryEntry> entries;
if (r.Name.EndsWith(".resources", StringComparison.OrdinalIgnoreCase)) {
if (GetEntries(stream, out entries) && entries.All(e => e.Value is Stream)) {
foreach (var pair in entries) {
string fileName = Path.Combine(((string)pair.Key).Split('/').Select(p => TextView.DecompilerTextView.CleanUpName(p)).ToArray());
string dirName = Path.GetDirectoryName(fileName);
if (!string.IsNullOrEmpty(dirName) && directories.Add(dirName)) {
Directory.CreateDirectory(Path.Combine(options.SaveAsProjectDirectory, dirName));
}
Stream entryStream = (Stream)pair.Value;
bool handled = false;
foreach (var handler in App.CompositionContainer.GetExportedValues<IResourceFileHandler>()) {
if (handler.CanHandle(fileName, options)) {
handled = true;
entryStream.Position = 0;
yield return Tuple.Create(handler.EntryType, handler.WriteResourceToFile(assembly, fileName, entryStream, options));
break;
}
}
if (!handled) {
using (FileStream fs = new FileStream(Path.Combine(options.SaveAsProjectDirectory, fileName), FileMode.Create, FileAccess.Write)) {
entryStream.Position = 0;
entryStream.CopyTo(fs);
}
yield return Tuple.Create("EmbeddedResource", fileName);
}
}
} else {
stream.Position = 0;
string fileName = GetFileNameForResource(Path.ChangeExtension(r.Name, ".resx"), directories);
using (ResourceReader reader = new ResourceReader(stream))
using (FileStream fs = new FileStream(Path.Combine(options.SaveAsProjectDirectory, fileName), FileMode.Create, FileAccess.Write))
using (ResXResourceWriter writer = new ResXResourceWriter(fs)) {
foreach (DictionaryEntry entry in reader) {
writer.AddResource((string)entry.Key, entry.Value);
}
}
yield return Tuple.Create("EmbeddedResource", fileName);
}
} else {
string fileName = GetFileNameForResource(r.Name, directories);
using (FileStream fs = new FileStream(Path.Combine(options.SaveAsProjectDirectory, fileName), FileMode.Create, FileAccess.Write)) {
stream.Position = 0;
stream.CopyTo(fs);
}
yield return Tuple.Create("EmbeddedResource", fileName);
}
}
}
string GetFileNameForResource(string fullName, HashSet<string> directories)
{
string[] splitName = fullName.Split('.');
string fileName = TextView.DecompilerTextView.CleanUpName(fullName);
for (int i = splitName.Length - 1; i > 0; i--) {
string ns = string.Join(".", splitName, 0, i);
if (directories.Contains(ns)) {
string name = string.Join(".", splitName, i, splitName.Length - i);
fileName = Path.Combine(ns, TextView.DecompilerTextView.CleanUpName(name));
break;
}
}
return fileName;
}
bool GetEntries(Stream stream, out IEnumerable<DictionaryEntry> entries)
{
try {
entries = new ResourceSet(stream).Cast<DictionaryEntry>();
return true;
} catch (ArgumentException) {
entries = null;
return false;
}
}
#endregion
}
}

8
ILSpy/MainWindow.xaml

@ -141,12 +141,12 @@ @@ -141,12 +141,12 @@
<RowDefinition Height="0" />
<RowDefinition Height="0" Name="bottomPaneRow" />
</Grid.RowDefinitions>
<Border BorderBrush="Black" BorderThickness="1" Name="updateAvailablePanel" Visibility="Collapsed">
<Border BorderBrush="Black" BorderThickness="1" Name="updatePanel" Visibility="Collapsed">
<DockPanel>
<Button DockPanel.Dock="Right" Click="updateAvailablePanelCloseButtonClick" MinWidth="0">X</Button>
<Button DockPanel.Dock="Right" Click="updatePanelCloseButtonClick" MinWidth="0">X</Button>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="4,0" VerticalAlignment="Center">A new ILSpy version is available.</TextBlock>
<Button Click="downloadUpdateButtonClick">Download</Button>
<TextBlock Name="updatePanelMessage" Margin="4,0" VerticalAlignment="Center">A new ILSpy version is available.</TextBlock>
<Button Name="downloadOrCheckUpdateButton" Click="downloadOrCheckUpdateButtonClick">Download</Button>
</StackPanel>
</DockPanel>
</Border>

72
ILSpy/MainWindow.xaml.cs

@ -257,7 +257,15 @@ namespace ICSharpCode.ILSpy @@ -257,7 +257,15 @@ namespace ICSharpCode.ILSpy
void HandleCommandLineArgumentsAfterShowList(CommandLineArguments args)
{
if (args.NavigateTo != null) {
// if a SaveDirectory is given, do not start a second concurrent decompilation
// by executing JumpoToReference (leads to https://github.com/icsharpcode/ILSpy/issues/710)
if (!string.IsNullOrEmpty(args.SaveDirectory)) {
foreach (var x in commandLineLoadedAssemblies) {
x.ContinueWhenLoaded((Task<ModuleDefinition> moduleTask) => {
OnExportAssembly(moduleTask, args.SaveDirectory);
}, TaskScheduler.FromCurrentSynchronizationContext());
}
} else if (args.NavigateTo != null) {
bool found = false;
if (args.NavigateTo.StartsWith("N:", StringComparison.Ordinal)) {
string namespaceName = args.NavigateTo.Substring(2);
@ -300,13 +308,6 @@ namespace ICSharpCode.ILSpy @@ -300,13 +308,6 @@ namespace ICSharpCode.ILSpy
SearchPane.Instance.SearchTerm = args.Search;
SearchPane.Instance.Show();
}
if (!string.IsNullOrEmpty(args.SaveDirectory)) {
foreach (var x in commandLineLoadedAssemblies) {
x.ContinueWhenLoaded( (Task<ModuleDefinition> moduleTask) => {
OnExportAssembly(moduleTask, args.SaveDirectory);
}, TaskScheduler.FromCurrentSynchronizationContext());
}
}
commandLineLoadedAssemblies.Clear(); // clear references once we don't need them anymore
}
@ -398,27 +399,44 @@ namespace ICSharpCode.ILSpy @@ -398,27 +399,44 @@ namespace ICSharpCode.ILSpy
#region Update Check
string updateAvailableDownloadUrl;
void ShowMessageIfUpdatesAvailableAsync(ILSpySettings spySettings)
public void ShowMessageIfUpdatesAvailableAsync(ILSpySettings spySettings, bool forceCheck = false)
{
AboutPage.CheckForUpdatesIfEnabledAsync(spySettings).ContinueWith(
delegate (Task<string> task) {
if (task.Result != null) {
updateAvailableDownloadUrl = task.Result;
updateAvailablePanel.Visibility = Visibility.Visible;
}
},
TaskScheduler.FromCurrentSynchronizationContext()
);
Task<string> result;
if (forceCheck) {
result = AboutPage.CheckForUpdatesAsync(spySettings);
} else {
result = AboutPage.CheckForUpdatesIfEnabledAsync(spySettings);
}
result.ContinueWith(task => AdjustUpdateUIAfterCheck(task, forceCheck), TaskScheduler.FromCurrentSynchronizationContext());
}
void updateAvailablePanelCloseButtonClick(object sender, RoutedEventArgs e)
void updatePanelCloseButtonClick(object sender, RoutedEventArgs e)
{
updateAvailablePanel.Visibility = Visibility.Collapsed;
updatePanel.Visibility = Visibility.Collapsed;
}
void downloadUpdateButtonClick(object sender, RoutedEventArgs e)
void downloadOrCheckUpdateButtonClick(object sender, RoutedEventArgs e)
{
Process.Start(updateAvailableDownloadUrl);
if (updateAvailableDownloadUrl != null) {
Process.Start(updateAvailableDownloadUrl);
} else {
updatePanel.Visibility = Visibility.Collapsed;
AboutPage.CheckForUpdatesAsync(spySettings ?? ILSpySettings.Load())
.ContinueWith(task => AdjustUpdateUIAfterCheck(task, true), TaskScheduler.FromCurrentSynchronizationContext());
}
}
void AdjustUpdateUIAfterCheck(Task<string> task, bool displayMessage)
{
updateAvailableDownloadUrl = task.Result;
updatePanel.Visibility = displayMessage ? Visibility.Visible : Visibility.Collapsed;
if (task.Result != null) {
updatePanelMessage.Text = "A new ILSpy version is available.";
downloadOrCheckUpdateButton.Content = "Download";
} else {
updatePanelMessage.Text = "No update for ILSpy found.";
downloadOrCheckUpdateButton.Content = "Check again";
}
}
#endregion
@ -527,6 +545,14 @@ namespace ICSharpCode.ILSpy @@ -527,6 +545,14 @@ namespace ICSharpCode.ILSpy
}
}
public void SelectNodes(IEnumerable<SharpTreeNode> nodes)
{
if (nodes.Any() && nodes.All(n => !n.AncestorsAndSelf().Any(a => a.IsHidden))) {
treeView.FocusNode(nodes.First());
treeView.SetSelectedNodes(nodes);
}
}
/// <summary>
/// Retrieves a node using the .ToString() representations of its ancestors.
/// </summary>
@ -555,7 +581,7 @@ namespace ICSharpCode.ILSpy @@ -555,7 +581,7 @@ namespace ICSharpCode.ILSpy
/// <summary>
/// Gets the .ToString() representation of the node's ancestors.
/// </summary>
public string[] GetPathForNode(SharpTreeNode node)
public static string[] GetPathForNode(SharpTreeNode node)
{
if (node == null)
return null;

10
ILSpy/OpenListDialog.xaml.cs

@ -181,11 +181,11 @@ namespace ICSharpCode.ILSpy @@ -181,11 +181,11 @@ namespace ICSharpCode.ILSpy
manager.DeleteList(listView.SelectedItem.ToString());
}
private void listView_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left && listView.SelectedItem != null)
this.DialogResult = true;
}
private void listView_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left && listView.SelectedItem != null)
this.DialogResult = true;
}
}
}

15
ILSpy/Options/DisplaySettings.cs

@ -96,12 +96,27 @@ namespace ICSharpCode.ILSpy.Options @@ -96,12 +96,27 @@ namespace ICSharpCode.ILSpy.Options
}
}
bool enableWordWrap;
public bool EnableWordWrap
{
get { return enableWordWrap; }
set
{
if (enableWordWrap != value) {
enableWordWrap = value;
OnPropertyChanged("EnableWordWrap");
}
}
}
public void CopyValues(DisplaySettings s)
{
this.SelectedFont = s.selectedFont;
this.SelectedFontSize = s.selectedFontSize;
this.ShowLineNumbers = s.showLineNumbers;
this.ShowMetadataTokens = s.showMetadataTokens;
this.EnableWordWrap = s.enableWordWrap;
}
}
}

1
ILSpy/Options/DisplaySettingsPanel.xaml

@ -61,6 +61,7 @@ @@ -61,6 +61,7 @@
<StackPanel Margin="3">
<CheckBox IsChecked="{Binding ShowLineNumbers}">Show line numbers</CheckBox>
<CheckBox IsChecked="{Binding ShowMetadataTokens}">Show metadata tokens</CheckBox>
<CheckBox IsChecked="{Binding EnableWordWrap}">Enable word wrap</CheckBox>
</StackPanel>
</GroupBox>
</Grid>

2
ILSpy/Options/DisplaySettingsPanel.xaml.cs

@ -101,6 +101,7 @@ namespace ICSharpCode.ILSpy.Options @@ -101,6 +101,7 @@ namespace ICSharpCode.ILSpy.Options
s.SelectedFontSize = (double?)e.Attribute("FontSize") ?? 10.0 * 4 / 3;
s.ShowLineNumbers = (bool?)e.Attribute("ShowLineNumbers") ?? false;
s.ShowMetadataTokens = (bool?) e.Attribute("ShowMetadataTokens") ?? false;
s.EnableWordWrap = (bool?)e.Attribute("EnableWordWrap") ?? false;
return s;
}
@ -116,6 +117,7 @@ namespace ICSharpCode.ILSpy.Options @@ -116,6 +117,7 @@ namespace ICSharpCode.ILSpy.Options
section.SetAttributeValue("FontSize", s.SelectedFontSize);
section.SetAttributeValue("ShowLineNumbers", s.ShowLineNumbers);
section.SetAttributeValue("ShowMetadataTokens", s.ShowMetadataTokens);
section.SetAttributeValue("EnableWordWrap", s.EnableWordWrap);
XElement existingElement = root.Element("DisplaySettings");
if (existingElement != null)

2
ILSpy/Options/OptionsDialog.xaml.cs

@ -89,7 +89,7 @@ namespace ICSharpCode.ILSpy.Options @@ -89,7 +89,7 @@ namespace ICSharpCode.ILSpy.Options
public int Order { get; set; }
}
[ExportMainMenuCommand(Menu = "_View", Header = "_Options", MenuCategory = "Options", MenuOrder = 999)]
[ExportMainMenuCommand(Menu = "_View", Header = "_Options...", MenuCategory = "Options", MenuOrder = 999)]
sealed class ShowOptionsCommand : SimpleCommand
{
public override void Execute(object parameter)

2
ILSpy/Properties/AssemblyInfo.template.cs

@ -15,7 +15,7 @@ using System.Runtime.InteropServices; @@ -15,7 +15,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyDescription(".NET assembly inspector and decompiler")]
[assembly: AssemblyCompany("ic#code")]
[assembly: AssemblyProduct("ILSpy")]
[assembly: AssemblyCopyright("Copyright 2011-2015 AlphaSierraPapa for the SharpDevelop Team")]
[assembly: AssemblyCopyright("Copyright 2011-2016 AlphaSierraPapa for the SharpDevelop Team")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

12
ILSpy/Properties/WPFAssemblyInfo.cs

@ -18,10 +18,10 @@ using System.Windows; @@ -18,10 +18,10 @@ using System.Windows;
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]

6
ILSpy/Properties/app.config.template

@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="ICSharpCode.AvalonEdit" publicKeyToken="9cc39be672370310" culture="neutral"/>
<bindingRedirect oldVersion="4.1.0.0-99.9.9.9" newVersion="5.0.1.0"/>
<bindingRedirect oldVersion="4.1.0.0-99.9.9.9" newVersion="5.0.3.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="ICSharpCode.NRefactory" publicKeyToken="d4bfe873e7598c49" culture="neutral"/>
@ -37,11 +37,11 @@ @@ -37,11 +37,11 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Mono.Cecil" publicKeyToken="0738eb9f132ed756" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-99.9.9.9" newVersion="0.9.5.0"/>
<bindingRedirect oldVersion="0.0.0.0-99.9.9.9" newVersion="0.9.6.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Mono.Cecil.Pdb" publicKeyToken="0738eb9f132ed756" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-99.9.9.9" newVersion="0.9.5.0"/>
<bindingRedirect oldVersion="0.0.0.0-99.9.9.9" newVersion="0.9.6.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>

48
ILSpy/SearchPane.cs

@ -58,10 +58,15 @@ namespace ICSharpCode.ILSpy @@ -58,10 +58,15 @@ namespace ICSharpCode.ILSpy
private SearchPane()
{
InitializeComponent();
searchModeComboBox.Items.Add(new { Image = Images.Library, Name = "Types and Members" });
searchModeComboBox.Items.Add(new { Image = Images.Class, Name = "Type" });
searchModeComboBox.Items.Add(new { Image = Images.Property, Name = "Member" });
searchModeComboBox.Items.Add(new { Image = Images.Method, Name = "Method" });
searchModeComboBox.Items.Add(new { Image = Images.Field, Name = "Field" });
searchModeComboBox.Items.Add(new { Image = Images.Property, Name = "Property" });
searchModeComboBox.Items.Add(new { Image = Images.Event, Name = "Event" });
searchModeComboBox.Items.Add(new { Image = Images.Literal, Name = "Constant" });
searchModeComboBox.SelectedIndex = (int)SearchMode.Type;
searchModeComboBox.SelectedIndex = (int)SearchMode.TypeAndMember;
ContextMenuProvider.Add(listBox);
MainWindow.Instance.CurrentAssemblyListChanged += MainWindow_Instance_CurrentAssemblyListChanged;
@ -249,23 +254,49 @@ namespace ICSharpCode.ILSpy @@ -249,23 +254,49 @@ namespace ICSharpCode.ILSpy
AbstractSearchStrategy GetSearchStrategy(SearchMode mode, string[] terms)
{
if (terms.Length == 1) {
if (terms[0].StartsWith("t:"))
if (terms[0].StartsWith("tm:", StringComparison.Ordinal))
return new TypeAndMemberSearchStrategy(terms[0].Substring(3));
if (terms[0].StartsWith("t:", StringComparison.Ordinal))
return new TypeSearchStrategy(terms[0].Substring(2));
if (terms[0].StartsWith("m:"))
if (terms[0].StartsWith("m:", StringComparison.Ordinal))
return new MemberSearchStrategy(terms[0].Substring(2));
if (terms[0].StartsWith("c:"))
if (terms[0].StartsWith("md:", StringComparison.Ordinal))
return new MemberSearchStrategy(terms[0].Substring(3), MemberSearchKind.Method);
if (terms[0].StartsWith("f:", StringComparison.Ordinal))
return new MemberSearchStrategy(terms[0].Substring(2), MemberSearchKind.Field);
if (terms[0].StartsWith("p:", StringComparison.Ordinal))
return new MemberSearchStrategy(terms[0].Substring(2), MemberSearchKind.Property);
if (terms[0].StartsWith("e:", StringComparison.Ordinal))
return new MemberSearchStrategy(terms[0].Substring(2), MemberSearchKind.Event);
if (terms[0].StartsWith("c:", StringComparison.Ordinal))
return new LiteralSearchStrategy(terms[0].Substring(2));
}
switch (mode) {
switch (mode)
{
case SearchMode.TypeAndMember:
return new TypeAndMemberSearchStrategy(terms);
case SearchMode.Type:
return new TypeSearchStrategy(terms);
case SearchMode.Member:
return new MemberSearchStrategy(terms);
case SearchMode.Literal:
return new LiteralSearchStrategy(terms);
case SearchMode.Method:
return new MemberSearchStrategy(terms, MemberSearchKind.Method);
case SearchMode.Field:
return new MemberSearchStrategy(terms, MemberSearchKind.Field);
case SearchMode.Property:
return new MemberSearchStrategy(terms, MemberSearchKind.Property);
case SearchMode.Event:
return new MemberSearchStrategy(terms, MemberSearchKind.Event);
}
return null;
@ -293,7 +324,7 @@ namespace ICSharpCode.ILSpy @@ -293,7 +324,7 @@ namespace ICSharpCode.ILSpy
}
}
[ExportMainMenuCommand(Menu = "_View", Header = "_Search", MenuIcon = "Images/Find.png", MenuCategory = "ShowPane", MenuOrder = 100)]
[ExportMainMenuCommand(Menu = "_View", Header = "_Search...", MenuIcon = "Images/Find.png", MenuCategory = "View", MenuOrder = 100)]
[ExportToolbarCommand(ToolTip = "Search (Ctrl+Shift+F or Ctrl+E)", ToolbarIcon = "Images/Find.png", ToolbarCategory = "View", ToolbarOrder = 100)]
sealed class ShowSearchCommand : CommandWrapper
{
@ -308,8 +339,13 @@ namespace ICSharpCode.ILSpy @@ -308,8 +339,13 @@ namespace ICSharpCode.ILSpy
public enum SearchMode
{
TypeAndMember,
Type,
Member,
Method,
Field,
Property,
Event,
Literal
}
}

2
ILSpy/SearchPane.xaml

@ -19,7 +19,7 @@ @@ -19,7 +19,7 @@
Text="{Binding SearchTerm, ElementName=self}" ToolTip="Search" UpdateDelay="0:0:0.1"
WatermarkColor="Gray" WatermarkText="Search for t:TypeName, m:Member or c:Constant; use /reg(ular)?Ex(pressions)?/ or both - t:/Type(Name)?/..." />
<StackPanel Grid.Column="1" Grid.Row="0" Orientation="Horizontal">
<Label Margin="0,-1">Search _for:</Label>
<Label Margin="0,-1" Target="searchModeComboBox">_Search for:</Label>
<ComboBox Width="100" Name="searchModeComboBox" Margin="1"
SelectionChanged="SearchModeComboBox_SelectionChanged">
<ComboBox.ItemTemplate>

106
ILSpy/SearchStrategies.cs

@ -21,7 +21,7 @@ namespace ICSharpCode.ILSpy @@ -21,7 +21,7 @@ namespace ICSharpCode.ILSpy
{
if (terms.Length == 1 && terms[0].Length > 2) {
var search = terms[0];
if (search.StartsWith("/") && search.EndsWith("/") && search.Length > 4)
if (search.StartsWith("/", StringComparison.Ordinal) && search.EndsWith("/", StringComparison.Ordinal) && search.Length > 4)
regex = SafeNewRegex(search.Substring(1, search.Length - 2));
terms[0] = search;
@ -37,8 +37,32 @@ namespace ICSharpCode.ILSpy @@ -37,8 +37,32 @@ namespace ICSharpCode.ILSpy
for (int i = 0; i < searchTerm.Length; ++i) {
// How to handle overlapping matches?
if (text.IndexOf(searchTerm[i], StringComparison.OrdinalIgnoreCase) < 0)
return false;
var term = searchTerm[i];
if (string.IsNullOrEmpty(term)) continue;
switch (term[0])
{
case '+': // must contain
term = term.Substring(1);
goto default;
case '-': // should not contain
if (term.Length > 1 && text.IndexOf(term.Substring(1), StringComparison.OrdinalIgnoreCase) >= 0)
return false;
break;
case '=': // exact match
{
var equalCompareLength = text.IndexOf('`');
if (equalCompareLength == -1)
equalCompareLength = text.Length;
if (term.Length > 1 && String.Compare(term, 1, text, 0, Math.Max(term.Length, equalCompareLength), StringComparison.OrdinalIgnoreCase) != 0)
return false;
}
break;
default:
if (text.IndexOf(term, StringComparison.OrdinalIgnoreCase) < 0)
return false;
break;
}
}
return true;
}
@ -279,31 +303,48 @@ namespace ICSharpCode.ILSpy @@ -279,31 +303,48 @@ namespace ICSharpCode.ILSpy
}
}
enum MemberSearchKind
{
All,
Field,
Property,
Event,
Method
}
class MemberSearchStrategy : AbstractSearchStrategy
{
public MemberSearchStrategy(params string[] terms)
MemberSearchKind searchKind;
public MemberSearchStrategy(string term, MemberSearchKind searchKind = MemberSearchKind.All)
: this(new[] { term }, searchKind)
{
}
public MemberSearchStrategy(string[] terms, MemberSearchKind searchKind = MemberSearchKind.All)
: base(terms)
{
this.searchKind = searchKind;
}
protected override bool IsMatch(FieldDefinition field)
{
return IsMatch(field.Name);
return (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Field) && IsMatch(field.Name);
}
protected override bool IsMatch(PropertyDefinition property)
{
return IsMatch(property.Name);
return (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Property) && IsMatch(property.Name);
}
protected override bool IsMatch(EventDefinition ev)
{
return IsMatch(ev.Name);
return (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Event) && IsMatch(ev.Name);
}
protected override bool IsMatch(MethodDefinition m)
{
return IsMatch(m.Name);
return (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Method) && IsMatch(m.Name);
}
}
@ -332,4 +373,53 @@ namespace ICSharpCode.ILSpy @@ -332,4 +373,53 @@ namespace ICSharpCode.ILSpy
}
}
class TypeAndMemberSearchStrategy : AbstractSearchStrategy
{
public TypeAndMemberSearchStrategy(params string[] terms)
: base(terms)
{
}
public override void Search(TypeDefinition type, Language language, Action<SearchResult> addResult)
{
if (IsMatch(type.Name) || IsMatch(type.FullName))
{
addResult(new SearchResult
{
Member = type,
Image = TypeTreeNode.GetIcon(type),
Name = language.TypeToString(type, includeNamespace: false),
LocationImage = type.DeclaringType != null ? TypeTreeNode.GetIcon(type.DeclaringType) : Images.Namespace,
Location = type.DeclaringType != null ? language.TypeToString(type.DeclaringType, includeNamespace: true) : type.Namespace
});
}
foreach (TypeDefinition nestedType in type.NestedTypes)
{
Search(nestedType, language, addResult);
}
base.Search(type, language, addResult);
}
protected override bool IsMatch(FieldDefinition field)
{
return IsMatch(field.Name);
}
protected override bool IsMatch(PropertyDefinition property)
{
return IsMatch(property.Name);
}
protected override bool IsMatch(EventDefinition ev)
{
return IsMatch(ev.Name);
}
protected override bool IsMatch(MethodDefinition m)
{
return IsMatch(m.Name);
}
}
}

5
ILSpy/TextView/DecompilerTextView.cs

@ -97,6 +97,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -97,6 +97,7 @@ namespace ICSharpCode.ILSpy.TextView
textEditor.TextArea.TextView.MouseDown += TextViewMouseDown;
textEditor.SetBinding(Control.FontFamilyProperty, new Binding { Source = DisplaySettingsPanel.CurrentDisplaySettings, Path = new PropertyPath("SelectedFont") });
textEditor.SetBinding(Control.FontSizeProperty, new Binding { Source = DisplaySettingsPanel.CurrentDisplaySettings, Path = new PropertyPath("SelectedFontSize") });
textEditor.SetBinding(TextEditor.WordWrapProperty, new Binding { Source = DisplaySettingsPanel.CurrentDisplaySettings, Path = new PropertyPath("EnableWordWrap") });
textMarkerService = new TextMarkerService(textEditor.TextArea.TextView);
textEditor.TextArea.TextView.BackgroundRenderers.Add(textMarkerService);
@ -234,6 +235,9 @@ namespace ICSharpCode.ILSpy.TextView @@ -234,6 +235,9 @@ namespace ICSharpCode.ILSpy.TextView
{
if (waitAdorner.Visibility != Visibility.Visible) {
waitAdorner.Visibility = Visibility.Visible;
// Work around a WPF bug by setting IsIndeterminate only while the progress bar is visible.
// https://github.com/icsharpcode/ILSpy/issues/593
progressBar.IsIndeterminate = true;
waitAdorner.BeginAnimation(OpacityProperty, new DoubleAnimation(0, 1, new Duration(TimeSpan.FromSeconds(0.5)), FillBehavior.Stop));
var taskBar = MainWindow.Instance.TaskbarItemInfo;
if (taskBar != null) {
@ -261,6 +265,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -261,6 +265,7 @@ namespace ICSharpCode.ILSpy.TextView
if (currentCancellationTokenSource == myCancellationTokenSource) {
currentCancellationTokenSource = null;
waitAdorner.Visibility = Visibility.Collapsed;
progressBar.IsIndeterminate = false;
var taskBar = MainWindow.Instance.TaskbarItemInfo;
if (taskBar != null) {
taskBar.ProgressState = System.Windows.Shell.TaskbarItemProgressState.None;

2
ILSpy/TextView/DecompilerTextView.xaml

@ -19,7 +19,7 @@ @@ -19,7 +19,7 @@
<Border Name="waitAdorner" Background="#C0FFFFFF" Visibility="Collapsed">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock FontSize="14pt">Decompiling...</TextBlock>
<ProgressBar IsIndeterminate="True" Height="16" Margin="0, 4" />
<ProgressBar Name="progressBar" Height="16" Margin="0, 4" />
<Button Click="cancelButton_Click" HorizontalAlignment="Center">Cancel</Button>
</StackPanel>
</Border>

28
ILSpy/TextView/EditorCommands.cs

@ -16,15 +16,10 @@ @@ -16,15 +16,10 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ICSharpCode.ILSpy.TextView
{
[ExportContextMenuEntryAttribute(Header = "Copy", Category = "Editor")]
internal sealed class CopyContextMenuEntry : IContextMenuEntry
[ExportContextMenuEntry(Header = "Copy", Category = "Editor")]
sealed class CopyContextMenuEntry : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)
{
@ -41,4 +36,23 @@ namespace ICSharpCode.ILSpy.TextView @@ -41,4 +36,23 @@ namespace ICSharpCode.ILSpy.TextView
context.TextView.textEditor.Copy();
}
}
[ExportContextMenuEntry(Header = "Select All", Category = "Editor")]
sealed class SelectAllContextMenuEntry : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)
{
return context.TextView != null;
}
public bool IsEnabled(TextViewContext context)
{
return context.TextView != null;
}
public void Execute(TextViewContext context)
{
context.TextView.textEditor.SelectAll();
}
}
}

6
ILSpy/TreeNodes/Analyzer/RemoveAnalyzeContextMenuEntry.cs

@ -27,19 +27,19 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -27,19 +27,19 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
if (context.TreeView is AnalyzerTreeView && context.SelectedTreeNodes != null && context.SelectedTreeNodes.All(n => n.Parent.IsRoot))
return true;
return false;
return false;
}
public bool IsEnabled(TextViewContext context)
{
return true;
return true;
}
public void Execute(TextViewContext context)
{
if (context.SelectedTreeNodes != null) {
foreach (var node in context.SelectedTreeNodes) {
node.Parent.Children.Remove(node);
node.Parent.Children.Remove(node);
}
}
}

48
ILSpy/TreeNodes/AssemblyListTreeNode.cs

@ -130,34 +130,34 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -130,34 +130,34 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
}
#region Find*Node
#region Find*Node
public ILSpyTreeNode FindResourceNode(Resource resource)
{
if (resource == null)
return null;
foreach (AssemblyTreeNode node in this.Children)
{
if (node.LoadedAssembly.IsLoaded)
{
node.EnsureLazyChildren();
foreach (var item in node.Children.OfType<ResourceListTreeNode>())
{
var founded = item.Children.OfType<ResourceTreeNode>().Where(x => x.Resource == resource).FirstOrDefault();
if (founded != null)
return founded;
public ILSpyTreeNode FindResourceNode(Resource resource)
{
if (resource == null)
return null;
foreach (AssemblyTreeNode node in this.Children)
{
if (node.LoadedAssembly.IsLoaded)
{
node.EnsureLazyChildren();
foreach (var item in node.Children.OfType<ResourceListTreeNode>())
{
var founded = item.Children.OfType<ResourceTreeNode>().Where(x => x.Resource == resource).FirstOrDefault();
if (founded != null)
return founded;
var foundedResEntry = item.Children.OfType<ResourceEntryNode>().Where(x => resource.Name.Equals(x.Text)).FirstOrDefault();
if (foundedResEntry != null)
return foundedResEntry;
}
}
}
return null;
}
var foundedResEntry = item.Children.OfType<ResourceEntryNode>().Where(x => resource.Name.Equals(x.Text)).FirstOrDefault();
if (foundedResEntry != null)
return foundedResEntry;
}
}
}
return null;
}
public AssemblyTreeNode FindAssemblyNode(ModuleDefinition module)
public AssemblyTreeNode FindAssemblyNode(ModuleDefinition module)
{
if (module == null)
return null;

36
ILSpy/TreeNodes/AssemblyTreeNode.cs

@ -318,7 +318,39 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -318,7 +318,39 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
}
[ExportContextMenuEntryAttribute(Header = "_Load Dependencies")]
[ExportContextMenuEntry(Header = "_Reload", Icon = "images/Refresh.png")]
sealed class ReloadAssembly : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)
{
if (context.SelectedTreeNodes == null)
return false;
return context.SelectedTreeNodes.All(n => n is AssemblyTreeNode);
}
public bool IsEnabled(TextViewContext context)
{
return true;
}
public void Execute(TextViewContext context)
{
if (context.SelectedTreeNodes == null)
return;
var paths = new List<string[]>();
using (context.TreeView.LockUpdates()) {
foreach (var node in context.SelectedTreeNodes) {
paths.Add(MainWindow.GetPathForNode(node));
var la = ((AssemblyTreeNode)node).LoadedAssembly;
la.AssemblyList.ReloadAssembly(la.FileName);
}
}
MainWindow.Instance.SelectNodes(paths.Select(p => MainWindow.Instance.FindNodeByPath(p, true)).ToArray());
MainWindow.Instance.RefreshDecompiledView();
}
}
[ExportContextMenuEntry(Header = "_Load Dependencies")]
sealed class LoadDependencies : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)
@ -349,7 +381,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -349,7 +381,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
}
[ExportContextMenuEntryAttribute(Header = "_Add To Main List")]
[ExportContextMenuEntry(Header = "_Add To Main List")]
sealed class AddToMainList : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)

30
ILSpy/TreeNodes/PropertyTreeNode.cs

@ -62,7 +62,35 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -62,7 +62,35 @@ namespace ICSharpCode.ILSpy.TreeNodes
public static object GetText(PropertyDefinition property, Language language, bool? isIndexer = null)
{
return HighlightSearchMatch(language.FormatPropertyName(property, isIndexer), " : " + language.TypeToString(property.PropertyType, false, property));
string name = language.FormatPropertyName(property, isIndexer);
var b = new System.Text.StringBuilder();
if (property.HasParameters)
{
b.Append('(');
for (int i = 0; i < property.Parameters.Count; i++)
{
if (i > 0)
b.Append(", ");
b.Append(language.TypeToString(property.Parameters[i].ParameterType, false, property.Parameters[i]));
}
var method = property.GetMethod ?? property.SetMethod;
if (method.CallingConvention == MethodCallingConvention.VarArg)
{
if (property.HasParameters)
b.Append(", ");
b.Append("...");
}
b.Append(") : ");
}
else
{
b.Append(" : ");
}
b.Append(language.TypeToString(property.PropertyType, false, property));
b.Append(property.MetadataToken.ToSuffixString());
return HighlightSearchMatch(name, b.ToString());
}
public override object Icon

40
ILSpy/VB/ILSpyEnvironmentProvider.cs

@ -37,7 +37,7 @@ namespace ICSharpCode.ILSpy.VB @@ -37,7 +37,7 @@ namespace ICSharpCode.ILSpy.VB
//readonly CecilLoader loader = new CecilLoader();
public string GetTypeNameForAttribute(ICSharpCode.NRefactory.CSharp.Attribute attribute)
public string GetTypeNameForAttribute(NRefactory.CSharp.Attribute attribute)
{
return attribute.Type.Annotations
.OfType<Mono.Cecil.MemberReference>()
@ -62,7 +62,7 @@ namespace ICSharpCode.ILSpy.VB @@ -62,7 +62,7 @@ namespace ICSharpCode.ILSpy.VB
return SpecialType.UnknownType;
}
public TypeKind GetTypeKindForAstType(ICSharpCode.NRefactory.CSharp.AstType type)
public TypeKind GetTypeKindForAstType(NRefactory.CSharp.AstType type)
{
var annotation = type.Annotation<TypeReference>();
if (annotation == null)
@ -83,7 +83,7 @@ namespace ICSharpCode.ILSpy.VB @@ -83,7 +83,7 @@ namespace ICSharpCode.ILSpy.VB
return TypeKind.Unknown;
}
public TypeCode ResolveExpression(ICSharpCode.NRefactory.CSharp.Expression expression)
public TypeCode ResolveExpression(NRefactory.CSharp.Expression expression)
{
var annotation = expression.Annotations.OfType<TypeInformation>().FirstOrDefault();
@ -105,9 +105,9 @@ namespace ICSharpCode.ILSpy.VB @@ -105,9 +105,9 @@ namespace ICSharpCode.ILSpy.VB
return TypeCode.Object;
}
public Nullable<bool> IsReferenceType(ICSharpCode.NRefactory.CSharp.Expression expression)
public bool? IsReferenceType(NRefactory.CSharp.Expression expression)
{
if (expression is ICSharpCode.NRefactory.CSharp.NullReferenceExpression)
if (expression is NRefactory.CSharp.NullReferenceExpression)
return true;
var annotation = expression.Annotations.OfType<TypeInformation>().FirstOrDefault();
@ -128,7 +128,7 @@ namespace ICSharpCode.ILSpy.VB @@ -128,7 +128,7 @@ namespace ICSharpCode.ILSpy.VB
foreach (var type in interfaces) {
var def = type.Annotation<TypeReference>().Resolve();
if (def == null) continue;
foreach (var method in def.Methods.Where(m => !m.Name.StartsWith("get_") && !m.Name.StartsWith("set_"))) {
foreach (var method in def.Methods.Where(m => !m.Name.StartsWith("get_", StringComparison.Ordinal) && !m.Name.StartsWith("set_", StringComparison.Ordinal))) {
yield return new NRefactory.VB.Ast.InterfaceMemberSpecifier((NRefactory.VB.Ast.AstType)type.Clone(), method.Name);
}
@ -143,14 +143,34 @@ namespace ICSharpCode.ILSpy.VB @@ -143,14 +143,34 @@ namespace ICSharpCode.ILSpy.VB
return expression.Annotation<EventDefinition>() != null;
}
public bool IsMethodGroup(ICSharpCode.NRefactory.CSharp.Expression expression)
public bool IsMethodGroup(NRefactory.CSharp.Expression expression)
{
var annotation = expression.Annotation<MethodDefinition>();
if (annotation != null) {
return true;
var methodInfo = expression.Annotation<MethodReference>()?.Resolve();
if (methodInfo != null) {
return !methodInfo.IsGetter && !methodInfo.IsSetter && !methodInfo.IsAddOn && !methodInfo.IsRemoveOn;
}
return false;
}
public NRefactory.CSharp.ParameterDeclaration[] GetParametersForProperty(NRefactory.CSharp.PropertyDeclaration property)
{
var propInfo = property.Annotation<PropertyReference>();
if (propInfo == null)
return new NRefactory.CSharp.ParameterDeclaration[0];
return propInfo.Parameters.Select(p => new NRefactory.CSharp.ParameterDeclaration(AstBuilder.ConvertType(p.ParameterType), p.Name, GetModifiers(p))).ToArray();
}
NRefactory.CSharp.ParameterModifier GetModifiers(ParameterDefinition p)
{
if (p.IsOut && p.IsIn)
return NRefactory.CSharp.ParameterModifier.Ref;
if (p.IsOut)
return NRefactory.CSharp.ParameterModifier.Out;
return NRefactory.CSharp.ParameterModifier.None;
}
}
}

86
ILSpy/VB/VBLanguage.cs

@ -17,24 +17,20 @@ @@ -17,24 +17,20 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
using System.Resources;
using System.Threading.Tasks;
using System.Xml;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Ast.Transforms;
using ICSharpCode.ILSpy.XmlDoc;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using CSharp = ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.VB;
using ICSharpCode.NRefactory.VB.Visitors;
using Mono.Cecil;
using CSharp = ICSharpCode.NRefactory.CSharp;
namespace ICSharpCode.ILSpy.VB
{
@ -320,84 +316,6 @@ namespace ICSharpCode.ILSpy.VB @@ -320,84 +316,6 @@ namespace ICSharpCode.ILSpy.VB
}
#endregion
#region WriteResourceFilesInProject
IEnumerable<Tuple<string, string>> WriteResourceFilesInProject(LoadedAssembly assembly, DecompilationOptions options, HashSet<string> directories)
{
//AppDomain bamlDecompilerAppDomain = null;
//try {
foreach (EmbeddedResource r in assembly.ModuleDefinition.Resources.OfType<EmbeddedResource>()) {
string fileName;
Stream s = r.GetResourceStream();
s.Position = 0;
if (r.Name.EndsWith(".g.resources", StringComparison.OrdinalIgnoreCase)) {
IEnumerable<DictionaryEntry> rs = null;
try {
rs = new ResourceSet(s).Cast<DictionaryEntry>();
}
catch (ArgumentException) {
}
if (rs != null && rs.All(e => e.Value is Stream)) {
foreach (var pair in rs) {
fileName = Path.Combine(((string)pair.Key).Split('/').Select(p => TextView.DecompilerTextView.CleanUpName(p)).ToArray());
string dirName = Path.GetDirectoryName(fileName);
if (!string.IsNullOrEmpty(dirName) && directories.Add(dirName)) {
Directory.CreateDirectory(Path.Combine(options.SaveAsProjectDirectory, dirName));
}
Stream entryStream = (Stream)pair.Value;
entryStream.Position = 0;
if (fileName.EndsWith(".baml", StringComparison.OrdinalIgnoreCase)) {
//MemoryStream ms = new MemoryStream();
//entryStream.CopyTo(ms);
// TODO implement extension point
// var decompiler = Baml.BamlResourceEntryNode.CreateBamlDecompilerInAppDomain(ref bamlDecompilerAppDomain, assembly.FileName);
// string xaml = null;
// try {
// xaml = decompiler.DecompileBaml(ms, assembly.FileName, new ConnectMethodDecompiler(assembly), new AssemblyResolver(assembly));
// }
// catch (XamlXmlWriterException) { } // ignore XAML writer exceptions
// if (xaml != null) {
// File.WriteAllText(Path.Combine(options.SaveAsProjectDirectory, Path.ChangeExtension(fileName, ".xaml")), xaml);
// yield return Tuple.Create("Page", Path.ChangeExtension(fileName, ".xaml"));
// continue;
// }
}
using (FileStream fs = new FileStream(Path.Combine(options.SaveAsProjectDirectory, fileName), FileMode.Create, FileAccess.Write)) {
entryStream.CopyTo(fs);
}
yield return Tuple.Create("Resource", fileName);
}
continue;
}
}
fileName = GetFileNameForResource(r.Name, directories);
using (FileStream fs = new FileStream(Path.Combine(options.SaveAsProjectDirectory, fileName), FileMode.Create, FileAccess.Write)) {
s.CopyTo(fs);
}
yield return Tuple.Create("EmbeddedResource", fileName);
}
//}
//finally {
// if (bamlDecompilerAppDomain != null)
// AppDomain.Unload(bamlDecompilerAppDomain);
//}
}
string GetFileNameForResource(string fullName, HashSet<string> directories)
{
string[] splitName = fullName.Split('.');
string fileName = TextView.DecompilerTextView.CleanUpName(fullName);
for (int i = splitName.Length - 1; i > 0; i--) {
string ns = string.Join(".", splitName, 0, i);
if (directories.Contains(ns)) {
string name = string.Join(".", splitName, i, splitName.Length - i);
fileName = Path.Combine(ns, TextView.DecompilerTextView.CleanUpName(name));
break;
}
}
return fileName;
}
#endregion
public override void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options)
{
WriteCommentLine(output, TypeToString(method.DeclaringType, includeNamespace: true));
@ -432,7 +350,7 @@ namespace ICSharpCode.ILSpy.VB @@ -432,7 +350,7 @@ namespace ICSharpCode.ILSpy.VB
public override void DecompileType(TypeDefinition type, ITextOutput output, DecompilationOptions options)
{
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: type);
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentModule: type.Module);
codeDomBuilder.AddType(type);
RunTransformsAndGenerateCode(codeDomBuilder, output, options, type.Module);
}

63
ILSpy/VB/VBTextOutputFormatter.cs

@ -34,6 +34,8 @@ namespace ICSharpCode.ILSpy.VB @@ -34,6 +34,8 @@ namespace ICSharpCode.ILSpy.VB
readonly ITextOutput output;
readonly Stack<AstNode> nodeStack = new Stack<AstNode>();
bool firstImport, lastImport;
public VBTextOutputFormatter(ITextOutput output)
{
if (output == null)
@ -43,28 +45,36 @@ namespace ICSharpCode.ILSpy.VB @@ -43,28 +45,36 @@ namespace ICSharpCode.ILSpy.VB
public void StartNode(AstNode node)
{
// var ranges = node.Annotation<List<ILRange>>();
// if (ranges != null && ranges.Count > 0)
// {
// // find the ancestor that has method mapping as annotation
// if (node.Ancestors != null && node.Ancestors.Count() > 0)
// {
// var n = node.Ancestors.FirstOrDefault(a => a.Annotation<MemberMapping>() != null);
// if (n != null) {
// MemberMapping mapping = n.Annotation<MemberMapping>();
//
// // add all ranges
// foreach (var range in ranges) {
// mapping.MemberCodeMappings.Add(new SourceCodeMapping {
// ILInstructionOffset = range,
// SourceCodeLine = output.CurrentLine,
// MemberMapping = mapping
// });
// }
// }
// }
// }
// var ranges = node.Annotation<List<ILRange>>();
// if (ranges != null && ranges.Count > 0)
// {
// // find the ancestor that has method mapping as annotation
// if (node.Ancestors != null && node.Ancestors.Count() > 0)
// {
// var n = node.Ancestors.FirstOrDefault(a => a.Annotation<MemberMapping>() != null);
// if (n != null) {
// MemberMapping mapping = n.Annotation<MemberMapping>();
//
// // add all ranges
// foreach (var range in ranges) {
// mapping.MemberCodeMappings.Add(new SourceCodeMapping {
// ILInstructionOffset = range,
// SourceCodeLine = output.CurrentLine,
// MemberMapping = mapping
// });
// }
// }
// }
// }
if (nodeStack.Count == 0) {
if (node is ImportsStatement) {
firstImport = !(node.PrevSibling is ImportsStatement);
lastImport = !(node.NextSibling is ImportsStatement);
} else {
firstImport = false;
lastImport = false;
}
}
nodeStack.Push(node);
}
@ -100,6 +110,11 @@ namespace ICSharpCode.ILSpy.VB @@ -100,6 +110,11 @@ namespace ICSharpCode.ILSpy.VB
return;
}
if (firstImport) {
output.MarkFoldStart(defaultCollapsed: true);
firstImport = false;
}
output.Write(identifier);
}
@ -198,6 +213,10 @@ namespace ICSharpCode.ILSpy.VB @@ -198,6 +213,10 @@ namespace ICSharpCode.ILSpy.VB
public void NewLine()
{
if (lastImport) {
output.MarkFoldEnd();
lastImport = false;
}
output.WriteLine();
}

2
NRefactory

@ -1 +1 @@ @@ -1 +1 @@
Subproject commit 2d65653491ba5a804dd2b44b946b1d33b00c0623
Subproject commit a2b55de351be2119b6f0c3a17c36b5b9adbd7c59

35
NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/AssemblyInfo.cs

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
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("NRefactory Test")]
[assembly: AssemblyDescription("Unit tests for the parser and refactoring library for C# and VB.NET")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("ic#code")]
[assembly: AssemblyProduct("SharpDevelop")]
[assembly: AssemblyCopyright("2004-2006 AlphaSierraPapa")]
[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("")]

102
NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/General/UnitTest.cs

@ -0,0 +1,102 @@ @@ -0,0 +1,102 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Reflection;
using NUnit.Framework;
using ICSharpCode.NRefactory.VB.Ast;
using ICSharpCode.NRefactory.VB.Parser;
namespace ICSharpCode.NRefactory.VB.Tests
{
[TestFixture]
public class StructuralTest
{
// [Test]
// public void TestToStringMethods()
// {
// Type[] allTypes = typeof(INode).Assembly.GetTypes();
//
// foreach (Type type in allTypes) {
// if (type.IsClass && !type.IsAbstract && !type.IsNested && type.GetInterface(typeof(INode).FullName) != null) {
// MethodInfo methodInfo = type.GetMethod("ToString", BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public);
// Assert.IsNotNull(methodInfo, "ToString() not found in " + type.FullName);
// }
// }
// }
//
// [Test]
// public void TestUnitTests()
// {
// Type[] allTypes = typeof(StructuralTest).Assembly.GetTypes();
//
// foreach (Type type in allTypes) {
// if (type.GetCustomAttributes(typeof(TestFixtureAttribute), true).Length > 0) {
// foreach (MethodInfo m in type.GetMethods()) {
// if (m.IsPublic && m.ReturnType == typeof(void) && m.GetParameters().Length == 0) {
// if (m.GetCustomAttributes(typeof(TestAttribute), true).Length == 0) {
// Assert.Fail(type.Name + "." + m.Name + " should have the [Test] attribute!");
// }
// }
// }
// }
// }
// }
//
// [Test]
// public void TestAcceptVisitorMethods()
// {
// Type[] allTypes = typeof(AbstractNode).Assembly.GetTypes();
//
// foreach (Type type in allTypes) {
// if (type.IsClass && !type.IsAbstract && type.GetInterface(typeof(INode).FullName) != null) {
// MethodInfo methodInfo = type.GetMethod("AcceptVisitor", BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public);
// Assertion.AssertNotNull("AcceptVisitor() not found in " + type.FullName, methodInfo);
// }
// }
// }
//
// [Test]
// public void TestIAstVisitor()
// {
// Type[] allTypes = typeof(AbstractNode).Assembly.GetTypes();
// Type visitor = typeof(IAstVisitor);
//
// foreach (Type type in allTypes) {
// if (type.IsClass && !type.IsAbstract && !type.IsNested && type.GetInterface(typeof(INode).FullName) != null && !type.Name.StartsWith("Null")) {
// MethodInfo methodInfo = visitor.GetMethod("Visit" + type.Name, BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.ExactBinding, null, new Type[] {type, typeof(object)}, null);
// Assert.IsNotNull(methodInfo, "Visit with parameter " + type.FullName + " not found");
// Assert.AreEqual(2, methodInfo.GetParameters().Length);
// ParameterInfo first = methodInfo.GetParameters()[0];
// Assert.AreEqual(Char.ToLower(first.ParameterType.Name[0]) + first.ParameterType.Name.Substring(1), first.Name);
//
// ParameterInfo second = methodInfo.GetParameters()[1];
// Assert.AreEqual(typeof(System.Object), second.ParameterType);
// Assert.AreEqual("data", second.Name);
// }
// }
// }
//
// [Test]
// public void TestAbstractAstVisitorVisitor()
// {
// Type[] allTypes = typeof(AbstractNode).Assembly.GetTypes();
// Type visitor = typeof(AbstractAstVisitor);
//
// foreach (Type type in allTypes) {
// if (type.IsClass && !type.IsAbstract && !type.IsNested && type.GetInterface(typeof(INode).FullName) != null && !type.Name.StartsWith("Null")) {
// MethodInfo methodInfo = visitor.GetMethod("Visit" + type.Name, BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.ExactBinding, null, new Type[] {type, typeof(object)}, null);
// Assert.IsNotNull(methodInfo, "Visit with parameter " + type.FullName + " not found");
//
// Assert.AreEqual(2, methodInfo.GetParameters().Length);
// ParameterInfo first = methodInfo.GetParameters()[0];
// Assert.AreEqual(Char.ToLower(first.ParameterType.Name[0]) + first.ParameterType.Name.Substring(1), first.Name);
//
// ParameterInfo second = methodInfo.GetParameters()[1];
// Assert.AreEqual(typeof(System.Object), second.ParameterType);
// Assert.AreEqual("data", second.Name);
// }
// }
// }
}
}

109
NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/ICSharpCode.NRefactory.VB.Tests.csproj

@ -0,0 +1,109 @@ @@ -0,0 +1,109 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.50215</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{870115DD-960A-4406-A6B9-600BCDC36A03}</ProjectGuid>
<RootNamespace>ICSharpCode.NRefactory.VB.Tests</RootNamespace>
<AssemblyName>ICSharpCode.NRefactory.VB.Tests</AssemblyName>
<OutputTarget>Library</OutputTarget>
<NoStdLib>False</NoStdLib>
<NoConfig>False</NoConfig>
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
<OutputType>Library</OutputType>
<OutputPath>bin\$(Configuration)\</OutputPath>
<AllowUnsafeBlocks>False</AllowUnsafeBlocks>
<WarningLevel>4</WarningLevel>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TreatWarningsAsErrors>False</TreatWarningsAsErrors>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
<NoWin32Manifest>False</NoWin32Manifest>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
<DefineConstants>DEBUG</DefineConstants>
<Optimize>False</Optimize>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<Optimize>True</Optimize>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugType>Full</DebugType>
<DebugSymbols>true</DebugSymbols>
<StartAction>Project</StartAction>
<BaseIntermediateOutputPath>obj\</BaseIntermediateOutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DebugSymbols>False</DebugSymbols>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'AnyCPU' ">
<RegisterForComInterop>False</RegisterForComInterop>
<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
<BaseAddress>4194304</BaseAddress>
<FileAlignment>4096</FileAlignment>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
<DefineConstants>DEBUG</DefineConstants>
<Optimize>False</Optimize>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<Optimize>True</Optimize>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'x86' ">
<RegisterForComInterop>False</RegisterForComInterop>
<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
<BaseAddress>4194304</BaseAddress>
<FileAlignment>4096</FileAlignment>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<Reference Include="nunit.framework">
<HintPath>..\..\ICSharpCode.Decompiler\Tests\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="AssemblyInfo.cs" />
<Compile Include="General\UnitTest.cs" />
<Compile Include="Lexer\CustomLexerTests.cs" />
<Compile Include="Lexer\ImplicitLineContinuationTests.cs" />
<Compile Include="Lexer\LATextReaderTests.cs" />
<Compile Include="Lexer\LexerContextTests.cs" />
<Compile Include="Lexer\LexerPositionTests.cs" />
<Compile Include="Lexer\LexerTests.cs" />
<Compile Include="Lexer\LiteralsTests.cs" />
<Compile Include="Lexer\TokenTests.cs" />
<Compile Include="Lexer\XmlModeLexerTests.cs" />
<Compile Include="Parser\GlobalScope\AttributeSectionTests.cs" />
<Compile Include="Parser\GlobalScope\NamespaceDeclarationTests.cs" />
<Compile Include="Parser\GlobalScope\ImportsStatementTests.cs" />
<Compile Include="Parser\GlobalScope\TypeDeclarationTests.cs" />
<Compile Include="Parser\SnippetParserTests.cs" />
<Compile Include="Parser\ParseUtil.cs" />
<Compile Include="Parser\GlobalScope\OptionStatementTests.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ICSharpCode.NRefactory.VB\ICSharpCode.NRefactory.VB.csproj">
<Project>{7b82b671-419f-45f4-b778-d9286f996efa}</Project>
<Name>ICSharpCode.NRefactory.VB</Name>
</ProjectReference>
<ProjectReference Include="..\..\NRefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">
<Project>{3b2a5653-ec97-4001-bb9b-d90f1af2c371}</Project>
<Name>ICSharpCode.NRefactory</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />
</Project>

118
NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Lexer/CustomLexerTests.cs

@ -0,0 +1,118 @@ @@ -0,0 +1,118 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.IO;
using NUnit.Framework;
using ICSharpCode.NRefactory.VB.Parser;
namespace ICSharpCode.NRefactory.VB.Tests.Lexer
{
[TestFixture]
public class CustomLexerTests
{
VBLexer GenerateLexer(StringReader sr)
{
return new VBLexer(sr);
}
[Test]
public void TestSingleEOLForMulitpleLines()
{
VBLexer lexer = GenerateLexer(new StringReader("Stop\n\n\nEnd"));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.Stop));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOL));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.End));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOL));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOF));
}
[Test]
public void TestSingleEOLForMulitpleLinesWithContinuation()
{
VBLexer lexer = GenerateLexer(new StringReader("Stop\n _\n\nEnd"));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.Stop));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOL));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.End));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOL));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOF));
}
[Test]
public void EscapedIdentifier()
{
VBLexer lexer = GenerateLexer(new StringReader("[Stop]"));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.Identifier));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOL));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOF));
}
[Test]
public void IdentifierWithTypeCharacter()
{
VBLexer lexer = GenerateLexer(new StringReader("Stop$"));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.Identifier));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOL));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOF));
}
[Test]
public void ExclamationMarkIsTypeCharacter()
{
VBLexer lexer = GenerateLexer(new StringReader("a!=b"));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.Identifier));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.Assign));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.Identifier));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOL));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOF));
}
[Test]
public void ExclamationMarkIsTypeCharacter2()
{
VBLexer lexer = GenerateLexer(new StringReader("a! b"));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.Identifier));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.Identifier));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOL));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOF));
}
[Test]
public void ExclamationMarkIsIdentifier()
{
VBLexer lexer = GenerateLexer(new StringReader("a!b"));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.Identifier));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.ExclamationMark));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.Identifier));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOL));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOF));
}
[Test]
public void ExclamationMarkIsIdentifier2()
{
VBLexer lexer = GenerateLexer(new StringReader("a![b]"));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.Identifier));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.ExclamationMark));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.Identifier));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOL));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOF));
}
[Test]
public void RemCommentTest()
{
VBLexer lexer = GenerateLexer(new StringReader("a rem b"));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.Identifier));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOL));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOF));
}
[Test]
public void RemCommentTest2()
{
VBLexer lexer = GenerateLexer(new StringReader("REM c"));
Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOF));
}
}
}

230
NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Lexer/ImplicitLineContinuationTests.cs

@ -0,0 +1,230 @@ @@ -0,0 +1,230 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.IO;
using ICSharpCode.NRefactory.VB.Parser;
using NUnit.Framework;
namespace ICSharpCode.NRefactory.VB.Tests.Lexer
{
[TestFixture]
public class ImplicitLineContinuationTests
{
[Test]
public void Example1()
{
string code = @"Module Test
Sub Print(
Param1 As Integer,
Param2 As Integer)
If (Param1 < Param2) Or
(Param1 > Param2) Then
Console.WriteLine(""Not equal"")
End If
End Sub
End Module";
VBLexer lexer = GenerateLexer(new StringReader(code));
CheckTokens(lexer, Tokens.Module, Tokens.Identifier, Tokens.EOL,
Tokens.Sub, Tokens.Identifier, Tokens.OpenParenthesis,
Tokens.Identifier, Tokens.As, Tokens.Integer, Tokens.Comma,
Tokens.Identifier, Tokens.As, Tokens.Integer, Tokens.CloseParenthesis, Tokens.EOL,
Tokens.If, Tokens.OpenParenthesis, Tokens.Identifier, Tokens.LessThan, Tokens.Identifier, Tokens.CloseParenthesis, Tokens.Or,
Tokens.OpenParenthesis, Tokens.Identifier, Tokens.GreaterThan, Tokens.Identifier, Tokens.CloseParenthesis, Tokens.Then, Tokens.EOL,
Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.OpenParenthesis, Tokens.LiteralString, Tokens.CloseParenthesis, Tokens.EOL,
Tokens.End, Tokens.If, Tokens.EOL,
Tokens.End, Tokens.Sub, Tokens.EOL,
Tokens.End, Tokens.Module);
}
[Test]
public void QualifierInWith()
{
string code = @"Module Test
Sub Print
With xml
Dim a = b.
d
Dim c = .
Count
End With
End Sub
End Module";
VBLexer lexer = GenerateLexer(new StringReader(code));
CheckTokens(lexer, Tokens.Module, Tokens.Identifier, Tokens.EOL,
Tokens.Sub, Tokens.Identifier, Tokens.EOL,
Tokens.With, Tokens.Identifier, Tokens.EOL,
Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.EOL,
Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.Dot, Tokens.EOL,
Tokens.Identifier, Tokens.EOL,
Tokens.End, Tokens.With, Tokens.EOL,
Tokens.End, Tokens.Sub, Tokens.EOL,
Tokens.End, Tokens.Module);
}
[Test]
public void Example2()
{
string code = @"Module Test
Sub Print
Dim a = _
y
End Sub
End Module";
VBLexer lexer = GenerateLexer(new StringReader(code));
CheckTokens(lexer, Tokens.Module, Tokens.Identifier, Tokens.EOL,
Tokens.Sub, Tokens.Identifier, Tokens.EOL,
Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.EOL, Tokens.Identifier, Tokens.EOL,
Tokens.End, Tokens.Sub, Tokens.EOL,
Tokens.End, Tokens.Module);
}
[Test]
public void Query()
{
string code = @"Module Test
Sub A
Dim q = From x In a
Select x
End Sub
End Module";
VBLexer lexer = GenerateLexer(new StringReader(code));
CheckTokens(lexer, Tokens.Module, Tokens.Identifier, Tokens.EOL,
Tokens.Sub, Tokens.Identifier, Tokens.EOL,
Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.From, Tokens.Identifier, Tokens.In, Tokens.Identifier,
Tokens.Select, Tokens.Identifier, Tokens.EOL,
Tokens.End, Tokens.Sub, Tokens.EOL,
Tokens.End, Tokens.Module);
}
[Test]
public void Query1()
{
string code = @"Module Test
Sub A
Dim actions = From a in b Select Sub()
Dim i = 1
Select Case i
End Select
End Sub
End Sub
End Module";
VBLexer lexer = GenerateLexer(new StringReader(code));
CheckTokens(lexer, Tokens.Module, Tokens.Identifier, Tokens.EOL,
Tokens.Sub, Tokens.Identifier, Tokens.EOL,
Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.From, Tokens.Identifier, Tokens.In, Tokens.Identifier, Tokens.Select, Tokens.Sub, Tokens.OpenParenthesis, Tokens.CloseParenthesis, Tokens.EOL,
Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.LiteralInteger, Tokens.EOL,
Tokens.Select, Tokens.Case, Tokens.Identifier, Tokens.EOL,
Tokens.End, Tokens.Select, Tokens.EOL,
Tokens.End, Tokens.Sub, Tokens.EOL,
Tokens.End, Tokens.Sub, Tokens.EOL,
Tokens.End, Tokens.Module);
}
/// <remarks>tests http://community.sharpdevelop.net/forums/p/12068/32893.aspx#32893</remarks>
[Test]
public void Bug_Thread12068()
{
string code = @"Class MainClass
Public Shared Sub Main()
Dim categoryNames = From p In AList _
Select p.AFunction(1,2,3) _
Distinct
End Sub
End Class";
VBLexer lexer = GenerateLexer(new StringReader(code));
CheckTokens(
lexer, Tokens.Class, Tokens.Identifier, Tokens.EOL,
Tokens.Public, Tokens.Shared, Tokens.Sub, Tokens.Identifier, Tokens.OpenParenthesis, Tokens.CloseParenthesis, Tokens.EOL,
Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.From, Tokens.Identifier, Tokens.In, Tokens.Identifier,
Tokens.Select, Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.OpenParenthesis, Tokens.LiteralInteger,
Tokens.Comma, Tokens.LiteralInteger, Tokens.Comma, Tokens.LiteralInteger, Tokens.CloseParenthesis,
Tokens.Distinct, Tokens.EOL,
Tokens.End, Tokens.Sub, Tokens.EOL,
Tokens.End, Tokens.Class
);
}
[Test]
public void LineContinuationAfterAttributes()
{
string code = @"<TestFixture>
Public Class TestContinuation
<Test>
Public Sub TestMethod
Assert.Fail
End Sub
<Test> _
Public Sub TestMethod2
Assert.Fail
End Sub
End Class";
VBLexer lexer = GenerateLexer(new StringReader(code));
CheckTokens(
lexer, Tokens.LessThan, Tokens.Identifier, Tokens.GreaterThan,
Tokens.Public, Tokens.Class, Tokens.Identifier, Tokens.EOL,
Tokens.LessThan, Tokens.Identifier, Tokens.GreaterThan,
Tokens.Public, Tokens.Sub, Tokens.Identifier, Tokens.EOL,
Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.EOL,
Tokens.End, Tokens.Sub, Tokens.EOL,
Tokens.LessThan, Tokens.Identifier, Tokens.GreaterThan,
Tokens.Public, Tokens.Sub, Tokens.Identifier, Tokens.EOL,
Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.EOL,
Tokens.End, Tokens.Sub, Tokens.EOL,
Tokens.End, Tokens.Class
);
}
[Test]
public void NoILCAfterGlobalAttributes()
{
string code = "<Assembly: AssemblyTitle(\"My.UnitTests\")>" + Environment.NewLine +
"<Assembly: AssemblyDescription(\"\")>";
VBLexer lexer = GenerateLexer(new StringReader(code));
CheckTokens(
lexer, Tokens.LessThan, Tokens.Assembly, Tokens.Colon,
Tokens.Identifier, Tokens.OpenParenthesis, Tokens.LiteralString,
Tokens.CloseParenthesis, Tokens.GreaterThan, Tokens.EOL,
Tokens.LessThan, Tokens.Assembly, Tokens.Colon,
Tokens.Identifier, Tokens.OpenParenthesis, Tokens.LiteralString,
Tokens.CloseParenthesis, Tokens.GreaterThan
);
}
#region Helpers
VBLexer GenerateLexer(StringReader sr)
{
return new VBLexer(sr);
}
void CheckTokens(VBLexer lexer, params int[] tokens)
{
for (int i = 0; i < tokens.Length; i++) {
int token = tokens[i];
Token t = lexer.NextToken();
int next = t.Kind;
Assert.AreEqual(token, next, "{2} of {3}: {0} != {1}; at {4}", Tokens.GetTokenString(token), Tokens.GetTokenString(next), i + 1, tokens.Length, t.Location);
}
}
#endregion
}
}

35
NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Lexer/LATextReaderTests.cs

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.IO;
using ICSharpCode.NRefactory.VB.Parser;
using NUnit.Framework;
namespace ICSharpCode.NRefactory.VB.Tests.Lexer
{
[TestFixture]
public class LATextReaderTests
{
[Test]
public void TestPeek()
{
LATextReader reader = new LATextReader(new StringReader("abcd"));
CheckPeek(reader, 0, 'a');
CheckPeek(reader, 2, 'c');
CheckPeek(reader, 3, 'd');
CheckPeek(reader, 1, 'b');
CheckPeek(reader, 0, 'a');
Assert.AreEqual((int)'a', reader.Read());
CheckPeek(reader, 1, 'c');
CheckPeek(reader, 2, 'd');
CheckPeek(reader, 0, 'b');
}
void CheckPeek(LATextReader reader, int num1, char char2)
{
Assert.AreEqual((int)char2, reader.Peek(num1));
}
}
}

575
NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Lexer/LexerContextTests.cs

@ -0,0 +1,575 @@ @@ -0,0 +1,575 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.IO;
using NUnit.Framework;
using ICSharpCode.NRefactory.VB.Parser;
namespace ICSharpCode.NRefactory.VB.Tests.Lexer
{
[TestFixture]
public class LexerContextTests
{
[Test]
public void SimpleGlobal()
{
RunTest(
@"Option Explicit",
@"enter Global
exit Global
"
);
}
[Test]
public void VariableWithXmlLiteral()
{
RunTest(
@"Class Test
Public Sub New()
Dim x = <a />
End Sub
End Class
",
@"enter Global
enter TypeDeclaration
enter Identifier
exit Identifier
enter Member
enter Identifier
exit Identifier
enter Body
enter Identifier
exit Identifier
enter Expression
enter Expression
enter Expression
enter Xml
enter Xml
exit Xml
exit Xml
exit Expression
exit Expression
exit Expression
exit Body
exit Member
exit TypeDeclaration
exit Global
"
);
}
[Test]
public void MemberWithXmlLiteral()
{
RunTest(
@"Class Test
Private xml As XElement = <b />
Public Sub New()
Dim x = <a />
End Sub
End Class
",
@"enter Global
enter TypeDeclaration
enter Identifier
exit Identifier
enter Member
enter Identifier
exit Identifier
enter Type
exit Type
enter Expression
enter Expression
enter Expression
enter Xml
enter Xml
exit Xml
exit Xml
exit Expression
exit Expression
exit Expression
exit Member
enter Member
enter Identifier
exit Identifier
enter Body
enter Identifier
exit Identifier
enter Expression
enter Expression
enter Expression
enter Xml
enter Xml
exit Xml
exit Xml
exit Expression
exit Expression
exit Expression
exit Body
exit Member
exit TypeDeclaration
exit Global
"
);
}
[Test]
public void GlobalAttributeTest()
{
RunTest(
@"<assembly: CLSCompliant(True)>
Class Test
Public Sub New()
Dim x = 5
End Sub
End Class
",
@"enter Global
enter Attribute
exit Attribute
enter TypeDeclaration
enter Identifier
exit Identifier
enter Member
enter Identifier
exit Identifier
enter Body
enter Identifier
exit Identifier
enter Expression
enter Expression
enter Expression
exit Expression
exit Expression
exit Expression
exit Body
exit Member
exit TypeDeclaration
exit Global
"
);
}
[Test]
public void ClassAttributeTest()
{
RunTest(
@"<Serializable>
Class Test
Public Sub New()
Dim x = 5
End Sub
End Class
",
@"enter Global
enter Attribute
exit Attribute
enter TypeDeclaration
enter Identifier
exit Identifier
enter Member
enter Identifier
exit Identifier
enter Body
enter Identifier
exit Identifier
enter Expression
enter Expression
enter Expression
exit Expression
exit Expression
exit Expression
exit Body
exit Member
exit TypeDeclaration
exit Global
"
);
}
[Test]
public void MethodAttributeTest()
{
RunTest(
@"Class Test
<Test>
Public Sub New()
Dim x = 5
End Sub
End Class
",
@"enter Global
enter TypeDeclaration
enter Identifier
exit Identifier
enter Attribute
exit Attribute
enter Member
enter Identifier
exit Identifier
enter Body
enter Identifier
exit Identifier
enter Expression
enter Expression
enter Expression
exit Expression
exit Expression
exit Expression
exit Body
exit Member
exit TypeDeclaration
exit Global
"
);
}
[Test]
public void WithBlockTest()
{
RunTest(
@"Class Test
Public Sub New()
With x
End With
End Sub
End Class
",
@"enter Global
enter TypeDeclaration
enter Identifier
exit Identifier
enter Member
enter Identifier
exit Identifier
enter Body
enter Expression
enter Expression
enter Expression
exit Expression
exit Expression
exit Expression
enter Body
exit Body
exit Body
exit Member
exit TypeDeclaration
exit Global
"
);
}
[Test]
public void StatementsTest()
{
RunTest(
@"Class Test
Public Sub New()
For i As Integer = 0 To 10
Next
For Each x As Integer In list
Next
Try
Catch e As Exception
End Try
End Sub
End Class
",
@"enter Global
enter TypeDeclaration
enter Identifier
exit Identifier
enter Member
enter Identifier
exit Identifier
enter Body
enter Identifier
enter Expression
exit Expression
exit Identifier
enter Type
exit Type
enter Expression
enter Expression
enter Expression
exit Expression
exit Expression
enter Expression
enter Expression
exit Expression
exit Expression
exit Expression
enter Body
exit Body
enter Identifier
enter Expression
exit Expression
exit Identifier
enter Type
exit Type
enter Expression
enter Expression
enter Expression
exit Expression
exit Expression
exit Expression
enter Body
exit Body
enter Body
exit Body
enter Identifier
exit Identifier
enter Type
exit Type
enter Body
exit Body
exit Body
exit Member
exit TypeDeclaration
exit Global
"
);
}
[Test]
public void ClassTest()
{
RunTest(
@"Class MainClass ' a comment
Dim under_score_field As Integer
Sub SomeMethod()
simple += 1
For Each loopVarName In collection
Next
End Sub
End Class",
@"enter Global
enter TypeDeclaration
enter Identifier
exit Identifier
enter Member
enter Identifier
exit Identifier
enter Type
exit Type
exit Member
enter Member
enter Identifier
exit Identifier
enter Body
enter Expression
enter Expression
enter Expression
exit Expression
exit Expression
enter Expression
enter Expression
exit Expression
exit Expression
exit Expression
enter Identifier
enter Expression
exit Expression
exit Identifier
enter Expression
enter Expression
enter Expression
exit Expression
exit Expression
exit Expression
enter Body
exit Body
exit Body
exit Member
exit TypeDeclaration
exit Global
");
}
[Test]
public void CollectionInitializer()
{
RunTest(@"'
' Created by SharpDevelop.
' User: Siegfried
' Date: 22.06.2010
' Time: 21:29
'
' To change this template use Tools | Options | Coding | Edit Standard Headers.
'
Option Infer On
Imports System.Linq
Imports System.Xml.Linq
Module Program
Sub Main()
Console.WriteLine(""Hello World!"")
Dim name = ""Test""
Dim content = { 4, 5, New XAttribute(""a"", 3) }
Dim xml = <<%= name %> <%= content %> />
Console.ReadKey()
End Sub
End Module",
@"enter Global
enter Importable
exit Importable
enter Importable
exit Importable
enter TypeDeclaration
enter Identifier
exit Identifier
enter Member
enter Identifier
exit Identifier
enter Body
enter Expression
enter Expression
enter Expression
exit Expression
enter Expression
enter Expression
enter Expression
enter Expression
exit Expression
exit Expression
exit Expression
exit Expression
exit Expression
exit Expression
enter Identifier
exit Identifier
enter Expression
enter Expression
enter Expression
exit Expression
exit Expression
exit Expression
enter Identifier
exit Identifier
enter Expression
enter Expression
enter Expression
enter Expression
enter Expression
exit Expression
exit Expression
exit Expression
enter Expression
enter Expression
enter Expression
exit Expression
exit Expression
exit Expression
enter Expression
enter Expression
enter ObjectCreation
enter Expression
enter Expression
enter Expression
enter Expression
exit Expression
exit Expression
exit Expression
enter Expression
enter Expression
enter Expression
exit Expression
exit Expression
exit Expression
exit Expression
exit ObjectCreation
exit Expression
exit Expression
exit Expression
exit Expression
enter Identifier
exit Identifier
enter Expression
enter Expression
enter Expression
enter Xml
enter Xml
enter Expression
enter Expression
enter Expression
exit Expression
exit Expression
exit Expression
enter Expression
enter Expression
enter Expression
exit Expression
exit Expression
exit Expression
exit Xml
exit Xml
exit Expression
exit Expression
exit Expression
enter Expression
enter Expression
enter Expression
exit Expression
enter Expression
exit Expression
exit Expression
exit Expression
exit Body
exit Member
exit TypeDeclaration
exit Global
");
}
[Test]
public void Imports()
{
RunTest(@"Imports System
Imports System.Linq
Imports System.Collections.Generic",
@"enter Global
enter Importable
exit Importable
enter Importable
exit Importable
enter Importable
exit Importable
exit Global
");
}
void RunTest(string code, string expectedOutput)
{
ExpressionFinder p = new ExpressionFinder();
VBLexer lexer = new VBLexer(new StringReader(code));
Token t;
do {
t = lexer.NextToken();
p.InformToken(t);
} while (t.Kind != Tokens.EOF);
Console.WriteLine(p.Output);
Assert.IsEmpty(p.Errors);
Assert.AreEqual(expectedOutput.Replace("\r", ""),
p.Output.Replace("\r", ""));
}
}
}

87
NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Lexer/LexerPositionTests.cs

@ -0,0 +1,87 @@ @@ -0,0 +1,87 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.IO;
using ICSharpCode.NRefactory.VB.Parser;
using NUnit.Framework;
namespace ICSharpCode.NRefactory.VB.Tests.Lexer
{
[TestFixture]
public class LexerPositionTests
{
VBLexer GenerateLexer(string s)
{
return new VBLexer(new StringReader(s));
}
[Test]
public void TestNewLine()
{
VBLexer l = GenerateLexer("public\nstatic");
Token t = l.NextToken();
Assert.AreEqual(Tokens.Public, t.Kind);
Assert.AreEqual(new TextLocation(1, 1), t.Location);
Assert.AreEqual(new TextLocation(1, 7), t.EndLocation);
t = l.NextToken();
Assert.AreEqual(Tokens.EOL, t.Kind);
Assert.AreEqual(new TextLocation(1, 7), t.Location);
Assert.AreEqual(new TextLocation(2, 1), t.EndLocation);
t = l.NextToken();
Assert.AreEqual(Tokens.Static, t.Kind);
Assert.AreEqual(new TextLocation(2, 1), t.Location);
Assert.AreEqual(new TextLocation(2, 7), t.EndLocation);
}
[Test]
public void TestCarriageReturnNewLine()
{
VBLexer l = GenerateLexer("public\r\nstatic");
Token t = l.NextToken();
Assert.AreEqual(Tokens.Public, t.Kind);
Assert.AreEqual(new TextLocation(1, 1), t.Location);
Assert.AreEqual(new TextLocation(1, 7), t.EndLocation);
t = l.NextToken();
Assert.AreEqual(Tokens.EOL, t.Kind);
Assert.AreEqual(new TextLocation(1, 7), t.Location);
Assert.AreEqual(new TextLocation(2, 1), t.EndLocation);
t = l.NextToken();
Assert.AreEqual(Tokens.Static, t.Kind);
Assert.AreEqual(new TextLocation(2, 1), t.Location);
Assert.AreEqual(new TextLocation(2, 7), t.EndLocation);
}
[Test]
public void TestPositionOfEOF1()
{
VBLexer l = GenerateLexer("public");
l.NextToken(); // public
Token t = l.NextToken();
Assert.AreEqual(Tokens.EOL, t.Kind);
Assert.AreEqual(new TextLocation(1, 7), t.Location);
Assert.AreEqual(new TextLocation(1, 7), t.EndLocation);
t = l.NextToken();
Assert.AreEqual(Tokens.EOF, t.Kind);
Assert.AreEqual(new TextLocation(1, 7), t.Location);
Assert.AreEqual(new TextLocation(1, 7), t.EndLocation);
}
[Test]
public void TestPositionOfEOF2()
{
VBLexer l = GenerateLexer("public _\n ");
l.NextToken(); // public
Token t = l.NextToken();
Assert.AreEqual(Tokens.EOL, t.Kind);
Assert.AreEqual(new TextLocation(2, 2), t.Location);
Assert.AreEqual(new TextLocation(2, 2), t.EndLocation);
t = l.NextToken();
Assert.AreEqual(Tokens.EOF, t.Kind);
Assert.AreEqual(new TextLocation(2, 2), t.Location);
Assert.AreEqual(new TextLocation(2, 2), t.EndLocation);
}
}
}

1538
NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Lexer/LexerTests.cs

File diff suppressed because it is too large Load Diff

194
NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Lexer/LiteralsTests.cs

@ -0,0 +1,194 @@ @@ -0,0 +1,194 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.IO;
using ICSharpCode.NRefactory.VB.Parser;
using NUnit.Framework;
namespace ICSharpCode.NRefactory.VB.Tests.Lexer
{
[TestFixture]
public sealed class LiteralsTests
{
VBLexer GenerateLexer(StringReader sr)
{
return new VBLexer(sr);
}
Token GetSingleToken(string text)
{
VBLexer lexer = GenerateLexer(new StringReader(text));
Token t = lexer.NextToken();
Assert.AreEqual(Tokens.EOL, lexer.NextToken().Kind, "Tokens.EOL");
Assert.AreEqual(Tokens.EOF, lexer.NextToken().Kind, "Tokens.EOF");
Assert.AreEqual("", lexer.Errors.ErrorOutput);
return t;
}
void CheckToken(string text, int tokenType, object val)
{
Token t = GetSingleToken(text);
Assert.AreEqual(tokenType, t.Kind, "Tokens.Literal");
Assert.IsNotNull(t.LiteralValue, "literalValue is null");
Assert.AreEqual(val.GetType(), t.LiteralValue.GetType(), "literalValue.GetType()");
Assert.AreEqual(val, t.LiteralValue, "literalValue");
}
[Test]
public void TestSingleDigit()
{
CheckToken("5", Tokens.LiteralInteger, 5);
}
[Test]
public void TestZero()
{
CheckToken("0", Tokens.LiteralInteger, 0);
}
[Test]
public void TestInteger()
{
CheckToken("15", Tokens.LiteralInteger, 15);
CheckToken("8581", Tokens.LiteralInteger, 8581);
}
[Test]
public void InvalidTypeCharacter()
{
// just check that we don't get exceptions:
GenerateLexer(new StringReader(".5s")).NextToken();
GenerateLexer(new StringReader(".5ul")).NextToken();
}
[Test]
public void TestHexadecimalInteger()
{
CheckToken("&H10", Tokens.LiteralInteger, 0x10);
CheckToken("&H10&", Tokens.LiteralInteger, (long)0x10);
CheckToken("&h3ff%", Tokens.LiteralInteger, 0x3ff);
CheckToken("&h8000s", Tokens.LiteralInteger, short.MinValue);
CheckToken("&h8000us", Tokens.LiteralInteger, (ushort)0x8000);
CheckToken("&HffffFFFF", Tokens.LiteralInteger, -1);
CheckToken("&HffffFFFF%", Tokens.LiteralInteger, -1);
CheckToken("&HffffFFFFui", Tokens.LiteralInteger, uint.MaxValue);
CheckToken("&HffffFFFF&", Tokens.LiteralInteger, (long)uint.MaxValue);
}
[Test]
public void TestLongHexadecimalInteger()
{
CheckToken("&H4244636f446c6d58", Tokens.LiteralInteger, 0x4244636f446c6d58);
CheckToken("&hf244636f446c6d58", Tokens.LiteralInteger, -989556688574190248);
CheckToken("&hf244636f446c6d58&", Tokens.LiteralInteger, -989556688574190248);
CheckToken("&hf244636f446c6d58ul", Tokens.LiteralInteger, 0xf244636f446c6d58);
}
[Test]
public void InvalidHexadecimalInteger()
{
// just check that we don't get exceptions:
GenerateLexer(new StringReader("&H")).NextToken();
// >ulong.MaxValue
GenerateLexer(new StringReader("&hff244636f446c6d58")).NextToken();
// needs an ulong, but "i" postfix specified integer
GenerateLexer(new StringReader("&hf244636f446c6d58i")).NextToken();
GenerateLexer(new StringReader("&hf244636f446c6d58ui")).NextToken();
}
[Test]
public void TestIncompleteHexadecimal()
{
VBLexer lexer = GenerateLexer(new StringReader("&H\r\nabc"));
Token t = lexer.NextToken();
Assert.AreEqual(Tokens.LiteralInteger, t.Kind);
Assert.AreEqual(0, (int)t.LiteralValue);
Assert.AreEqual(Tokens.EOL, lexer.NextToken().Kind, "Tokens.EOL (1)");
Assert.AreEqual(Tokens.Identifier, lexer.NextToken().Kind, "Tokens.Identifier");
Assert.AreEqual(Tokens.EOL, lexer.NextToken().Kind, "Tokens.EOL (2)");
Assert.AreEqual(Tokens.EOF, lexer.NextToken().Kind, "Tokens.EOF");
Assert.AreNotEqual("", lexer.Errors.ErrorOutput);
}
[Test]
public void TestStringLiterals()
{
CheckToken("\"\"", Tokens.LiteralString, "");
CheckToken("\"Hello, World!\"", Tokens.LiteralString, "Hello, World!");
CheckToken("\"\"\"\"", Tokens.LiteralString, "\"");
}
[Test]
public void TestCharacterLiterals()
{
CheckToken("\" \"c", Tokens.LiteralCharacter, ' ');
CheckToken("\"!\"c", Tokens.LiteralCharacter, '!');
CheckToken("\"\"\"\"c", Tokens.LiteralCharacter, '"');
}
[Test]
public void TestDateLiterals()
{
CheckToken("# 8/23/1970 #", Tokens.LiteralDate, new DateTime(1970, 8, 23, 0, 0, 0));
CheckToken("#8/23/1970#", Tokens.LiteralDate, new DateTime(1970, 8, 23, 0, 0, 0));
CheckToken("# 8/23/1970 3:45:39AM #", Tokens.LiteralDate, new DateTime(1970, 8, 23, 3, 45, 39));
CheckToken("# 3:45:39AM #", Tokens.LiteralDate, new DateTime(1, 1, 1, 3, 45, 39));
CheckToken("# 3:45:39 PM #", Tokens.LiteralDate, new DateTime(1, 1, 1, 15, 45, 39));
CheckToken("# 3:45:39 #", Tokens.LiteralDate, new DateTime(1, 1, 1, 3, 45, 39));
CheckToken("# 13:45:39 #", Tokens.LiteralDate, new DateTime(1, 1, 1, 13, 45, 39));
CheckToken("# 1AM #", Tokens.LiteralDate, new DateTime(1, 1, 1, 1, 0, 0));
}
[Test]
public void TestDouble()
{
CheckToken("1.0", Tokens.LiteralDouble, 1.0);
CheckToken("1.1", Tokens.LiteralDouble, 1.1);
CheckToken("2e-5", Tokens.LiteralDouble, 2e-5);
CheckToken("2.0e-5", Tokens.LiteralDouble, 2e-5);
CheckToken("2e5", Tokens.LiteralDouble, 2e5);
CheckToken("2.2e5", Tokens.LiteralDouble, 2.2e5);
CheckToken("2e+5", Tokens.LiteralDouble, 2e5);
CheckToken("2.2e+5", Tokens.LiteralDouble, 2.2e5);
CheckToken("1r", Tokens.LiteralDouble, 1.0);
CheckToken("1.0r", Tokens.LiteralDouble, 1.0);
CheckToken("1.1r", Tokens.LiteralDouble, 1.1);
CheckToken("2e-5r", Tokens.LiteralDouble, 2e-5);
CheckToken("2.0e-5r", Tokens.LiteralDouble, 2e-5);
CheckToken("2e5r", Tokens.LiteralDouble, 2e5);
CheckToken("2.2e5r", Tokens.LiteralDouble, 2.2e5);
CheckToken("2e+5r", Tokens.LiteralDouble, 2e5);
CheckToken("2.2e+5r", Tokens.LiteralDouble, 2.2e5);
}
[Test]
public void TestSingle()
{
CheckToken("1f", Tokens.LiteralSingle, 1.0f);
CheckToken("1.0f", Tokens.LiteralSingle, 1.0f);
CheckToken("1.1f", Tokens.LiteralSingle, 1.1f);
CheckToken("2e-5f", Tokens.LiteralSingle, 2e-5f);
CheckToken("2.0e-5f", Tokens.LiteralSingle, 2e-5f);
CheckToken("2e5f", Tokens.LiteralSingle, 2e5f);
CheckToken("2.2e5f", Tokens.LiteralSingle, 2.2e5f);
CheckToken("2e+5f", Tokens.LiteralSingle, 2e5f);
CheckToken("2.2e+5f", Tokens.LiteralSingle, 2.2e5f);
}
[Test]
public void TestDecimal()
{
CheckToken("1d", Tokens.LiteralDecimal, 1m);
CheckToken("1.0d", Tokens.LiteralDecimal, 1.0m);
CheckToken("1.1d", Tokens.LiteralDecimal, 1.1m);
CheckToken("2e-5d", Tokens.LiteralDecimal, 2e-5m);
CheckToken("2.0e-5d", Tokens.LiteralDecimal, 2.0e-5m);
CheckToken("2e5d", Tokens.LiteralDecimal, 2e5m);
CheckToken("2.2e5d", Tokens.LiteralDecimal, 2.2e5m);
CheckToken("2e+5d", Tokens.LiteralDecimal, 2e5m);
CheckToken("2.2e+5d", Tokens.LiteralDecimal, 2.2e5m);
}
}
}

23
NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Lexer/TokenTests.cs

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using ICSharpCode.NRefactory.VB.Parser;
using NUnit.Framework;
namespace ICSharpCode.NRefactory.VB.Tests.Lexer
{
[TestFixture]
public class TokenTests
{
[Test]
public void TokenToStringDoesNotThrowException()
{
Assert.DoesNotThrow(
() => {
string text = new Token(71, 1, 1).ToString();
}
);
}
}
}

993
NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Lexer/XmlModeLexerTests.cs

@ -0,0 +1,993 @@ @@ -0,0 +1,993 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.IO;
using ICSharpCode.NRefactory.VB;
using ICSharpCode.NRefactory.VB.Parser;
using NUnit.Framework;
namespace ICSharpCode.NRefactory.VB.Tests.Lexer
{
[TestFixture]
public class XmlModeLexerTests
{
#region Xml Tests
[Test]
public void TagWithContent()
{
VBLexer lexer = GenerateLexer(new StringReader(TestStatement("Dim x = <Test>Hello World</Test>")));
CheckHead(lexer);
Assert.AreEqual(Tokens.Dim, lexer.NextToken().Kind);
Assert.AreEqual(Tokens.Identifier, lexer.NextToken().Kind);
Assert.AreEqual(Tokens.Assign, lexer.NextToken().Kind);
Assert.AreEqual(Tokens.XmlOpenTag, lexer.NextToken().Kind);
Assert.AreEqual(Tokens.Identifier, lexer.NextToken().Kind);
Assert.AreEqual(Tokens.XmlCloseTag, lexer.NextToken().Kind);
Assert.AreEqual(Tokens.XmlContent, lexer.NextToken().Kind);
Assert.AreEqual(Tokens.XmlOpenEndTag, lexer.NextToken().Kind);
Assert.AreEqual(Tokens.Identifier, lexer.NextToken().Kind);
Assert.AreEqual(Tokens.XmlCloseTag, lexer.NextToken().Kind);
CheckFoot(lexer);
}
[Test]
public void HtmlText()
{
VBLexer lexer = GenerateLexer(new StringReader(TestStatement("Dim x = <div><h1>Title</h1>" +
"<p>test test <br /> test</p></div>")));
CheckHead(lexer);
Assert.AreEqual(Tokens.Dim, lexer.NextToken().Kind);
Assert.AreEqual(Tokens.Identifier, lexer.NextToken().Kind);
Assert.AreEqual(Tokens.Assign, lexer.NextToken().Kind);
// <div>
Assert.AreEqual(Tokens.XmlOpenTag, lexer.NextToken().Kind);
Assert.AreEqual(Tokens.Identifier, lexer.NextToken().Kind);
Assert.AreEqual(Tokens.XmlCloseTag, lexer.NextToken().Kind);
// <h1>
Assert.AreEqual(Tokens.XmlOpenTag, lexer.NextToken().Kind);
Assert.AreEqual(Tokens.Identifier, lexer.NextToken().Kind);
Assert.AreEqual(Tokens.XmlCloseTag, lexer.NextToken().Kind);
// Title
Assert.AreEqual(Tokens.XmlContent, lexer.NextToken().Kind);
// </h1>
Assert.AreEqual(Tokens.XmlOpenEndTag, lexer.NextToken().Kind);
Assert.AreEqual(Tokens.Identifier, lexer.NextToken().Kind);
Assert.AreEqual(Tokens.XmlCloseTag, lexer.NextToken().Kind);
// <p>
Assert.AreEqual(Tokens.XmlOpenTag, lexer.NextToken().Kind);
Assert.AreEqual(Tokens.Identifier, lexer.NextToken().Kind);
Assert.AreEqual(Tokens.XmlCloseTag, lexer.NextToken().Kind);
// test test
Assert.AreEqual(Tokens.XmlContent, lexer.NextToken().Kind);
// <br />
Assert.AreEqual(Tokens.XmlOpenTag, lexer.NextToken().Kind);
Assert.AreEqual(Tokens.Identifier, lexer.NextToken().Kind);
Assert.AreEqual(Tokens.XmlCloseTagEmptyElement, lexer.NextToken().Kind);
// test
Assert.AreEqual(Tokens.XmlContent, lexer.NextToken().Kind);
// </p>
Assert.AreEqual(Tokens.XmlOpenEndTag, lexer.NextToken().Kind);
Assert.AreEqual(Tokens.Identifier, lexer.NextToken().Kind);
Assert.AreEqual(Tokens.XmlCloseTag, lexer.NextToken().Kind);
// </div>
Assert.AreEqual(Tokens.XmlOpenEndTag, lexer.NextToken().Kind);
Assert.AreEqual(Tokens.Identifier, lexer.NextToken().Kind);
Assert.AreEqual(Tokens.XmlCloseTag, lexer.NextToken().Kind);
CheckFoot(lexer);
}
[Test]
public void XmlLiteralsExample1()
{
VBLexer lexer = GenerateLexer(new StringReader(TestStatement("Dim xml = <menu>\n" +
" <course name=\"appetizer\">\n" +
" <dish>Shrimp Cocktail</dish>\n" +
" <dish>Escargot</dish>\n" +
" </course>\n" +
" <course name=\"main\">\n" +
" <dish>Filet Mignon</dish>\n" +
" <dish>Garlic Potatoes</dish>\n" +
" <dish>Broccoli</dish>\n" +
" </course>\n" +
" <course name=\"dessert\">\n" +
" <dish>Chocolate Cheesecake</dish>\n" +
" </course>\n" +
" </menu>")));
CheckHead(lexer);
CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.Assign,
// <menu>
Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag,
// whitespaces
Tokens.XmlContent,
// <course name=\"appetizer\">
Tokens.XmlOpenTag, Tokens.Identifier, Tokens.Identifier, Tokens.Assign, Tokens.LiteralString, Tokens.XmlCloseTag,
// whitespaces
Tokens.XmlContent,
// <dish>Shrimp Cocktail</dish>
Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag,
// whitespaces
Tokens.XmlContent,
// <dish>Escargot</dish>
Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag,
// whitespaces
Tokens.XmlContent,
// </course>
Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag,
// whitespaces
Tokens.XmlContent,
// <course name=\"main\">
Tokens.XmlOpenTag, Tokens.Identifier, Tokens.Identifier, Tokens.Assign, Tokens.LiteralString, Tokens.XmlCloseTag,
// whitespaces
Tokens.XmlContent,
// <dish>Filet Mignon</dish>
Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag,
// whitespaces
Tokens.XmlContent,
// <dish>Garlic Potatoes</dish>
Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag,
// whitespaces
Tokens.XmlContent,
// <dish>Broccoli</dish>
Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag,
// whitespaces
Tokens.XmlContent,
// </course>
Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag,
// whitespaces
Tokens.XmlContent,
// <course name=\"dessert\">
Tokens.XmlOpenTag, Tokens.Identifier, Tokens.Identifier, Tokens.Assign, Tokens.LiteralString, Tokens.XmlCloseTag,
// whitespaces
Tokens.XmlContent,
// <dish>Chocolate Cheesecake</dish>
Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag,
// whitespaces
Tokens.XmlContent,
// </course>
Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag,
// whitespaces
Tokens.XmlContent,
// </menu>
Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag
);
CheckFoot(lexer);
}
[Test]
public void SimpleXmlWithComments()
{
VBLexer lexer = GenerateLexer(new StringReader(TestStatement(@"Dim x = <?xml version=""1.0""?> <!-- Test file -->
<Test>
<!-- Test data -->
<Data />
</Test>
<!-- eof -->
<!-- hey, wait! -->
<?target some data?>")));
CheckHead(lexer);
CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.Assign,
Tokens.XmlProcessingInstruction, Tokens.XmlContent, Tokens.XmlComment, Tokens.XmlContent, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag,
Tokens.XmlContent, Tokens.XmlComment, Tokens.XmlContent, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement,
Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlComment, Tokens.XmlComment, Tokens.XmlProcessingInstruction);
CheckFoot(lexer);
}
[Test]
public void SimpleEmptyTag()
{
VBLexer lexer = GenerateLexer(new StringReader(TestStatement("Dim x = <Test />")));
CheckHead(lexer);
CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.Assign,
Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement);
CheckFoot(lexer);
}
[Test]
public void SimpleTag()
{
VBLexer lexer = GenerateLexer(new StringReader(TestStatement("Dim x = <Test></Test>")));
CheckHead(lexer);
CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.XmlOpenTag,
Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlOpenEndTag,
Tokens.Identifier, Tokens.XmlCloseTag);
CheckFoot(lexer);
}
[Test]
public void XmlImport()
{
string code = @"Imports System
Imports System.Linq
Imports <xmlns='http://icsharpcode.net/sharpdevelop/avalonedit'>
Imports <xmlns:h='http://www.w3.org/TR/html4/'>
Class TestClass
Sub TestSub()
Dim xml = <h:table>
<h:tr>
<h:td>1. Cell</h:td>
</h:tr>
</h:table>
End Sub
End Class";
VBLexer lexer = GenerateLexer(new StringReader(code));
CheckTokens(lexer, Tokens.Imports, Tokens.Identifier, Tokens.EOL,
Tokens.Imports, Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.EOL,
Tokens.Imports, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.Assign, Tokens.LiteralString, Tokens.XmlCloseTag, Tokens.EOL,
Tokens.Imports, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.Assign, Tokens.LiteralString, Tokens.XmlCloseTag, Tokens.EOL,
Tokens.Class, Tokens.Identifier, Tokens.EOL, Tokens.Sub, Tokens.Identifier, Tokens.OpenParenthesis, Tokens.CloseParenthesis, Tokens.EOL,
Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag,
Tokens.XmlContent, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag,
Tokens.XmlContent, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag,
Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag,
Tokens.EOL, Tokens.End, Tokens.Sub, Tokens.EOL, Tokens.End, Tokens.Class
);
}
[Test]
public void CDataSection()
{
string xml = @"Dim xml = <template>
<name>test</name>
<language>VB</languge>
<file language='XAML'>
<![CDATA[<Window x:Class='DefaultNamespace.Window1'
xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
Title='DefaultNamespace' Height='300' Width='300'>
<Grid>
</Grid>
</Window>]]>
</file>
<file language='CSharp'>
<![CDATA[using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
namespace DefaultNamespace
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
}
}]]>
</file>
</template>
";
VBLexer lexer = GenerateLexer(new StringReader(TestStatement(xml)));
CheckHead(lexer);
CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.Assign, // 2
Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, // 6
Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, // 10
Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, // 14
Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, // 18
Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, // 22
Tokens.XmlOpenTag, Tokens.Identifier, Tokens.Identifier, Tokens.Assign, Tokens.LiteralString, Tokens.XmlCloseTag, // 28
Tokens.XmlContent, Tokens.XmlCData, Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, // 34
Tokens.XmlContent, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.Identifier, Tokens.Assign, Tokens.LiteralString, Tokens.XmlCloseTag,
Tokens.XmlContent, Tokens.XmlCData, Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag,
Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag
);
CheckFoot(lexer);
}
[Test]
public void InlineVB()
{
string code = @"Dim xml = <?xml version='1.0'?>
<menu>
<course name=""appetizer"">
<%= From m In menu _
Where m.Course = ""appetizer"" _
Select <dish><%= m.Food %></dish> _
%>
</course>
<course name=""main"">
<%= From m In menu _
Where m.Course = ""main"" _
Select <dish><%= m.Food %></dish> _
%>
</course>
<course name=""dessert"">
<%= From m In menu _
Where m.Course = ""dessert"" _
Select <dish><%= m.Food %></dish> _
%>
</course>
</menu>";
VBLexer lexer = GenerateLexer(new StringReader(TestStatement(code)));
CheckHead(lexer);
CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.XmlProcessingInstruction, Tokens.XmlContent,
Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlOpenTag, Tokens.Identifier,
Tokens.Identifier, Tokens.Assign, Tokens.LiteralString, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlStartInlineVB,
Tokens.From, Tokens.Identifier, Tokens.In, Tokens.Identifier, Tokens.Where, Tokens.Identifier, Tokens.Dot,
Tokens.Identifier, Tokens.Assign, Tokens.LiteralString, Tokens.Select, Tokens.XmlOpenTag, Tokens.Identifier,
Tokens.XmlCloseTag, Tokens.XmlStartInlineVB, Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.XmlEndInlineVB,
Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlEndInlineVB, Tokens.XmlContent, Tokens.XmlOpenEndTag,
Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlOpenTag, Tokens.Identifier,
Tokens.Identifier, Tokens.Assign, Tokens.LiteralString, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlStartInlineVB,
Tokens.From, Tokens.Identifier, Tokens.In, Tokens.Identifier, Tokens.Where, Tokens.Identifier, Tokens.Dot,
Tokens.Identifier, Tokens.Assign, Tokens.LiteralString, Tokens.Select, Tokens.XmlOpenTag, Tokens.Identifier,
Tokens.XmlCloseTag, Tokens.XmlStartInlineVB, Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.XmlEndInlineVB,
Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlEndInlineVB, Tokens.XmlContent, Tokens.XmlOpenEndTag,
Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlOpenTag, Tokens.Identifier,
Tokens.Identifier, Tokens.Assign, Tokens.LiteralString, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlStartInlineVB,
Tokens.From, Tokens.Identifier, Tokens.In, Tokens.Identifier, Tokens.Where, Tokens.Identifier, Tokens.Dot,
Tokens.Identifier, Tokens.Assign, Tokens.LiteralString, Tokens.Select, Tokens.XmlOpenTag, Tokens.Identifier,
Tokens.XmlCloseTag, Tokens.XmlStartInlineVB, Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.XmlEndInlineVB,
Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlEndInlineVB, Tokens.XmlContent, Tokens.XmlOpenEndTag,
Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag
);
CheckFoot(lexer);
}
[Test]
public void InlineVB2()
{
string code = @"Dim contact As XElement = <<%=elementName %>>
<name><%= MyName %></name>
</>";
VBLexer lexer = GenerateLexer(new StringReader(TestStatement(code)));
CheckHead(lexer);
CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.As, Tokens.Identifier, Tokens.Assign, Tokens.XmlOpenTag,
Tokens.XmlStartInlineVB, Tokens.Identifier, Tokens.XmlEndInlineVB, Tokens.XmlCloseTag, Tokens.XmlContent,
Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlStartInlineVB, Tokens.Identifier, Tokens.XmlEndInlineVB,
Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.XmlCloseTag);
CheckFoot(lexer);
}
[Test]
public void XmlAccessOperators()
{
string code = @"Dim childAxis = xml.<menu>.<course>
Dim course3 = xml...<course>(2)
Dim childAxis = xml...<course>
For Each item In childAxis
Console.WriteLine(item.@name)
Next";
VBLexer lexer = GenerateLexer(new StringReader(TestStatement(code)));
CheckHead(lexer);
CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.Identifier, Tokens.Dot, Tokens.XmlOpenTag,
Tokens.Identifier, Tokens.XmlCloseTag, Tokens.Dot, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag,
Tokens.EOL, Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.Identifier, Tokens.TripleDot, Tokens.XmlOpenTag,
Tokens.Identifier, Tokens.XmlCloseTag, Tokens.OpenParenthesis, Tokens.LiteralInteger, Tokens.CloseParenthesis,
Tokens.EOL, Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.Identifier, Tokens.TripleDot, Tokens.XmlOpenTag,
Tokens.Identifier, Tokens.XmlCloseTag, Tokens.EOL, Tokens.For, Tokens.Each, Tokens.Identifier, Tokens.In, Tokens.Identifier, Tokens.EOL,
Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.OpenParenthesis, Tokens.Identifier, Tokens.DotAt, Tokens.Identifier, Tokens.CloseParenthesis, Tokens.EOL,
Tokens.Next);
CheckFoot(lexer);
}
[Test]
public void GetXmlNamespace()
{
VBLexer lexer = GenerateLexer(new StringReader(TestStatement("Dim name = GetXmlNamespace(x)")));
CheckHead(lexer);
CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.Assign,
Tokens.GetXmlNamespace, Tokens.OpenParenthesis, Tokens.Identifier, Tokens.CloseParenthesis);
CheckFoot(lexer);
}
[Test]
public void GetXmlNamespace2()
{
VBLexer lexer = GenerateLexer(new StringReader(TestStatement("Dim name = GetXmlNamespace(db-name)")));
CheckHead(lexer);
CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.Assign,
Tokens.GetXmlNamespace, Tokens.OpenParenthesis, Tokens.Identifier, Tokens.CloseParenthesis);
CheckFoot(lexer);
}
[Test]
public void XmlInSelect()
{
VBLexer lexer = GenerateLexer(new StringReader(TestStatement("Dim data = From x In list Select <test>x</test>")));
CheckHead(lexer);
CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.Assign,
Tokens.From, Tokens.Identifier, Tokens.In, Tokens.Identifier, Tokens.Select,
Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlOpenEndTag,
Tokens.Identifier, Tokens.XmlCloseTag);
CheckFoot(lexer);
}
[Test]
public void IfExpressionTest()
{
VBLexer lexer = GenerateLexer(new StringReader(TestStatement("Dim name = If(a <> 2, 4, 8)")));
CheckHead(lexer);
CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.Assign,
Tokens.If, Tokens.OpenParenthesis, Tokens.Identifier, Tokens.NotEqual, Tokens.LiteralInteger,
Tokens.Comma, Tokens.LiteralInteger, Tokens.Comma, Tokens.LiteralInteger, Tokens.CloseParenthesis);
CheckFoot(lexer);
}
[Test]
public void IfStatementTest()
{
VBLexer lexer = GenerateLexer(new StringReader(TestStatement("If a <> 2 Then Return")));
CheckHead(lexer);
CheckTokens(lexer, Tokens.If, Tokens.Identifier, Tokens.NotEqual, Tokens.LiteralInteger,
Tokens.Then, Tokens.Return);
CheckFoot(lexer);
}
[Test]
public void Bug1()
{
VBLexer lexer = GenerateLexer(new StringReader(TestStatement(@"Dim xml = <!-- test -->")));
CheckHead(lexer);
CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.XmlComment);
CheckFoot(lexer);
}
[Test]
public void Bug2()
{
VBLexer lexer = GenerateLexer(new StringReader(TestStatement(@"Dim xml = <?xml?><Data /><!-- test -->")));
CheckHead(lexer);
CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.Assign,
Tokens.XmlProcessingInstruction, Tokens.XmlOpenTag, Tokens.Identifier,
Tokens.XmlCloseTagEmptyElement, Tokens.XmlComment);
CheckFoot(lexer);
}
[Test]
public void Bug3()
{
VBLexer lexer = GenerateLexerForSnippet(new StringReader("New String() {}"), SnippetType.Expression);
CheckTokens(lexer, Tokens.New, Tokens.String, Tokens.OpenParenthesis,
Tokens.CloseParenthesis, Tokens.OpenCurlyBrace, Tokens.CloseCurlyBrace);
}
[Test]
public void Bug4()
{
VBLexer lexer = GenerateLexer(new StringReader(TestStatement(@"Dim x = From kvp As KeyValuePair(Of String, DataGridViewCellStyle) In styleCache.CellStyleCache _
Select includeStyle(kvp.Key, kvp.Value)")));
CheckHead(lexer);
CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.From, Tokens.Identifier, Tokens.As, Tokens.Identifier,
Tokens.OpenParenthesis, Tokens.Of, Tokens.String, Tokens.Comma, Tokens.Identifier, Tokens.CloseParenthesis,
Tokens.In, Tokens.Identifier, Tokens.Dot, Tokens.Identifier,
Tokens.Select, Tokens.Identifier, Tokens.OpenParenthesis, Tokens.Identifier, Tokens.Dot, Tokens.Key, Tokens.Comma,
Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.CloseParenthesis);
CheckFoot(lexer);
}
[Test]
public void LessThanCheck()
{
VBLexer lexer = GenerateLexer(new StringReader(TestStatement(@"Dim xml = <!-- test --><Data")));
CheckHead(lexer);
CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.Assign,
Tokens.XmlComment, Tokens.LessThan, Tokens.Identifier);
CheckFoot(lexer);
}
#endregion
#region Context Tests
[Test]
public void MethodInvocation()
{
VBLexer lexer = GenerateLexer(new StringReader(TestStatement("DoSomething(<Test />, True)")));
CheckHead(lexer);
CheckTokens(lexer, Tokens.Identifier, Tokens.OpenParenthesis, Tokens.XmlOpenTag,
Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.Comma, Tokens.True,
Tokens.CloseParenthesis);
CheckFoot(lexer);
}
[Test]
public void AddHandlerStatement()
{
VBLexer lexer = GenerateLexer(new StringReader(TestStatement("AddHandler <Test />, True")));
CheckHead(lexer);
CheckTokens(lexer, Tokens.AddHandler, Tokens.XmlOpenTag,
Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.Comma, Tokens.True);
CheckFoot(lexer);
}
[Test]
public void AddHandlerStatement2()
{
VBLexer lexer = GenerateLexer(new StringReader(TestStatement("AddHandler <x />, <y />")));
CheckHead(lexer);
CheckTokens(lexer, Tokens.AddHandler, Tokens.XmlOpenTag,
Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.Comma, Tokens.XmlOpenTag,
Tokens.Identifier, Tokens.XmlCloseTagEmptyElement);
CheckFoot(lexer);
}
[Test]
public void RemoveHandlerStatement()
{
VBLexer lexer = GenerateLexer(new StringReader(TestStatement("RemoveHandler <x />, <Data>5</Data>")));
CheckHead(lexer);
CheckTokens(lexer, Tokens.RemoveHandler, Tokens.XmlOpenTag,
Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.Comma,
Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent,
Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag
);
CheckFoot(lexer);
}
[Test]
public void ErrorHandlingStatement()
{
VBLexer lexer = GenerateLexer(new StringReader(TestStatement("On Error Resume Next\n" +
"On Error GoTo -1\n" +
"On Error GoTo 0\n" +
"On Error GoTo Test\n" +
"Error 5\n" +
"Error <Test />\n" +
"Resume Next\n" +
"Resume Label\n" +
"Resume 4")));
CheckHead(lexer);
CheckTokens(lexer, Tokens.On, Tokens.Error, Tokens.Resume, Tokens.Next, Tokens.EOL,
Tokens.On, Tokens.Error, Tokens.GoTo, Tokens.Minus, Tokens.LiteralInteger, Tokens.EOL,
Tokens.On, Tokens.Error, Tokens.GoTo, Tokens.LiteralInteger, Tokens.EOL,
Tokens.On, Tokens.Error, Tokens.GoTo, Tokens.Identifier, Tokens.EOL,
Tokens.Error, Tokens.LiteralInteger, Tokens.EOL,
Tokens.Error, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.EOL,
Tokens.Resume, Tokens.Next, Tokens.EOL,
Tokens.Resume, Tokens.Identifier, Tokens.EOL,
Tokens.Resume, Tokens.LiteralInteger
);
CheckFoot(lexer);
}
[Test]
public void ForLoopStatement()
{
string statement = @"For <Test /> = <Test /> To <Test /> Step <Test />
Next <Test />, <Test />
For Each <Test /> In <Test />
Next <Test />";
VBLexer lexer = GenerateLexer(new StringReader(TestStatement(statement)));
CheckHead(lexer);
CheckTokens(lexer, Tokens.For, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement,
Tokens.Assign, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement,
Tokens.To, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement,
Tokens.Step, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.EOL,
Tokens.Next, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.Comma,
Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.EOL,
Tokens.For, Tokens.Each, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement,
Tokens.In, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.EOL,
Tokens.Next, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement
);
CheckFoot(lexer);
}
[Test]
public void WhileLoopStatement()
{
string statement = @"While <Test />
End While";
VBLexer lexer = GenerateLexer(new StringReader(TestStatement(statement)));
CheckHead(lexer);
CheckTokens(lexer, Tokens.While, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.EOL,
Tokens.End, Tokens.While
);
CheckFoot(lexer);
}
[Test]
public void WhileLoopStatement2()
{
string statement = @"Do While <Test />
Loop";
VBLexer lexer = GenerateLexer(new StringReader(TestStatement(statement)));
CheckHead(lexer);
CheckTokens(lexer, Tokens.Do, Tokens.While, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.EOL,
Tokens.Loop
);
CheckFoot(lexer);
}
[Test]
public void WhileLoopStatement3()
{
string statement = @"Do
Loop While <Test />";
VBLexer lexer = GenerateLexer(new StringReader(TestStatement(statement)));
CheckHead(lexer);
CheckTokens(lexer, Tokens.Do, Tokens.EOL,
Tokens.Loop, Tokens.While, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement
);
CheckFoot(lexer);
}
[Test]
public void UntilLoopStatement()
{
string statement = @"Do Until <Test />
Loop";
VBLexer lexer = GenerateLexer(new StringReader(TestStatement(statement)));
CheckHead(lexer);
CheckTokens(lexer, Tokens.Do, Tokens.Until, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.EOL,
Tokens.Loop
);
CheckFoot(lexer);
}
[Test]
public void UntilLoopStatement2()
{
string statement = @"Do
Loop Until <Test />";
VBLexer lexer = GenerateLexer(new StringReader(TestStatement(statement)));
CheckHead(lexer);
CheckTokens(lexer, Tokens.Do, Tokens.EOL,
Tokens.Loop, Tokens.Until, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement
);
CheckFoot(lexer);
}
[Test]
public void IfStatementLarge()
{
string statement = @"If <Test /> Then
Else If <Test /> Then
ElseIf <Test></Test> Then
Else
End If";
VBLexer lexer = GenerateLexer(new StringReader(TestStatement(statement)));
CheckHead(lexer);
CheckTokens(lexer, Tokens.If, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.Then, Tokens.EOL,
Tokens.Else, Tokens.If, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.Then, Tokens.EOL,
Tokens.ElseIf, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.Then, Tokens.EOL,
Tokens.Else, Tokens.EOL,
Tokens.End, Tokens.If
);
CheckFoot(lexer);
}
[Test]
public void SelectStatement()
{
string statement = @"Select Case <Test />
Case <Test />, <Test />
Case Else
End Select";
VBLexer lexer = GenerateLexer(new StringReader(TestStatement(statement)));
CheckHead(lexer);
CheckTokens(lexer, Tokens.Select, Tokens.Case, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.EOL,
Tokens.Case, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.Comma,
Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.EOL,
Tokens.Case, Tokens.Else, Tokens.EOL,
Tokens.End, Tokens.Select
);
CheckFoot(lexer);
}
[Test]
public void TryStatement()
{
string statement = @"Try
Catch x
Catch y As Exception
Catch When <Test />
Finally
End Try";
VBLexer lexer = GenerateLexer(new StringReader(TestStatement(statement)));
CheckHead(lexer);
CheckTokens(lexer, Tokens.Try, Tokens.EOL,
Tokens.Catch, Tokens.Identifier, Tokens.EOL,
Tokens.Catch, Tokens.Identifier, Tokens.As, Tokens.Identifier, Tokens.EOL,
Tokens.Catch, Tokens.When, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.EOL,
Tokens.Finally, Tokens.EOL,
Tokens.End, Tokens.Try
);
CheckFoot(lexer);
}
[Test]
public void ThrowStatement()
{
VBLexer lexer = GenerateLexer(new StringReader(TestStatement("Throw <Test />")));
CheckHead(lexer);
CheckTokens(lexer, Tokens.Throw, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement);
CheckFoot(lexer);
}
[Test]
public void BranchStatements()
{
string statement = @"GoTo 5
GoTo LabelName
Exit Do
Exit For
Exit While
Exit Select
Exit Sub
Exit Function
Exit Property
Exit Try
Continue Do
Continue For
Continue While
Stop
End
Return
Return 5
Return <Test />";
VBLexer lexer = GenerateLexer(new StringReader(TestStatement(statement)));
CheckHead(lexer);
CheckTokens(lexer, Tokens.GoTo, Tokens.LiteralInteger, Tokens.EOL,
Tokens.GoTo, Tokens.Identifier, Tokens.EOL,
Tokens.Exit, Tokens.Do, Tokens.EOL,
Tokens.Exit, Tokens.For, Tokens.EOL,
Tokens.Exit, Tokens.While, Tokens.EOL,
Tokens.Exit, Tokens.Select, Tokens.EOL,
Tokens.Exit, Tokens.Sub, Tokens.EOL,
Tokens.Exit, Tokens.Function, Tokens.EOL,
Tokens.Exit, Tokens.Property, Tokens.EOL,
Tokens.Exit, Tokens.Try, Tokens.EOL,
Tokens.Continue, Tokens.Do, Tokens.EOL,
Tokens.Continue, Tokens.For, Tokens.EOL,
Tokens.Continue, Tokens.While, Tokens.EOL,
Tokens.Stop, Tokens.EOL,
Tokens.End, Tokens.EOL,
Tokens.Return, Tokens.EOL,
Tokens.Return, Tokens.LiteralInteger, Tokens.EOL,
Tokens.Return, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement
);
CheckFoot(lexer);
}
[Test]
public void ArrayHandlingStatements()
{
string statement = @"Erase <Test />
Erase <Test />, <Test />
ReDim Preserve <Test />";
VBLexer lexer = GenerateLexer(new StringReader(TestStatement(statement)));
CheckHead(lexer);
CheckTokens(lexer, Tokens.Erase, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.EOL,
Tokens.Erase, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.Comma,
Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.EOL,
Tokens.ReDim, Tokens.Preserve, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement
);
CheckFoot(lexer);
}
[Test]
public void UsingStatement()
{
string statement = @"Using <Test />
End Using";
VBLexer lexer = GenerateLexer(new StringReader(TestStatement(statement)));
CheckHead(lexer);
CheckTokens(lexer, Tokens.Using, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.EOL,
Tokens.End, Tokens.Using
);
CheckFoot(lexer);
}
[Test]
public void NewExpressionWithObjectInitializer()
{
string code = @"New Common.ComboBoxItem With {.Item = _
Localizer.GetString(""Month"" & initParameters.SelectedDate.FirstDayOfPreviousMonth.Month) & "" "" &
initParameters.SelectedDate.FirstDayOfPreviousMonth.Year, .Value = New Date(2010, initParameters.SelectedDate.FirstDayOfPreviousMonth.Month, 1)}";
VBLexer lexer = GenerateLexerForSnippet(new StringReader(code), SnippetType.Expression);
CheckTokens(lexer, Tokens.New, Tokens.Identifier, Tokens.Dot, Tokens.Identifier,
Tokens.With, Tokens.OpenCurlyBrace, Tokens.Dot, Tokens.Identifier, Tokens.Assign,
Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.OpenParenthesis, Tokens.LiteralString,
Tokens.ConcatString, Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.Dot,
Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.CloseParenthesis, Tokens.ConcatString,
Tokens.LiteralString, Tokens.ConcatString, Tokens.Identifier, Tokens.Dot, Tokens.Identifier,
Tokens.Dot, Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.Comma, Tokens.Dot,
Tokens.Identifier, Tokens.Assign, Tokens.New, Tokens.Date, Tokens.OpenParenthesis, Tokens.LiteralInteger,
Tokens.Comma, Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.Dot,
Tokens.Identifier, Tokens.Comma, Tokens.LiteralInteger, Tokens.CloseParenthesis, Tokens.CloseCurlyBrace);
}
#endregion
#region Helpers
VBLexer GenerateLexer(StringReader sr)
{
return new VBLexer(sr);
}
VBLexer GenerateLexerForSnippet(StringReader sr, SnippetType type)
{
var lexer = new VBLexer(sr);
lexer.SetInitialContext(type);
return lexer;
}
string TestStatement(string stmt)
{
return "Class Test\n" +
"Sub A\n" +
stmt + "\n" +
"End Sub\n" +
"End Class";
}
void CheckFoot(VBLexer lexer)
{
CheckTokens(lexer, Tokens.EOL, Tokens.End, Tokens.Sub, Tokens.EOL, Tokens.End, Tokens.Class);
}
void CheckHead(VBLexer lexer)
{
CheckTokens(lexer, Tokens.Class, Tokens.Identifier, Tokens.EOL,
Tokens.Sub, Tokens.Identifier, Tokens.EOL);
}
void CheckTokens(VBLexer lexer, params int[] tokens)
{
for (int i = 0; i < tokens.Length; i++) {
int token = tokens[i];
Token t = lexer.NextToken();
int next = t.Kind;
Assert.IsEmpty(lexer.Errors.ErrorOutput);
Assert.AreEqual(token, next, "{2} of {3}: expected: \"{0}\", was: \"{1}\"; at {4}", Tokens.GetTokenString(token), Tokens.GetTokenString(next), i + 1, tokens.Length, t.Location);
}
}
#endregion
}
}

22
NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Output/CodeDOM/CodeDOMParenthesizedExpressionTest.cs

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.CodeDom;
using ICSharpCode.NRefactory.VB.Ast;
using ICSharpCode.NRefactory.VB.Visitors;
using NUnit.Framework;
namespace ICSharpCode.NRefactory.VB.Tests.Output.CodeDom.Tests
{
[TestFixture]
public class CodeDOMParenthesizedExpressionTest
{
[Test]
public void TestParenthesizedExpression()
{
object output = new ParenthesizedExpression(new PrimitiveExpression(5, "5")).AcceptVisitor(new CodeDomVisitor(), null);
Assert.IsTrue(output is CodePrimitiveExpression);
}
}
}

23
NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Output/CodeDOM/CodeDOMPrimitiveExpressionTest.cs

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.CodeDom;
using ICSharpCode.NRefactory.VB.Ast;
using ICSharpCode.NRefactory.VB.Visitors;
using NUnit.Framework;
namespace ICSharpCode.NRefactory.VB.Tests.Output.CodeDom.Tests
{
[TestFixture]
public class CodeDOMPrimitiveExpressionsTests
{
[Test]
public void TestPrimitiveExpression()
{
object output = new PrimitiveExpression(5, "5").AcceptVisitor(new CodeDomVisitor(), null);
Assert.IsTrue(output is CodePrimitiveExpression);
Assert.AreEqual(((CodePrimitiveExpression)output).Value, 5);
}
}
}

30
NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Output/CodeDOM/CodeDOMTypeReferenceTest.cs

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.CodeDom;
using System.Collections.Generic;
using ICSharpCode.NRefactory.VB.Ast;
using ICSharpCode.NRefactory.VB.Visitors;
using NUnit.Framework;
namespace ICSharpCode.NRefactory.VB.Tests.Output.CodeDom.Tests
{
[TestFixture]
public class CodeDOMTypeReferenceTest
{
[TestAttribute]
public void InnerClassTypeReferencTest()
{
InnerClassTypeReference ictr = new InnerClassTypeReference(
new TypeReference("OuterClass", new List<TypeReference> { new TypeReference("String") }),
"InnerClass",
new List<TypeReference> { new TypeReference("Int32"), new TypeReference("Int64") });
Assert.AreEqual("OuterClass<String>+InnerClass<Int32,Int64>", 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);
}
}
}

59
NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Output/CodeDOM/InvocationExpressionTest.cs

@ -0,0 +1,59 @@ @@ -0,0 +1,59 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.CodeDom;
using System.Collections.Generic;
using ICSharpCode.NRefactory.VB.Ast;
using ICSharpCode.NRefactory.VB.Visitors;
using NUnit.Framework;
namespace ICSharpCode.NRefactory.VB.Tests.Output.CodeDom.Tests
{
[TestFixture]
public class InvocationExpressionsTests
{
[Test]
public void IdentifierOnlyInvocation()
{
// InitializeComponents();
SimpleNameExpression identifier = new SimpleNameExpression("InitializeComponents");
InvocationExpression invocation = new InvocationExpression(identifier, new List<Expression>());
object output = invocation.AcceptVisitor(new CodeDomVisitor(), null);
Assert.IsTrue(output is CodeMethodInvokeExpression);
CodeMethodInvokeExpression mie = (CodeMethodInvokeExpression)output;
Assert.AreEqual("InitializeComponents", mie.Method.MethodName);
Assert.IsTrue(mie.Method.TargetObject is CodeThisReferenceExpression);
}
[Test]
public void MethodOnThisReferenceInvocation()
{
// InitializeComponents();
MemberReferenceExpression field = new MemberReferenceExpression(new ThisReferenceExpression(), "InitializeComponents");
InvocationExpression invocation = new InvocationExpression(field, new List<Expression>());
object output = invocation.AcceptVisitor(new CodeDomVisitor(), null);
Assert.IsTrue(output is CodeMethodInvokeExpression);
CodeMethodInvokeExpression mie = (CodeMethodInvokeExpression)output;
Assert.AreEqual("InitializeComponents", mie.Method.MethodName);
Assert.IsTrue(mie.Method.TargetObject is CodeThisReferenceExpression);
}
[Test]
public void InvocationOfStaticMethod()
{
// System.Drawing.Color.FromArgb();
MemberReferenceExpression field = new MemberReferenceExpression(new SimpleNameExpression("System"), "Drawing");
field = new MemberReferenceExpression(field, "Color");
field = new MemberReferenceExpression(field, "FromArgb");
InvocationExpression invocation = new InvocationExpression(field, new List<Expression>());
object output = invocation.AcceptVisitor(new CodeDomVisitor(), null);
Assert.IsTrue(output is CodeMethodInvokeExpression);
CodeMethodInvokeExpression mie = (CodeMethodInvokeExpression)output;
Assert.AreEqual("FromArgb", mie.Method.MethodName);
Assert.IsTrue(mie.Method.TargetObject is CodeTypeReferenceExpression);
Assert.AreEqual("System.Drawing.Color", (mie.Method.TargetObject as CodeTypeReferenceExpression).Type.BaseType);
}
}
}

79
NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Output/SpecialOutputVisitorTest.cs

@ -0,0 +1,79 @@ @@ -0,0 +1,79 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.IO;
using ICSharpCode.NRefactory.VB.Ast;
using ICSharpCode.NRefactory.VB.Parser;
using ICSharpCode.NRefactory.VB.PrettyPrinter;
using NUnit.Framework;
namespace ICSharpCode.NRefactory.VB.Tests.PrettyPrinter
{
[TestFixture]
public class SpecialOutputVisitorTest
{
void TestProgram(string program)
{
VBParser parser = ParserFactory.CreateParser(new StringReader(program));
parser.Parse();
Assert.AreEqual("", parser.Errors.ErrorOutput);
VBNetOutputVisitor outputVisitor = new VBNetOutputVisitor();
outputVisitor.Options.IndentationChar = ' ';
outputVisitor.Options.TabSize = 2;
outputVisitor.Options.IndentSize = 2;
using (SpecialNodesInserter.Install(parser.Lexer.SpecialTracker.RetrieveSpecials(),
outputVisitor)) {
outputVisitor.VisitCompilationUnit(parser.CompilationUnit, null);
}
Assert.AreEqual("", outputVisitor.Errors.ErrorOutput);
Assert.AreEqual(program.Replace("\r", ""), outputVisitor.Text.TrimEnd().Replace("\r", ""));
parser.Dispose();
}
[Test]
public void Enum()
{
TestProgram("Enum Test\n" +
" ' a\n" +
" m1\n" +
" ' b\n" +
" m2\n" +
" ' c\n" +
"End Enum\n" +
"' d");
}
[Test]
public void CommentsInsideMethod()
{
TestProgram(@"Public Class Class1
Private Function test(l As Integer, lvw As Integer) As Boolean
' Begin
Dim i As Integer = 1
Return False
' End of method
End Function
End Class");
}
[Test]
public void BlankLines()
{
TestProgram("Imports System\n" +
"\n" +
"Imports System.IO");
TestProgram("Imports System\n" +
"\n" +
"\n" +
"Imports System.IO");
TestProgram("\n" +
"' Some comment\n" +
"\n" +
"Imports System.IO");
}
}
}

670
NRefactory.VB/ICSharpCode.NRefactory.VB.Tests/Output/VBNet/VBNetOutputTest.cs

@ -0,0 +1,670 @@ @@ -0,0 +1,670 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.IO;
using ICSharpCode.NRefactory.VB.Ast;
using ICSharpCode.NRefactory.VB.Parser;
using ICSharpCode.NRefactory.VB.PrettyPrinter;
using ICSharpCode.NRefactory.VB.Visitors;
using NUnit.Framework;
namespace ICSharpCode.NRefactory.VB.Tests.PrettyPrinter
{
[TestFixture]
public class VBNetOutputTest
{
void TestProgram(string program)
{
VBParser parser = ParserFactory.CreateParser(new StringReader(program));
parser.Parse();
Assert.AreEqual("", parser.Errors.ErrorOutput);
VBNetOutputVisitor outputVisitor = new VBNetOutputVisitor();
outputVisitor.Options.OutputByValModifier = true;
outputVisitor.VisitCompilationUnit(parser.CompilationUnit, null);
Assert.AreEqual("", outputVisitor.Errors.ErrorOutput);
Assert.AreEqual(StripWhitespace(program), StripWhitespace(outputVisitor.Text));
}
string StripWhitespace(string text)
{
text = text.Trim().Replace("\t", "").Replace("\r", "").Replace("\n", " ").Replace(" ", " ");
while (text.Contains(" ")) {
text = text.Replace(" ", " ");
}
return text;
}
void TestTypeMember(string program)
{
TestProgram("Class A\n" + program + "\nEnd Class");
}
void TestStatement(string statement)
{
TestTypeMember("Sub Method()\n" + statement + "\nEnd Sub");
}
void TestExpression(string expression)
{
VBParser parser = ParserFactory.CreateParser(new StringReader(expression));
Expression e = parser.ParseExpression();
Assert.AreEqual("", parser.Errors.ErrorOutput);
VBNetOutputVisitor outputVisitor = new VBNetOutputVisitor();
e.AcceptVisitor(outputVisitor, null);
Assert.AreEqual("", outputVisitor.Errors.ErrorOutput);
Assert.AreEqual(StripWhitespace(expression), StripWhitespace(outputVisitor.Text));
}
[Test]
public void Field()
{
TestTypeMember("Private a As Integer");
}
[Test]
public void Method()
{
TestTypeMember("Sub Method()\nEnd Sub");
}
[Test]
public void EnumWithBaseType()
{
TestProgram("Public Enum Foo As UShort\nEnd Enum");
}
[Test]
public void PartialModifier()
{
TestProgram("Public Partial Class Foo\nEnd Class");
}
[Test]
public void MustInheritClass()
{
TestProgram("Public MustInherit Class Foo\nEnd Class");
}
[Test]
public void GenericClassDefinition()
{
TestProgram("Public Class Foo(Of T As {IDisposable, ICloneable})\nEnd Class");
}
[Test]
public void GenericClassDefinitionWithBaseType()
{
TestProgram("Public Class Foo(Of T As IDisposable)\nInherits BaseType\nEnd Class");
}
[Test]
public void GenericMethodDefinition()
{
TestTypeMember("Public Sub Foo(Of T As {IDisposable, ICloneable})(ByVal arg As T)\nEnd Sub");
}
[Test]
public void ArrayRank()
{
TestStatement("Dim a As Object(,,)");
}
[Test]
public void ArrayInitialization()
{
TestStatement("Dim a As Object() = New Object(10) {}");
TestTypeMember("Private MultiDim As Integer(,) = {{1, 2}, {1, 3}}");
TestExpression("New Integer(, ) {{1, 1}, {1, 1}}");
TestTypeMember("Private _titles As String() = New String() {}");
}
[Test]
public void MethodCallWithOptionalArguments()
{
TestExpression("M(, )");
}
[Test]
public void IfStatement()
{
TestStatement("If a Then\n" +
"\tm1()\n" +
"ElseIf b Then\n" +
"\tm2()\n" +
"Else\n" +
"\tm3()\n" +
"End If");
}
[Test]
public void ForNextLoop()
{
TestStatement("For i = 0 To 10\n" +
"Next");
TestStatement("For i As Long = 10 To 0 Step -1\n" +
"Next");
}
[Test]
public void DoLoop()
{
TestStatement("Do\n" +
"Loop");
TestStatement("Do\n" +
"Loop While Not (i = 10)");
}
[Test]
public void SelectCase()
{
TestStatement(@"Select Case i
Case 0
Case 1 To 4
Case Else
End Select");
}
[Test]
public void UsingStatement()
{
TestStatement(@"Using nf As New Font(), nf2 As New List(Of Font)(), nf3 = Nothing
Bla(nf)
End Using");
}
[Test]
public void UntypedVariable()
{
TestStatement("Dim x = 0");
}
[Test]
public void UntypedField()
{
TestTypeMember("Dim x = 0");
}
[Test]
public void Assignment()
{
TestExpression("a = b");
}
[Test]
public void SpecialIdentifiers()
{
// Assembly, Ansi and Until are contextual keywords
// Custom is valid inside methods, but not valid for field names
TestExpression("Assembly = Ansi * [For] + Until - [Custom]");
}
[Test]
public void DictionaryAccess()
{
TestExpression("c!key");
}
[Test]
public void GenericMethodInvocation()
{
TestExpression("GenericMethod(Of T)(arg)");
}
[Test]
public void SpecialIdentifierName()
{
TestExpression("[Class]");
}
[Test]
public void GenericDelegate()
{
TestProgram("Public Delegate Function Predicate(Of T)(ByVal item As T) As String");
}
[Test]
public void Enum()
{
TestProgram("Enum MyTest\nRed\n Green\n Blue\nYellow\n End Enum");
}
[Test]
public void EnumWithInitializers()
{
TestProgram("Enum MyTest\nRed = 1\n Green = 2\n Blue = 4\n Yellow = 8\n End Enum");
}
[Test]
public void SyncLock()
{
TestStatement("SyncLock a\nWork()\nEnd SyncLock");
}
[Test]
public void Using()
{
TestStatement("Using a As New A()\na.Work()\nEnd Using");
}
[Test]
public void Cast()
{
TestExpression("CType(a, T)");
}
[Test]
public void DirectCast()
{
TestExpression("DirectCast(a, T)");
}
[Test]
public void TryCast()
{
TestExpression("TryCast(a, T)");
}
[Test]
public void PrimitiveCast()
{
TestExpression("CStr(a)");
}
[Test]
public void TypeOfIs()
{
TestExpression("TypeOf a Is String");
}
[Test]
public void PropertyWithAccessorAccessModifiers()
{
TestTypeMember("Public Property ExpectsValue() As Boolean\n" +
"\tPublic Get\n" +
"\tEnd Get\n" +
"\tProtected Set\n" +
"\tEnd Set\n" +
"End Property");
}
[Test]
public void AutoProperty()
{
TestTypeMember("Public Property Value()");
TestTypeMember("Public Property Value() As Integer");
TestTypeMember("Public Property Value() As Integer = 5");
TestTypeMember("Public Property Value() As New List()");
}
[Test]
public void AbstractProperty()
{
TestTypeMember("Public MustOverride Property ExpectsValue() As Boolean");
TestTypeMember("Public MustOverride ReadOnly Property ExpectsValue() As Boolean");
TestTypeMember("Public MustOverride WriteOnly Property ExpectsValue() As Boolean");
}
[Test]
public void AbstractMethod()
{
TestTypeMember("Public MustOverride Sub Run()");
TestTypeMember("Public MustOverride Function Run() As Boolean");
}
[Test]
public void InterfaceImplementingMethod()
{
TestTypeMember("Public Sub Run() Implements SomeInterface.Run\nEnd Sub");
TestTypeMember("Public Function Run() As Boolean Implements SomeInterface.Bla\nEnd Function");
}
[Test]
public void NamedAttributeArgument()
{
TestProgram("<Attribute(ArgName := \"value\")> _\n" +
"Class Test\n" +
"End Class");
}
[Test]
public void ReturnTypeAttribute()
{
TestTypeMember("Function A() As <Attribute> String\n" +
"End Function");
}
[Test]
public void AssemblyAttribute()
{
TestProgram("<Assembly: CLSCompliant>");
}
[Test]
public void ModuleAttribute()
{
TestProgram("<Module: SuppressMessageAttribute>");
}
[Test]
public void Interface()
{
TestProgram("Interface ITest\n" +
"Property GetterAndSetter() As Boolean\n" +
"ReadOnly Property GetterOnly() As Boolean\n" +
"WriteOnly Property SetterOnly() As Boolean\n" +
"Sub InterfaceMethod()\n" +
"Function InterfaceMethod2() As String\n" +
"End Interface");
}
[Test]
public void OnErrorStatement()
{
TestStatement("On Error Resume Next");
}
[Test]
public void OverloadedConversionOperators()
{
TestTypeMember("Public Shared Narrowing Operator CType(ByVal xmlNode As XmlNode) As TheBug\nEnd Operator");
TestTypeMember("Public Shared Widening Operator CType(ByVal bugNode As TheBug) As XmlNode\nEnd Operator");
}
[Test]
public void OverloadedTrueFalseOperators()
{
TestTypeMember("Public Shared Operator IsTrue(ByVal a As TheBug) As Boolean\nEnd Operator");
TestTypeMember("Public Shared Operator IsFalse(ByVal a As TheBug) As Boolean\nEnd Operator");
}
[Test]
public void OverloadedOperators()
{
TestTypeMember("Public Shared Operator +(ByVal bugNode As TheBug, ByVal bugNode2 As TheBug) As TheBug\nEnd Operator");
TestTypeMember("Public Shared Operator >>(ByVal bugNode As TheBug, ByVal b As Integer) As TheBug\nEnd Operator");
}
[Test]
public void AttributeOnParameter()
{
TestTypeMember("Sub Main(ByRef one As Integer, ByRef two As Integer, <Out> ByRef three As Integer)\nEnd Sub");
}
[Test]
public void FieldWithoutType()
{
TestTypeMember("Dim X");
}
[Test]
public void UsingStatementForExistingVariable()
{
TestStatement("Using obj\nEnd Using");
}
[Test]
public void ContinueFor()
{
TestStatement("Continue For");
}
[Test]
public void ForNextStatementWithFieldLoopVariable()
{
TestStatement("For Me.Field = 0 To 10\n" +
"Next Me.Field");
}
[Test]
public void WithStatement()
{
TestStatement("With Ejes\n" +
"\t.AddLine(New Point(Me.ClientSize.Width / 2, 0), (New Point(Me.ClientSize.Width / 2, Me.ClientSize.Height)))\n" +
"End With");
}
[Test]
public void NewConstraint()
{
TestProgram("Public Class Rational(Of T, O As {IRationalMath(Of T), New})\nEnd Class");
}
[Test]
public void StructConstraint()
{
TestProgram("Public Class Rational(Of T, O As {IRationalMath(Of T), Structure})\nEnd Class");
}
[Test]
public void ClassConstraint()
{
TestProgram("Public Class Rational(Of T, O As {IRationalMath(Of T), Class})\nEnd Class");
}
[Test]
public void Integer()
{
TestExpression("16");
}
[Test]
public void Double()
{
TestExpression("1.0");
}
[Test]
public void HexadecimalInteger()
{
TestExpression("&H10");
}
[Test]
public void HexadecimalMinusOne()
{
TestExpression("&Hffffffff");
}
[Test]
public void TypeCharacters()
{
TestExpression("347S");
TestExpression("347L");
TestExpression("347D");
TestExpression("347F");
TestExpression("347US");
TestExpression("347UI");
TestExpression("347UL");
TestExpression("\".\"C");
}
[Test]
public void AddressOf()
{
TestExpression("AddressOf Abc");
}
[Test]
public void ChainedConstructorCall()
{
TestExpression("MyBase.New()");
TestExpression("Me.New()");
TestExpression("MyClass.New()");
}
[Test]
public void NewMethodCall()
{
TestExpression("something.[New]()");
}
[Test]
public void ObjectInitializer()
{
TestExpression("New StringWriter() With { _\n" +
" .NewLine = Environment.NewLine, _\n" +
" .Encoding = Encoding.UTF8 _\n" +
"}");
}
[Test]
public void EventDefinition()
{
TestTypeMember("Public Event MyEvent(ByVal sender As Object)");
}
[Test]
public void Options()
{
TestProgram("Option Strict On\n" +
"Option Explicit On\n" +
"Option Infer On\n" +
"Option Compare Text");
}
[Test]
public void UntypedForeach()
{
TestStatement("For Each x In myGuidArray\nNext");
}
[Test]
public void MethodDefinitionWithOptionalParameter()
{
TestTypeMember("Sub M(Optional ByVal msg As String = Nothing, Optional ByRef output As String = Nothing)\nEnd Sub");
}
[Test]
public void Module()
{
TestProgram("Module Test\n" +
" Sub M()\n" +
" End Sub\n" +
"End Module");
}
[Test]
public void WithEvents()
{
TestTypeMember("Dim WithEvents a As Button");
}
[Test]
public void FriendWithEventsField()
{
TestTypeMember("Friend WithEvents Button1 As System.Windows.Forms.Button");
}
[Test]
public void SimpleFunctionLambda()
{
TestExpression("Function(x) x * x");
}
[Test]
public void SimpleFunctionLambdaWithType()
{
TestExpression("Function(x As Integer) x * x");
}
[Test]
public void SimpleSubLambdaWithType()
{
TestExpression("Sub(x As Integer) Console.WriteLine(x)");
}
[Test]
public void BlockSubLambdaWithType()
{
TestExpression("Sub(x As Integer)\n" +
" Console.WriteLine(x)\n" +
"End Sub");
}
[Test]
public void BlockFunctionLambdaWithType()
{
TestExpression("Function(x As Integer) As Integer\n" +
" If x < 2 Then\n" +
" Return x\n" +
" End If\n" +
" Return x * x\n" +
"End Function");
}
[Test]
public void XmlSimple()
{
TestExpression("<?xml?>\n" +
"<!-- test -->\n" +
"<Test>\n" +
" <A />\n" +
" <B test='a' <%= test %> />\n" +
"</Test>");
}
[Test]
public void XmlNested()
{
TestExpression(@"<menu>
<course name=""appetizer"">
<dish>Shrimp Cocktail</dish>
<dish>Escargot</dish>
</course>
<course name=""main"">
<dish>Filet Mignon</dish>
<dish>Garlic Potatoes</dish>
<dish>Broccoli</dish>
</course>
<course name=""dessert"">
<dish>Chocolate Cheesecake</dish>
</course>
</menu>");
}
[Test]
public void XmlDocument()
{
TestExpression(@"<?xml version=""1.0""?>
<menu>
<course name=""appetizer"">
<dish>Shrimp Cocktail</dish>
<dish>Escargot</dish>
</course>
</menu>");
}
[Test]
public void XmlNestedWithExpressions()
{
TestExpression(@"<?xml version=""1.0""?>
<menu>
<course name=""appetizer"">
<%= From m In menu _
Where m.Course = ""appetizer"" _
Select <dish><%= m.Food %></dish> %>
</course>
<course name=""main"">
<%= From m In menu _
Where m.Course = ""main"" _
Select <dish><%= m.Food %></dish> %>
</course>
<course name=""dessert"">
<%= From m In menu _
Where m.Course = ""dessert"" _
Select <dish><%= m.Food %></dish> %>
</course>
</menu>");
}
[Test]
public void XmlAccessExpressions()
{
TestExpression("xml.<menu>.<course>");
TestExpression("xml...<course>");
TestExpression("xml...<course>(2)");
TestExpression("item.@name");
}
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save