Browse Source

Merge branch '4.2' to master.

pull/26/merge
Daniel Grunwald 13 years ago
parent
commit
b2855bc85a
  1. 17
      data/resources/StringResources.de.resx
  2. 54
      data/resources/StringResources.nl.resx
  3. 5
      data/resources/StringResources.resx
  4. 124
      data/resources/StringResources.tr.resx
  5. 18
      src/AddIns/BackendBindings/VBNetBinding/Project/Src/FormattingStrategy/VBNetFormattingStrategy.cs
  6. 48
      src/AddIns/BackendBindings/VBNetBinding/Test/FormattingStrategy/IndentationTests.cs
  7. 7
      src/AddIns/Debugger/Debugger.Core/IDStringProvider.cs
  8. 7
      src/AddIns/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs
  9. 34
      src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerGenerator/AbstractDesignerGenerator.cs
  10. 3
      src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs
  11. 39
      src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/TypeResolutionService.cs
  12. 9
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/WpfViewContent.cs
  13. 17
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/StackPanelPlacementSupport.cs
  14. 5
      src/AddIns/VersionControl/SubversionAddIn/Src/Gui/ProjectBrowserVisitor/OverlayIconManager.cs
  15. 3
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs
  16. 16
      src/Libraries/ICSharpCode.Decompiler/Ast/AstBuilder.cs
  17. 6
      src/Libraries/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
  18. 1
      src/Libraries/ICSharpCode.Decompiler/Ast/DecompilerContext.cs
  19. 8
      src/Libraries/ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs
  20. 1
      src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs
  21. 15
      src/Libraries/ICSharpCode.Decompiler/DecompilerSettings.cs
  22. 3
      src/Libraries/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  23. 653
      src/Libraries/ICSharpCode.Decompiler/ILAst/AsyncDecompiler.cs
  24. 13
      src/Libraries/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs
  25. 6
      src/Libraries/ICSharpCode.Decompiler/ILAst/ILCodes.cs
  26. 12
      src/Libraries/ICSharpCode.Decompiler/ILAst/PatternMatching.cs
  27. 310
      src/Libraries/ICSharpCode.Decompiler/ILAst/StateRange.cs
  28. 148
      src/Libraries/ICSharpCode.Decompiler/ILAst/SymbolicExecution.cs
  29. 21
      src/Libraries/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs
  30. 418
      src/Libraries/ICSharpCode.Decompiler/ILAst/YieldReturnDecompiler.cs
  31. 4
      src/Libraries/ICSharpCode.Decompiler/Properties/AssemblyInfo.cs
  32. 144
      src/Libraries/ICSharpCode.Decompiler/Tests/Async.cs
  33. 4
      src/Libraries/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
  34. 2
      src/Libraries/ICSharpCode.Decompiler/Tests/PropertiesAndEvents.cs
  35. 6
      src/Libraries/ICSharpCode.Decompiler/Tests/TestRunner.cs
  36. 15
      src/Libraries/NRefactory/Project/Src/Lexer/VBNet/ExpressionFinder.atg
  37. 4
      src/Libraries/NRefactory/Project/Src/Lexer/VBNet/ExpressionFinder.cs
  38. 2
      src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Lexer.cs
  39. 3197
      src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Parser.cs
  40. 1
      src/Libraries/NRefactory/Project/Src/Lexer/VBNet/PushParser.frame
  41. 6
      src/Libraries/NRefactory/Test/Lexer/VBNet/XmlModeLexerTests.cs
  42. 14
      src/Libraries/NRefactory/Test/Parser/Statements/SwitchStatementTests.cs
  43. 16
      src/Main/Base/Project/Src/Gui/Components/ExtTreeView/ExtTreeView.cs
  44. 7
      src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/ServiceReference/ProjectWithServiceReferences.cs
  45. 79
      src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/Commands/ReferenceFolderNodeCommands.cs
  46. 20
      src/Main/Base/Test/ServiceReferences/ProjectWithServiceReferencesTests.cs

17
data/resources/StringResources.de.resx

@ -1498,6 +1498,12 @@ Beispiele: "120", "MainClass", "Main.cs, 120".</value> @@ -1498,6 +1498,12 @@ Beispiele: "120", "MainClass", "Main.cs, 120".</value>
<data name="Dialog.HighlightingEditor.ColorDlg.Italic" xml:space="preserve">
<value>Kursiv</value>
</data>
<data name="Dialog.HighlightingEditor.Export" xml:space="preserve">
<value>Hervorhebungsfarben exportieren</value>
</data>
<data name="Dialog.HighlightingEditor.Import" xml:space="preserve">
<value>Hervorhebungsfarben importieren</value>
</data>
<data name="Dialog.HighlightingEditor.Properties.Value" xml:space="preserve">
<value>Wert</value>
</data>
@ -2181,11 +2187,14 @@ Wollen Sie die neue Datei zum Projekt ${CurrentProjectName} hinzufügen?</value> @@ -2181,11 +2187,14 @@ Wollen Sie die neue Datei zum Projekt ${CurrentProjectName} hinzufügen?</value>
<value>Deaktiviert</value>
</data>
<data name="Dialog.Options.IDEOptions.TextEditor.Markers.MarkersGroupBox" xml:space="preserve">
<value>Markierungen und Liniale</value>
<value>Markierungen</value>
</data>
<data name="Dialog.Options.IDEOptions.TextEditor.Markers.PanelName" xml:space="preserve">
<value>Markierungen und Liniale</value>
</data>
<data name="Dialog.Options.IDEOptions.TextEditor.Markers.RulersGroupBox" xml:space="preserve">
<value>Lineale</value>
</data>
<data name="Dialog.Options.IDEOptions.TextEditor.Markers.ShowHiddenDefinitionsCheckBox" xml:space="preserve">
<value>Verdeckte Definitionen anzeigen (nur geschweifte Klammern)</value>
</data>
@ -5393,6 +5402,12 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFxCompiler, WixNetFxExtension< @@ -5393,6 +5402,12 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFxCompiler, WixNetFxExtension<
<data name="OpenFileTabEventHandler.OpenCommandPromptHere" xml:space="preserve">
<value>Kommandozeile hier öffnen</value>
</data>
<data name="PortableLibrary.ChooseTargetFrameworks" xml:space="preserve">
<value>Ziel-Frameworks wählen</value>
</data>
<data name="PortableLibrary.CouldNotFindTools" xml:space="preserve">
<value>Konnte die Portable Class Library Tools nicht finden.</value>
</data>
<data name="ProjectBrowser.Toolbar.CollapseAll" xml:space="preserve">
<value>Alle Knoten einklappen</value>
</data>

54
data/resources/StringResources.nl.resx

@ -1501,6 +1501,12 @@ Voorbeelden: "120", "MainClass", "Main.cs, 120".</value> @@ -1501,6 +1501,12 @@ Voorbeelden: "120", "MainClass", "Main.cs, 120".</value>
<data name="Dialog.HighlightingEditor.ColorDlg.Italic" xml:space="preserve">
<value>Cursief</value>
</data>
<data name="Dialog.HighlightingEditor.Export" xml:space="preserve">
<value>Selectie kleuren expoorteren</value>
</data>
<data name="Dialog.HighlightingEditor.Import" xml:space="preserve">
<value>Selectie kleuren importeren</value>
</data>
<data name="Dialog.HighlightingEditor.Properties.Value" xml:space="preserve">
<value>Waarde</value>
</data>
@ -2184,11 +2190,14 @@ Wilt u het nieuwe bestand toevoegen aan project ${CurrentProjectName}?</value> @@ -2184,11 +2190,14 @@ Wilt u het nieuwe bestand toevoegen aan project ${CurrentProjectName}?</value>
<value>Geen</value>
</data>
<data name="Dialog.Options.IDEOptions.TextEditor.Markers.MarkersGroupBox" xml:space="preserve">
<value>Markeringen en Linealen</value>
<value>Markeringen</value>
</data>
<data name="Dialog.Options.IDEOptions.TextEditor.Markers.PanelName" xml:space="preserve">
<value>Markeringen en Linealen</value>
</data>
<data name="Dialog.Options.IDEOptions.TextEditor.Markers.RulersGroupBox" xml:space="preserve">
<value>Linealen</value>
</data>
<data name="Dialog.Options.IDEOptions.TextEditor.Markers.ShowHiddenDefinitionsCheckBox" xml:space="preserve">
<value>Toon &amp;verborgen definities(alleen haakjes)</value>
</data>
@ -2355,7 +2364,7 @@ Wilt u het nieuwe bestand toevoegen aan project ${CurrentProjectName}?</value> @@ -2355,7 +2364,7 @@ Wilt u het nieuwe bestand toevoegen aan project ${CurrentProjectName}?</value>
<value>32 bit Intel-compatibele processor</value>
</data>
<data name="Dialog.ProjectOptions.Build.TargetFramework" xml:space="preserve">
<value>Doel Framework:</value>
<value>Doel raamwerk:</value>
</data>
<data name="Dialog.ProjectOptions.Build.TreatWarningsAsErrors" xml:space="preserve">
<value>Behandel waarschuwingen als fouten</value>
@ -3046,7 +3055,7 @@ Er kan worden gekozen voor opslag van de instellingen in het .user bestand inpla @@ -3046,7 +3055,7 @@ Er kan worden gekozen voor opslag van de instellingen in het .user bestand inpla
<value>Bezig met Code Analyse...</value>
</data>
<data name="ICSharpCode.Build.UnknownTargetMonoFrameworkVersion" xml:space="preserve">
<value>Onbekend doel Mono Framework Versie:</value>
<value>Onbekend doel Mono Raamwerk Versie:</value>
</data>
<data name="ICSharpCode.CodeAnalysis" xml:space="preserve">
<value>Code Analyse</value>
@ -4090,7 +4099,7 @@ Alleen letters, getallen, spatie, '.' of '_' zijn toegestaan.</value> @@ -4090,7 +4099,7 @@ Alleen letters, getallen, spatie, '.' of '_' zijn toegestaan.</value>
<value>Converteer geselecteerde &amp;projecten naar</value>
</data>
<data name="ICSharpCode.SharpDevelop.Project.UpgradeView.ChangeTargetFrameworkLabel" xml:space="preserve">
<value>Wijzig doel framework</value>
<value>Wijzig doel Raamwerk:</value>
</data>
<data name="ICSharpCode.SharpDevelop.Project.UpgradeView.ChangeVersionGroupBoxHeader" xml:space="preserve">
<value>Versie van geselecteerde projecten wijzigen</value>
@ -4105,7 +4114,7 @@ Alleen letters, getallen, spatie, '.' of '_' zijn toegestaan.</value> @@ -4105,7 +4114,7 @@ Alleen letters, getallen, spatie, '.' of '_' zijn toegestaan.</value>
<value>&lt;niet wijzigen&gt;</value>
</data>
<data name="ICSharpCode.SharpDevelop.Project.UpgradeView.TargetFramework" xml:space="preserve">
<value>Doel framework</value>
<value>Doel Raamwerk</value>
</data>
<data name="ICSharpCode.SharpDevelop.Project.UpgradeView.Title" xml:space="preserve">
<value>Project opwaarderen</value>
@ -4119,7 +4128,7 @@ Zonder opwaarderen kan het project niet geopend wordenh.</value> @@ -4119,7 +4128,7 @@ Zonder opwaarderen kan het project niet geopend wordenh.</value>
<value>Opwaarderen naar MSBuild ${NewToolsVersion}</value>
</data>
<data name="ICSharpCode.SharpDevelop.Project.UpgradeView.UpgradeFromPreviousVersionDescription" xml:space="preserve">
<value>Deze oplossing werd met een vorige versie van SharpDevelop gemaakt. Door te upgraden kan gebruik gemaakt worden van nieuwe taal of framework mogelijkheden.</value>
<value>Deze oplossing werd met een eerdere versie van SharpDevelop gemaakt. Door te upgraden kan gebruik gemaakt worden van nieuwe taal- of raamwerk mogelijkheden.</value>
</data>
<data name="ICSharpCode.SharpDevelop.Services.AmbienceService.AmbienceNotFoundError" xml:space="preserve">
<value>Momentele ambience niet gevonden.
@ -4427,7 +4436,7 @@ Microsoft.Tools.WindowsInstallerXml.Extenties.NetFxCompiler, WixNetFxExtentie</v @@ -4427,7 +4436,7 @@ Microsoft.Tools.WindowsInstallerXml.Extenties.NetFxCompiler, WixNetFxExtentie</v
<value>WiX localisatie bestanden</value>
</data>
<data name="ICSharpCode.WixBinding.WixNetFxExtensionTitle" xml:space="preserve">
<value>.NET Framework uitbreiding</value>
<value>.NET Raamwerk uitbreiding</value>
</data>
<data name="ICSharpCode.WixBinding.WixPackageFilesDiffControl.NoDiffFound" xml:space="preserve">
<value>Geen verschil gevonden.</value>
@ -5383,6 +5392,27 @@ Microsoft.Tools.WindowsInstallerXml.Extenties.NetFxCompiler, WixNetFxExtentie</v @@ -5383,6 +5392,27 @@ Microsoft.Tools.WindowsInstallerXml.Extenties.NetFxCompiler, WixNetFxExtentie</v
<data name="OpenFileTabEventHandler.OpenCommandPromptHere" xml:space="preserve">
<value>Open hier de commando prompt</value>
</data>
<data name="PortableLibrary.ChooseTargetFrameworks" xml:space="preserve">
<value>Selecteer doel-raamwerken.</value>
</data>
<data name="PortableLibrary.CouldNotFindTools" xml:space="preserve">
<value>Kan Portable Klasse-bibliotheek gereedschap niet vinden.</value>
</data>
<data name="PortableLibrary.PortableSubset" xml:space="preserve">
<value>.NET Portable subset</value>
</data>
<data name="PortableLibrary.SelectAtLeastTwoFrameworks" xml:space="preserve">
<value>Er moeten tenminste twee raamwerken worden geselecteerd.</value>
</data>
<data name="PortableLibrary.SelectedProfile" xml:space="preserve">
<value>Gekozen profiel:</value>
</data>
<data name="PortableLibrary.SelectProfileDialog.Title" xml:space="preserve">
<value>Kies een Portable Bibliotheek profiel.</value>
</data>
<data name="PortableLibrary.ToolsInstallationHelp" xml:space="preserve">
<value>Om de portabele Klassebibliotheek gereedschappen te installeren zonder Visual Studio te installeren, sla het download bestand op (PortableLibraryTools.exe) op uw computer en voer de installatie uit via de commndoregel. Inclusief de /bouwmachine schakeling op de commandoregel.</value>
</data>
<data name="ProjectBrowser.Toolbar.CollapseAll" xml:space="preserve">
<value>Alle knooppunten invouwen</value>
</data>
@ -6639,6 +6669,12 @@ De hulpbron bestanden zijn hernoemd/verplaatst op de beschreven wijze.</value> @@ -6639,6 +6669,12 @@ De hulpbron bestanden zijn hernoemd/verplaatst op de beschreven wijze.</value>
<data name="Templates.Project.GtkSharpProject.Name" xml:space="preserve">
<value>Gtk# toepassing</value>
</data>
<data name="Templates.Project.PortableLibrary.Description" xml:space="preserve">
<value>Bibliotheek, bruikbaar bij Windows, Silverlight, Windows Phone en Xbox.</value>
</data>
<data name="Templates.Project.PortableLibrary.Name" xml:space="preserve">
<value>Portable Klassen-bibliotheek</value>
</data>
<data name="Templates.Project.SetupProject.Description" xml:space="preserve">
<value>Windows installatie project om een MSI installatie programma te maken.</value>
</data>
@ -6790,7 +6826,7 @@ De hulpbron bestanden zijn hernoemd/verplaatst op de beschreven wijze.</value> @@ -6790,7 +6826,7 @@ De hulpbron bestanden zijn hernoemd/verplaatst op de beschreven wijze.</value>
<value>Ontkoppel</value>
</data>
<data name="XML.MainMenu.DebugMenu.Error.BadAssembly" xml:space="preserve">
<value>Kan .NET Framework versie van het programma niet krijgen. Ga na of het programma een beheerde assembly is.</value>
<value>Kan .NET Raamwerk versie van het programma niet oproepen. Ga na of het programma een gemanagede assembly is.</value>
</data>
<data name="XML.MainMenu.DebugMenu.Error.CannotAttachToProcess" xml:space="preserve">
<value>Kan niet bij proces aanhaken.</value>
@ -6805,7 +6841,7 @@ De hulpbron bestanden zijn hernoemd/verplaatst op de beschreven wijze.</value> @@ -6805,7 +6841,7 @@ De hulpbron bestanden zijn hernoemd/verplaatst op de beschreven wijze.</value>
<value>Kan SharpDevelop foutopsporing niet starten omdat kernel foutopsporing is aangezet. Om de kernel foutopsporing uit te zetten, dient de schakeling "/debug" uit bestand Boot.ini verwijderd te worden en de computer opnieuw te worden opgestart.</value>
</data>
<data name="XML.MainMenu.DebugMenu.Error.Net10NotSupported" xml:space="preserve">
<value>Foutopsporing bij .NET Framework 1.0 programmas is niet ondersteund.</value>
<value>Foutopsporing bij .NET Raamwerk 1.0 programmas is niet ondersteund.</value>
</data>
<data name="XML.MainMenu.DebugMenu.Error.NotDebugging" xml:space="preserve">
<value>Kan actie niet uitvoeren omdat er geen foutopsporing van een proces plaatsvindt.</value>

5
data/resources/StringResources.resx

@ -2262,11 +2262,14 @@ system. I don't think that it needs translation.</comment> @@ -2262,11 +2262,14 @@ system. I don't think that it needs translation.</comment>
<value>None</value>
</data>
<data name="Dialog.Options.IDEOptions.TextEditor.Markers.MarkersGroupBox" xml:space="preserve">
<value>Markers and Rulers</value>
<value>Markers</value>
</data>
<data name="Dialog.Options.IDEOptions.TextEditor.Markers.PanelName" xml:space="preserve">
<value>Markers and Rulers</value>
</data>
<data name="Dialog.Options.IDEOptions.TextEditor.Markers.RulersGroupBox" xml:space="preserve">
<value>Rulers</value>
</data>
<data name="Dialog.Options.IDEOptions.TextEditor.Markers.ShowHiddenDefinitionsCheckBox" xml:space="preserve">
<value>Show &amp;hidden definitions (brackets only)</value>
</data>

124
data/resources/StringResources.tr.resx

@ -608,7 +608,7 @@ @@ -608,7 +608,7 @@
<value>{0} arayüz ekle</value>
</data>
<data name="AddIns.SharpRefactoring.OverrideEqualsGetHashCodeMethods.AddOperatorOverloads" xml:space="preserve">
<value>Taşma operatörü ekle</value>
<value>Aşırı yükleme operatörü ekle</value>
</data>
<data name="AddIns.SharpRefactoring.OverrideEqualsGetHashCodeMethods.AddOtherMethod" xml:space="preserve">
<value>${otherMethod} geçersiz ekleme</value>
@ -1019,7 +1019,7 @@ Oluşturulan stili yenisiyle değiştirmek istiyor musunuz?</value> @@ -1019,7 +1019,7 @@ Oluşturulan stili yenisiyle değiştirmek istiyor musunuz?</value>
<value>Temel sınıf kategorisindeki nesne üyelerini göster</value>
</data>
<data name="ComponentInspector.CustomObjectPanel.ShowPublicMembersCheckBox" xml:space="preserve">
<value>Sadece genel üyeler</value>
<value>Sadece public üyeler</value>
</data>
<data name="ComponentInspector.ErrorDialog.LessInformationButton" xml:space="preserve">
<value>Kısa Bilgilendirme</value>
@ -1069,7 +1069,7 @@ Olayları kayıt etmek için, Nesneler panelinden bir nesne yada olay seçip, ya @@ -1069,7 +1069,7 @@ Olayları kayıt etmek için, Nesneler panelinden bir nesne yada olay seçip, ya
<value>Tüm seviyeler</value>
</data>
<data name="ComponentInspector.FindDialog.AssembliesRadioButton" xml:space="preserve">
<value>Çevirmeler/Türler</value>
<value>Derlemeler/Türler</value>
</data>
<data name="ComponentInspector.FindDialog.ContainsRadioButton" xml:space="preserve">
<value>İçerir</value>
@ -1317,7 +1317,7 @@ Bir ActiveX / COM nesnesi oluşturmak / değiştirmek için, nesne ağacı veya @@ -1317,7 +1317,7 @@ Bir ActiveX / COM nesnesi oluşturmak / değiştirmek için, nesne ağacı veya
<value>Özellik/Olay erişim yöntemleri</value>
</data>
<data name="ComponentInspector.ObjectTreeOptionsPanel.ShowPublicMembersOnlyCheckBox" xml:space="preserve">
<value>Sadece genel üyeler</value>
<value>Sadece public üyeler</value>
</data>
<data name="ComponentInspector.OutputList.OutputColumnHeader" xml:space="preserve">
<value>Çıktı</value>
@ -1470,7 +1470,7 @@ Bir ActiveX / COM nesnesi oluşturmak / değiştirmek için, nesne ağacı veya @@ -1470,7 +1470,7 @@ Bir ActiveX / COM nesnesi oluşturmak / değiştirmek için, nesne ağacı veya
<value>&lt;Boş&gt;</value>
</data>
<data name="Dialog.EditAvailableConfigurationsDialog.EnterNewName" xml:space="preserve">
<value>Yeni adı girin:</value>
<value>Yeni ad girin:</value>
</data>
<data name="Dialog.EditAvailableConfigurationsDialog.InvalidName" xml:space="preserve">
<value>Ad geçersiz.</value>
@ -1498,6 +1498,12 @@ Satır numaraları, sınıf yada dosya adları girebilirsiniz. @@ -1498,6 +1498,12 @@ Satır numaraları, sınıf yada dosya adları girebilirsiniz.
<data name="Dialog.HighlightingEditor.ColorDlg.Italic" xml:space="preserve">
<value>İtalik</value>
</data>
<data name="Dialog.HighlightingEditor.Export" xml:space="preserve">
<value>Renk vurgulamayı dışa aktar</value>
</data>
<data name="Dialog.HighlightingEditor.Import" xml:space="preserve">
<value>Renk vurgulaması al</value>
</data>
<data name="Dialog.HighlightingEditor.Properties.Value" xml:space="preserve">
<value>Değer</value>
</data>
@ -1861,7 +1867,7 @@ Yeni dosyayı, ${CurrentProjectName} projesine eklemek istiyor musunuz?</value> @@ -1861,7 +1867,7 @@ Yeni dosyayı, ${CurrentProjectName} projesine eklemek istiyor musunuz?</value>
<value>İstisnalar</value>
</data>
<data name="Dialog.Options.IDEOptions.Debugging.PauseOnHandledExceptions" xml:space="preserve">
<value>Tanıtıcı istisnaları duraklat</value>
<value>Yakalanan istisnaları duraklat</value>
</data>
<data name="Dialog.Options.IDEOptions.Debugging.Stepping" xml:space="preserve">
<value>Adımlama</value>
@ -2182,11 +2188,14 @@ Yeni dosyayı, ${CurrentProjectName} projesine eklemek istiyor musunuz?</value> @@ -2182,11 +2188,14 @@ Yeni dosyayı, ${CurrentProjectName} projesine eklemek istiyor musunuz?</value>
<value>Hiçbiri</value>
</data>
<data name="Dialog.Options.IDEOptions.TextEditor.Markers.MarkersGroupBox" xml:space="preserve">
<value>İşaretleyiciler ve Cetveller</value>
<value>İşaretleyiciler</value>
</data>
<data name="Dialog.Options.IDEOptions.TextEditor.Markers.PanelName" xml:space="preserve">
<value>İşaretleyiciler ve Cetveller</value>
</data>
<data name="Dialog.Options.IDEOptions.TextEditor.Markers.RulersGroupBox" xml:space="preserve">
<value>Cetveller</value>
</data>
<data name="Dialog.Options.IDEOptions.TextEditor.Markers.ShowHiddenDefinitionsCheckBox" xml:space="preserve">
<value>Gizli tanımları (sadece parentezler) göster</value>
</data>
@ -4717,7 +4726,7 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension< @@ -4717,7 +4726,7 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension<
<value>parametre</value>
</data>
<data name="MainWindow.Editor.Tooltip.UnresolvedOverload" xml:space="preserve">
<value>Taşma</value>
<value>Aşırı yükleme</value>
</data>
<data name="MainWindow.SaveChangesMessage" xml:space="preserve">
<value>Geçerli değişiklikleri kaydetmek istiyor musunuz?</value>
@ -4765,16 +4774,16 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension< @@ -4765,16 +4774,16 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension<
<value>Diğer Üyeleri Göster</value>
</data>
<data name="MainWindow.Windows.ClassBrowser.ClassViewSettings.ShowPrivateMembers.Label" xml:space="preserve">
<value>Gizli Üyeleri Göster</value>
<value>Private Üyeleri Göster</value>
</data>
<data name="MainWindow.Windows.ClassBrowser.ClassViewSettings.ShowProjectReferences.Label" xml:space="preserve">
<value>Proje Referanslarını Göster</value>
</data>
<data name="MainWindow.Windows.ClassBrowser.ClassViewSettings.ShowProtectedMembers.Label" xml:space="preserve">
<value>Korunmuş Üyeleri Göster</value>
<value>Protected Üyeleri Göster</value>
</data>
<data name="MainWindow.Windows.ClassBrowser.ClassViewSettings.ShowPublicMembers.Label" xml:space="preserve">
<value>Genel Üyeleri Göster</value>
<value>Public Üyeleri Göster</value>
</data>
<data name="MainWindow.Windows.ClassBrowser.ClassViewSettingsButton.ToolTip" xml:space="preserve">
<value>Sınıf Görünüm Ayarları</value>
@ -4912,7 +4921,7 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension< @@ -4912,7 +4921,7 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension<
<value>İstisnaya müdahale edilemedi. Hata ayıklaması yapılan program daha fazla devam edemez.</value>
</data>
<data name="MainWindow.Windows.Debug.ExceptionForm.Error.CannotInterceptHandledException" xml:space="preserve">
<value>İşlenen istisnaya müdahale edilemedi. Hata ayıklama sembolleri istisna kaynağı için mevcut olmayabilir.</value>
<value>Yakalanan istisnaya müdahale edilemedi. Hata ayıklama sembolleri istisna kaynağı için mevcut olmayabilir.</value>
</data>
<data name="MainWindow.Windows.Debug.ExceptionForm.HideExceptionDetails" xml:space="preserve">
<value>İstisna Detaylarını Gizle</value>
@ -4939,10 +4948,10 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension< @@ -4939,10 +4948,10 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension<
<value>İstisna</value>
</data>
<data name="MainWindow.Windows.Debug.ExceptionForm.Title.Handled" xml:space="preserve">
<value>İşlenen istisna</value>
<value>Yakalanan istisna</value>
</data>
<data name="MainWindow.Windows.Debug.ExceptionForm.Title.Unhandled" xml:space="preserve">
<value>İşlenmeyen istisna</value>
<value>Bilinmeyen istisna</value>
</data>
<data name="MainWindow.Windows.Debug.ExceptionHistory" xml:space="preserve">
<value>İstisna geçmişi</value>
@ -4984,16 +4993,16 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension< @@ -4984,16 +4993,16 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension<
<value>Ad</value>
</data>
<data name="MainWindow.Windows.Debug.LocalVariables.NonPublicMembers" xml:space="preserve">
<value>Genel üyeler dışında</value>
<value>Public üyeler dışında</value>
</data>
<data name="MainWindow.Windows.Debug.LocalVariables.NonPublicStaticMembers" xml:space="preserve">
<value>Genel sabit üyeler dışında</value>
<value>Public Static üyeler dışında</value>
</data>
<data name="MainWindow.Windows.Debug.LocalVariables.PrivateMembers" xml:space="preserve">
<value>Özel üyeler</value>
<value>Private üyeler</value>
</data>
<data name="MainWindow.Windows.Debug.LocalVariables.PrivateStaticMembers" xml:space="preserve">
<value>Özel Sabit Üyeler</value>
<value>Private Static Üyeler</value>
</data>
<data name="MainWindow.Windows.Debug.LocalVariables.ShowFullError" xml:space="preserve">
<value>Hatanın tümünü göster...</value>
@ -5002,7 +5011,7 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension< @@ -5002,7 +5011,7 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension<
<value>Değerleri onaltılık göster</value>
</data>
<data name="MainWindow.Windows.Debug.LocalVariables.StaticMembers" xml:space="preserve">
<value>Sabit üyeler</value>
<value>Static üyeler</value>
</data>
<data name="MainWindow.Windows.Debug.LocalVariables.TypeColumn" xml:space="preserve">
<value>Tür</value>
@ -5323,7 +5332,7 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension< @@ -5323,7 +5332,7 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension<
<value>Doğrulama: başarılı</value>
</data>
<data name="NUnitPad.NUnitPadContent.CancelItem" xml:space="preserve">
<value>Test çevirmeleri yüklenemiyor, kendiliğinden yükleme iptal edildi.</value>
<value>Test derlemeleri yüklenemiyor, kendiliğinden yükleme iptal edildi.</value>
</data>
<data name="NUnitPad.NUnitPadContent.GotoDefinitionContextMenuLabel" xml:space="preserve">
<value>Tanimlamaya &amp;git</value>
@ -5332,7 +5341,7 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension< @@ -5332,7 +5341,7 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension<
<value>Mevcut seçili projedeki NUnit 'e referans ekle</value>
</data>
<data name="NUnitPad.NUnitPadContent.RefreshItem" xml:space="preserve">
<value>Test çevirmelerini yeniden yükler</value>
<value>Test derlemelerini yeniden yükler</value>
</data>
<data name="NUnitPad.NUnitPadContent.RunAllTests" xml:space="preserve">
<value>Bütün testleri çalıştır</value>
@ -5359,25 +5368,25 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension< @@ -5359,25 +5368,25 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension<
<value>Test durumu '${TestCase}' yürütülemedi.</value>
</data>
<data name="ObjectBrowser.Menu.LoadAssembly" xml:space="preserve">
<value>Çevirme Yükle...</value>
<value>Derleme Yükle...</value>
</data>
<data name="ObjectBrowser.Menu.LoadRef" xml:space="preserve">
<value>Referanslı Çevirmeleri Yükle</value>
<value>Referanslı Derlemeleri Yükle</value>
</data>
<data name="ObjectBrowser.Menu.LoadStd" xml:space="preserve">
<value>Standart Çevirmeleri Yükle</value>
<value>Standart Derlemeleri Yükle</value>
</data>
<data name="OpenFileTabEventHandler.ContextMenu.Close" xml:space="preserve">
<value>&amp;Kapat</value>
<value>Kapat</value>
</data>
<data name="OpenFileTabEventHandler.ContextMenu.CloseAllButThis" xml:space="preserve">
<value>Bu hariç hepsini kapat</value>
</data>
<data name="OpenFileTabEventHandler.ContextMenu.Save" xml:space="preserve">
<value>K&amp;aydet</value>
<value>Kaydet</value>
</data>
<data name="OpenFileTabEventHandler.ContextMenu.SaveAs" xml:space="preserve">
<value>Farklı Ka&amp;ydet...</value>
<value>Farklı Kaydet...</value>
</data>
<data name="OpenFileTabEventHandler.CopyPathName" xml:space="preserve">
<value>Dosya yolunu/adını kopyala</value>
@ -5388,6 +5397,27 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension< @@ -5388,6 +5397,27 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension<
<data name="OpenFileTabEventHandler.OpenCommandPromptHere" xml:space="preserve">
<value>Burada komut istemi aç</value>
</data>
<data name="PortableLibrary.ChooseTargetFrameworks" xml:space="preserve">
<value>hedef çalışmaçerçevesini seçin</value>
</data>
<data name="PortableLibrary.CouldNotFindTools" xml:space="preserve">
<value>Taşınabilir Sınıf Kitaplığı Araçları bulunamadı.</value>
</data>
<data name="PortableLibrary.PortableSubset" xml:space="preserve">
<value>.NET Taşınabilir AltSeti</value>
</data>
<data name="PortableLibrary.SelectAtLeastTwoFrameworks" xml:space="preserve">
<value>İki veya daha fazla çerçevenin seçilmesi gerekir.</value>
</data>
<data name="PortableLibrary.SelectedProfile" xml:space="preserve">
<value>Seçili profil:</value>
</data>
<data name="PortableLibrary.SelectProfileDialog.Title" xml:space="preserve">
<value>Taşınabilir Kitaplık Profili seç</value>
</data>
<data name="PortableLibrary.ToolsInstallationHelp" xml:space="preserve">
<value>Visual Studio yüklemeden Taşınabilir Sınıf Kitaplığı Araçları'nı yüklemek için,bilgisayarınıza dosyayı(PortableLibraryTools.exe)indirip kaydedin ve bir komut istemi penceresinde kurulum programını çalıştırın.Komut satırında /buildmachine anahtarı ekleyin.</value>
</data>
<data name="ProjectBrowser.Toolbar.CollapseAll" xml:space="preserve">
<value>Bütün düğümleri daralt</value>
</data>
@ -5422,7 +5452,7 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension< @@ -5422,7 +5452,7 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension<
<value>Web Referansı Ekle</value>
</data>
<data name="ProjectComponent.ContextMenu.Build" xml:space="preserve">
<value>D&amp;erle</value>
<value>Derle</value>
</data>
<data name="ProjectComponent.ContextMenu.Clean" xml:space="preserve">
<value>Temizle</value>
@ -5542,10 +5572,10 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension< @@ -5542,10 +5572,10 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension<
<value>Tüm web referanslarını sil</value>
</data>
<data name="RegExpTk.MainDialog.Assemblies" xml:space="preserve">
<value>Çevirmeler (*.dll)|*.dll</value>
<value>Derlemeler (*.dll)|*.dll</value>
</data>
<data name="RegExpTk.MainDialog.Assembly" xml:space="preserve">
<value>Çevirme</value>
<value>Derleme</value>
</data>
<data name="RegExpTk.MainDialog.Classname" xml:space="preserve">
<value>Sınıf adı</value>
@ -5554,7 +5584,7 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension< @@ -5554,7 +5584,7 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension<
<value>Derle</value>
</data>
<data name="RegExpTk.MainDialog.CreateAssembly" xml:space="preserve">
<value>Çevirme oluştur</value>
<value>Derleme oluştur</value>
</data>
<data name="RegExpTk.MainDialog.ECMA" xml:space="preserve">
<value>ECMA betiği</value>
@ -5584,7 +5614,7 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension< @@ -5584,7 +5614,7 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension<
<value>Çok satırlı</value>
</data>
<data name="RegExpTk.MainDialog.Namespace" xml:space="preserve">
<value>Adalanı</value>
<value>Ad alanı</value>
</data>
<data name="RegExpTk.MainDialog.PublicVisible" xml:space="preserve">
<value>Açıkça görünür</value>
@ -5659,7 +5689,7 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension< @@ -5659,7 +5689,7 @@ Microsoft.Tools.WindowsInstallerXml.Extensions.NetFXCompiler, WixNetFxExtension<
<value>Sözcük olmayan karakter değeri</value>
</data>
<data name="RegExpTk.RegExpMenu.UngreedyStar" xml:space="preserve">
<value>Tok yıldız</value>
<value>Dolu yıldız</value>
</data>
<data name="RegExpTk.RegExpMenu.WhitespaceCharacter" xml:space="preserve">
<value>Boşluk karakteri</value>
@ -6305,7 +6335,7 @@ Kaynak dosyaları buna göre yeniden adlandırıldı/taşındı.</value> @@ -6305,7 +6335,7 @@ Kaynak dosyaları buna göre yeniden adlandırıldı/taşındı.</value>
<value>Yapılandırma Eleman Koleksiyonundan türeme sınıf.</value>
</data>
<data name="Templates.File.ConfigurationElementCollection.Name" xml:space="preserve">
<value>Nesne Yığını Ayarları</value>
<value>Yapılandırma Elemanı Koleksiyonu</value>
</data>
<data name="Templates.File.ConfigurationSection.Description" xml:space="preserve">
<value>ConfigurationSection gerçeklemesi yapan sınıf</value>
@ -6326,10 +6356,10 @@ Kaynak dosyaları buna göre yeniden adlandırıldı/taşındı.</value> @@ -6326,10 +6356,10 @@ Kaynak dosyaları buna göre yeniden adlandırıldı/taşındı.</value>
<value>Boş Dosya</value>
</data>
<data name="Templates.File.Exception.Description" xml:space="preserve">
<value>Yeni bir Kuraldışı Sınıf oluştur.</value>
<value>Yeni bir istisna Sınıf oluştur.</value>
</data>
<data name="Templates.File.Exception.Name" xml:space="preserve">
<value>Kuraldışı Durum</value>
<value>İstisna</value>
</data>
<data name="Templates.File.GtkSharpWindow.Description" xml:space="preserve">
<value>Bir Gtk# uygulaması için pencere</value>
@ -6368,7 +6398,7 @@ Kaynak dosyaları buna göre yeniden adlandırıldı/taşındı.</value> @@ -6368,7 +6398,7 @@ Kaynak dosyaları buna göre yeniden adlandırıldı/taşındı.</value>
<value>MSBuild dosyası</value>
</data>
<data name="Templates.File.MyExtensionClass.Description" xml:space="preserve">
<value>"My" alanadını uzatan sınıf için bir şablon.</value>
<value>"My" ad alanını uzatan sınıf için bir şablon.</value>
</data>
<data name="Templates.File.MyExtensionClass.Name" xml:space="preserve">
<value>"My" uzantılar</value>
@ -6605,7 +6635,7 @@ Kaynak dosyaları buna göre yeniden adlandırıldı/taşındı.</value> @@ -6605,7 +6635,7 @@ Kaynak dosyaları buna göre yeniden adlandırıldı/taşındı.</value>
<value>Başka uygulamalarda kullanılabilen sınıflar oluşturan bir proje.</value>
</data>
<data name="Templates.Project.ClassLibrary.Name" xml:space="preserve">
<value>Sınıf Kütüphanesi</value>
<value>Sınıf Kitaplığı</value>
</data>
<data name="Templates.Project.ConsoleProject.Description" xml:space="preserve">
<value>Komut satırı uygulaması oluşturan proje.</value>
@ -6643,6 +6673,12 @@ Kaynak dosyaları buna göre yeniden adlandırıldı/taşındı.</value> @@ -6643,6 +6673,12 @@ Kaynak dosyaları buna göre yeniden adlandırıldı/taşındı.</value>
<data name="Templates.Project.GtkSharpProject.Name" xml:space="preserve">
<value>Gtk# Uygulaması</value>
</data>
<data name="Templates.Project.PortableLibrary.Description" xml:space="preserve">
<value>Windows, Silverlight, Windows Phone ve Xbox kullanılabilir Kitaplığı.</value>
</data>
<data name="Templates.Project.PortableLibrary.Name" xml:space="preserve">
<value>Taşınabilir Sınıf Kitaplığı</value>
</data>
<data name="Templates.Project.SetupProject.Description" xml:space="preserve">
<value>MSI Installer oluşturabilmek için bir Windows Installer projesi.</value>
</data>
@ -6728,7 +6764,7 @@ Kaynak dosyaları buna göre yeniden adlandırıldı/taşındı.</value> @@ -6728,7 +6764,7 @@ Kaynak dosyaları buna göre yeniden adlandırıldı/taşındı.</value>
<value>Kenarçubuğu Yapılandır...</value>
</data>
<data name="XML.MainMenu.Analysis" xml:space="preserve">
<value>&amp;Analiz</value>
<value>Analiz</value>
</data>
<data name="XML.MainMenu.BuildMenu" xml:space="preserve">
<value>Derle</value>
@ -6788,13 +6824,13 @@ Kaynak dosyaları buna göre yeniden adlandırıldı/taşındı.</value> @@ -6788,13 +6824,13 @@ Kaynak dosyaları buna göre yeniden adlandırıldı/taşındı.</value>
<value>Hata ayıklamaya devam et</value>
</data>
<data name="XML.MainMenu.DebugMenu.Continue.Description" xml:space="preserve">
<value>İşlemin yürütülmesine devam eder.</value>
<value>İşlemin yürütülmesine devam edilir.</value>
</data>
<data name="XML.MainMenu.DebugMenu.Detach" xml:space="preserve">
<value>Bırak</value>
</data>
<data name="XML.MainMenu.DebugMenu.Error.BadAssembly" xml:space="preserve">
<value>Programın .NET Framework sürüm numarası bulunamadı. Programın yönetilen çevirici olup olmadığını kontrol edin.</value>
<value>Programın .NET Framework sürüm numarası bulunamadı. Programın yönetilen derleme olup olmadığını kontrol edin.</value>
</data>
<data name="XML.MainMenu.DebugMenu.Error.CannotAttachToProcess" xml:space="preserve">
<value>İşleme eklenemiyor.</value>
@ -6827,7 +6863,7 @@ Kaynak dosyaları buna göre yeniden adlandırıldı/taşındı.</value> @@ -6827,7 +6863,7 @@ Kaynak dosyaları buna göre yeniden adlandırıldı/taşındı.</value>
<value>Önceki derlemeyi çalıştır</value>
</data>
<data name="XML.MainMenu.DebugMenu.RunWithoutDebug" xml:space="preserve">
<value>Hata ayıklayıcı olmadan çalıştır</value>
<value>Hata ayıklamadan çalıştır</value>
</data>
<data name="XML.MainMenu.DebugMenu.RunWithoutDebug.Description" xml:space="preserve">
<value>Programı normal olarak çalıştırır.</value>
@ -7235,7 +7271,7 @@ Kaynak dosyaları buna göre yeniden adlandırıldı/taşındı.</value> @@ -7235,7 +7271,7 @@ Kaynak dosyaları buna göre yeniden adlandırıldı/taşındı.</value>
<value>Tüm Yer İmlerini Temizle</value>
</data>
<data name="XML.MainMenu.SearchMenu.ClrBookmark.Description" xml:space="preserve">
<value>Mevcut tampondaki tüm yer imlerini temizle</value>
<value>Mevcut tampondaki tüm yer imlerini temizler</value>
</data>
<data name="XML.MainMenu.SearchMenu.Find" xml:space="preserve">
<value>Bul...</value>
@ -7326,7 +7362,7 @@ Başlatma hatası:</value> @@ -7326,7 +7362,7 @@ Başlatma hatası:</value>
<value>Kurulum</value>
</data>
<data name="XML.MainMenu.ViewMenu.SetupMenu.DialogsMenu" xml:space="preserve">
<value>Diyaloglar</value>
<value>İletişim Kutuları</value>
</data>
<data name="XML.MainMenu.ViewMenu.SetupMenu.FilesMenu" xml:space="preserve">
<value>Dosyalar</value>

18
src/AddIns/BackendBindings/VBNetBinding/Project/Src/FormattingStrategy/VBNetFormattingStrategy.cs

@ -832,22 +832,14 @@ namespace ICSharpCode.VBNetBinding @@ -832,22 +832,14 @@ namespace ICSharpCode.VBNetBinding
internal static bool IsBlockEnd(Token current, Token prev)
{
if (current.Kind == Tokens.Next) {
if (prev.Kind == Tokens.Resume)
return false;
else
return true;
}
if (current.Kind == Tokens.Next)
return prev.Kind == Tokens.EOL || prev.Kind == Tokens.Colon;
if (current.Kind == Tokens.Loop)
return true;
return prev.Kind == Tokens.EOL || prev.Kind == Tokens.Colon;
if (blockTokens.Contains(current.Kind)) {
if (prev.Kind == Tokens.End)
return true;
else
return false;
}
if (blockTokens.Contains(current.Kind))
return prev.Kind == Tokens.End;
return IsSpecialCase(current, prev);
}

48
src/AddIns/BackendBindings/VBNetBinding/Test/FormattingStrategy/IndentationTests.cs

@ -524,6 +524,54 @@ End Module"; @@ -524,6 +524,54 @@ End Module";
RunFormatTest(code, expected);
}
[Test]
public void ForNextOneLine()
{
string expected = @"Module Core
Sub Main
Dim a = 1
For i = 0 To 10 : Console.WriteLine(i) : Next
Dim b = 2
End Sub
End Module";
string code = @"Module Core
Sub Main
Dim a = 1
For i = 0 To 10 : Console.WriteLine(i) : Next
Dim b = 2
End Sub
End Module";
RunFormatTest(code, expected);
}
[Test]
public void RandomNext()
{
string expected = @"Module Core
Public Function GetRandomNumber( _
Optional ByVal Low As Integer = 1, _
Optional ByVal High As Integer = 100) As Integer
' Returns a random number,
' between the optional Low and High parameters
Return objRandom.Next(Low, High + 1)
End Function
End Module";
string code = @"Module Core
Public Function GetRandomNumber( _
Optional ByVal Low As Integer = 1, _
Optional ByVal High As Integer = 100) As Integer
' Returns a random number,
' between the optional Low and High parameters
Return objRandom.Next(Low, High + 1)
End Function
End Module";
RunFormatTest(code, expected);
}
void RunFormatTest(string code, string expectedCode)
{
AvalonEditTextEditorAdapter editor = new AvalonEditTextEditorAdapter(new TextEditor());

7
src/AddIns/Debugger/Debugger.Core/IDStringProvider.cs

@ -5,6 +5,7 @@ using System; @@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using Debugger.MetaData;
namespace Debugger
{
@ -42,6 +43,10 @@ namespace Debugger @@ -42,6 +43,10 @@ namespace Debugger
MethodInfo mr = (MethodInfo)member;
if (mr.IsGenericMethod) {
b.Append("``");
// DebugMethodInfo does not implement GetGenericArguments
if (mr is DebugMethodInfo)
b.Append(((DebugMethodInfo)mr).GenericParameterCount);
else
b.Append(mr.GetGenericArguments().Length);
}
parameters = mr.GetParameters();
@ -73,7 +78,7 @@ namespace Debugger @@ -73,7 +78,7 @@ namespace Debugger
return;
}
if (type.IsGenericType) {
AppendTypeNameWithArguments(b, type.GetElementType(), type.GetGenericArguments());
AppendTypeNameWithArguments(b, type, type.GetGenericArguments());
} else if (type.HasElementType) {
AppendTypeName(b, type.GetElementType());
if (type.IsArray) {

7
src/AddIns/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs

@ -195,6 +195,13 @@ namespace Debugger.MetaData @@ -195,6 +195,13 @@ namespace Debugger.MetaData
get { return this.MethodDefSig.GenericParameterCount > 0; }
}
/// <summary>
/// Gets the number of generic parameters on this method.
/// </summary>
public int GenericParameterCount {
get { return this.MethodDefSig.GenericParameterCount; }
}
/// <inheritdoc/>
public override RuntimeMethodHandle MethodHandle {
get { throw new NotSupportedException(); }

34
src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerGenerator/AbstractDesignerGenerator.cs

@ -339,16 +339,9 @@ namespace ICSharpCode.FormsDesigner @@ -339,16 +339,9 @@ namespace ICSharpCode.FormsDesigner
CodeMethodInvokeExpression invocation = (CodeMethodInvokeExpression)stmt.Expression;
CodeCastExpression expr = invocation.Method.TargetObject as CodeCastExpression;
if (expr != null) {
CodeFieldReferenceExpression fieldRef = expr.Expression as CodeFieldReferenceExpression;
if (fieldRef == null || !(fieldRef.TargetObject is CodeThisReferenceExpression))
continue;
if (expr.TargetType.BaseType != "System.ComponentModel.ISupportInitialize")
continue;
IField field = this.formClass.DefaultReturnType.GetFields()
.First(f => this.formClass.ProjectContent.Language.NameComparer.Equals(fieldRef.FieldName, f.Name));
if (field.ReturnType == null)
continue;
IClass fieldType = field.ReturnType.GetUnderlyingClass();
var fieldType = GetTypeOfControl(expr.Expression, initializeComponent, formClass);
if (fieldType == null)
continue;
if (!fieldType.IsTypeInInheritanceTree(iSupportInitializeInterface))
@ -361,6 +354,31 @@ namespace ICSharpCode.FormsDesigner @@ -361,6 +354,31 @@ namespace ICSharpCode.FormsDesigner
}
}
/// <summary>
/// Tries to find the type of the expression.
/// </summary>
IClass GetTypeOfControl(CodeExpression expression, CodeMemberMethod initializeComponentMethod, CodeTypeDeclaration formTypeDeclaration)
{
StringComparer comparer = formClass.ProjectContent.Language.NameComparer;
if (expression is CodeVariableReferenceExpression) {
string name = ((CodeVariableReferenceExpression)expression).VariableName;
var decl = initializeComponentMethod.Statements.OfType<CodeVariableDeclarationStatement>().Single(v => comparer.Equals(v.Name, name));
return formClass.ProjectContent.GetClass(decl.Type.BaseType, 0);
}
if (expression is CodeFieldReferenceExpression && ((CodeFieldReferenceExpression)expression).TargetObject is CodeThisReferenceExpression) {
string name = ((CodeFieldReferenceExpression)expression).FieldName;
var decl = formTypeDeclaration.Members.OfType<CodeMemberField>().FirstOrDefault(f => comparer.Equals(name, f.Name));
if (decl != null)
return formClass.ProjectContent.GetClass(decl.Type.BaseType, 0);
var field = formClass.DefaultReturnType.GetFields()
.First(f => comparer.Equals(f.Name, name));
if (field.ReturnType == null)
return null;
return field.ReturnType.GetUnderlyingClass();
}
return null;
}
/// <summary>
/// Compares the SharpDevelop.Dom field declaration oldField to
/// the CodeDom field declaration newField.

3
src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs

@ -159,6 +159,9 @@ namespace ICSharpCode.FormsDesigner @@ -159,6 +159,9 @@ namespace ICSharpCode.FormsDesigner
{
LoggingService.Debug("Forms designer: Load " + file.FileName + "; inMasterLoadOperation=" + this.inMasterLoadOperation);
if (this.typeResolutionService != null)
this.typeResolutionService.ClearCaches();
if (inMasterLoadOperation) {
if (this.sourceCodeStorage.ContainsFile(file)) {

39
src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/TypeResolutionService.cs

@ -361,6 +361,19 @@ namespace ICSharpCode.FormsDesigner.Services @@ -361,6 +361,19 @@ namespace ICSharpCode.FormsDesigner.Services
return GetType(name, throwOnError, false);
}
#if DEBUG
int count = 0;
#endif
Dictionary<string, Type> typeCache = new Dictionary<string, Type>(StringComparer.Ordinal);
Dictionary<string, Type> typeCacheIgnoreCase = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase);
public void ClearCaches()
{
typeCacheIgnoreCase.Clear();
typeCache.Clear();
}
public Type GetType(string name, bool throwOnError, bool ignoreCase)
{
if (name == null || name.Length == 0) {
@ -369,9 +382,19 @@ namespace ICSharpCode.FormsDesigner.Services @@ -369,9 +382,19 @@ namespace ICSharpCode.FormsDesigner.Services
if (IgnoreType(name)) {
return null;
}
if (ignoreCase) {
Type cachedType;
if (typeCacheIgnoreCase.TryGetValue(name, out cachedType))
return cachedType;
} else {
Type cachedType;
if (typeCache.TryGetValue(name, out cachedType))
return cachedType;
}
#if DEBUG
if (!name.StartsWith("System.")) {
LoggingService.Debug("TypeResolutionService: Looking for " + name);
count++;
LoggingService.Debug(count + " TypeResolutionService: Looking for " + name);
}
#endif
try {
@ -436,6 +459,7 @@ namespace ICSharpCode.FormsDesigner.Services @@ -436,6 +459,7 @@ namespace ICSharpCode.FormsDesigner.Services
try {
Type t = asm.GetType(name, false);
if (t != null) {
AddToCache(name, t, ignoreCase);
return t;
}
} catch (FileNotFoundException) {
@ -449,7 +473,7 @@ namespace ICSharpCode.FormsDesigner.Services @@ -449,7 +473,7 @@ namespace ICSharpCode.FormsDesigner.Services
if (throwOnError && type == null)
throw new TypeLoadException(name + " not found by TypeResolutionService");
AddToCache(name, type, ignoreCase);
return type;
} catch (Exception e) {
LoggingService.Error(e);
@ -457,6 +481,17 @@ namespace ICSharpCode.FormsDesigner.Services @@ -457,6 +481,17 @@ namespace ICSharpCode.FormsDesigner.Services
return null;
}
void AddToCache(string name, Type type, bool ignoreCase)
{
if (type == null)
return;
if (ignoreCase) {
typeCacheIgnoreCase.Add(name, type);
} else {
typeCache.Add(name, type);
}
}
public void ReferenceAssembly(AssemblyName name)
{
ICSharpCode.Core.LoggingService.Warn("TODO: Add Assembly reference : " + name);

9
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/WpfViewContent.cs

@ -60,6 +60,7 @@ namespace ICSharpCode.WpfDesign.AddIn @@ -60,6 +60,7 @@ namespace ICSharpCode.WpfDesign.AddIn
protected override void LoadInternal(OpenedFile file, System.IO.Stream stream)
{
wasChangedInDesigner = false;
Debug.Assert(file == this.PrimaryFile);
_stream = new MemoryStream();
@ -108,10 +109,11 @@ namespace ICSharpCode.WpfDesign.AddIn @@ -108,10 +109,11 @@ namespace ICSharpCode.WpfDesign.AddIn
}
private MemoryStream _stream;
bool wasChangedInDesigner;
protected override void SaveInternal(OpenedFile file, System.IO.Stream stream)
{
if (IsDirty && designer.DesignContext != null) {
if (wasChangedInDesigner && designer.DesignContext != null) {
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.IndentChars = EditorControlService.GlobalOptions.IndentationString;
@ -120,16 +122,14 @@ namespace ICSharpCode.WpfDesign.AddIn @@ -120,16 +122,14 @@ namespace ICSharpCode.WpfDesign.AddIn
designer.SaveDesigner(xmlWriter);
}
} else {
if (_stream.CanRead) {
_stream.Position = 0;
using (var reader = new StreamReader(_stream)) {
using (var reader = new StreamReader(new UnclosableStream(_stream))) {
using (var writer = new StreamWriter(stream)) {
writer.Write(reader.ReadToEnd());
}
}
}
}
}
void UpdateTasks(XamlErrorService xamlErrorService)
{
@ -153,6 +153,7 @@ namespace ICSharpCode.WpfDesign.AddIn @@ -153,6 +153,7 @@ namespace ICSharpCode.WpfDesign.AddIn
void OnUndoStackChanged(object sender, EventArgs e)
{
wasChangedInDesigner = true;
this.PrimaryFile.MakeDirty();
}

17
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/StackPanelPlacementSupport.cs

@ -109,19 +109,20 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions @@ -109,19 +109,20 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions
DrawVerticalRectangle(offset);
}
ChangePostionTo(info.Item.View, _indexToInsert);
ChangePositionTo(info.Item, _indexToInsert);
}
}
private void ChangePostionTo(UIElement element, int index)
private void ChangePositionTo(DesignItem element, int index)
{
int elementIndex = 0;
if (_stackPanel.Children.Contains(element))
elementIndex = _stackPanel.Children.IndexOf(element);
if (index > elementIndex)
if (this.ExtendedItem.ContentProperty == null || !this.ExtendedItem.ContentProperty.IsCollection)
return;
var elements = this.ExtendedItem.ContentProperty.CollectionElements;
int elementIndex = elements.IndexOf(element);
if (elementIndex >= 0 && index > elementIndex)
index--;
_stackPanel.Children.Remove(element);
_stackPanel.Children.Insert(index, element);
elements.Remove(element);
elements.Insert(index, element);
}
private double FindHorizontalRectanglePlacementOffset(Rect rect)

5
src/AddIns/VersionControl/SubversionAddIn/Src/Gui/ProjectBrowserVisitor/OverlayIconManager.cs

@ -192,7 +192,12 @@ namespace ICSharpCode.Svn @@ -192,7 +192,12 @@ namespace ICSharpCode.Svn
}
}
try {
return client.SingleStatus(fileName).TextStatus;
} catch (SvnClientException ex) {
LoggingService.Warn(ex);
return StatusKind.None;
}
}
}

3
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs

@ -943,7 +943,8 @@ namespace ICSharpCode.AvalonEdit.Rendering @@ -943,7 +943,8 @@ namespace ICSharpCode.AvalonEdit.Rendering
// number of pixels clipped from the first visual line(s)
clippedPixelsOnTop = scrollOffset.Y - heightTree.GetVisualPosition(firstLineInView);
Debug.Assert(clippedPixelsOnTop >= 0);
// clippedPixelsOnTop should be >= 0, except for floating point inaccurracy.
Debug.Assert(clippedPixelsOnTop >= -ExtensionMethods.Epsilon);
newVisualLines = new List<VisualLine>();

16
src/Libraries/ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -81,6 +81,8 @@ namespace ICSharpCode.Decompiler.Ast @@ -81,6 +81,8 @@ namespace ICSharpCode.Decompiler.Ast
return true;
if (settings.YieldReturn && YieldReturnDecompiler.IsCompilerGeneratorEnumerator(type))
return true;
if (settings.AsyncAwait && AsyncDecompiler.IsCompilerGeneratedStateMachine(type))
return true;
} else if (type.IsCompilerGenerated()) {
if (type.Name.StartsWith("<PrivateImplementationDetails>", StringComparison.Ordinal))
return true;
@ -770,6 +772,10 @@ namespace ICSharpCode.Decompiler.Ast @@ -770,6 +772,10 @@ namespace ICSharpCode.Decompiler.Ast
SetNewModifier(astMethod);
}
astMethod.Body = CreateMethodBody(methodDef, astMethod.Parameters);
if (context.CurrentMethodIsAsync) {
astMethod.Modifiers |= Modifiers.Async;
context.CurrentMethodIsAsync = false;
}
}
ConvertAttributes(astMethod, methodDef);
if (methodDef.HasCustomAttributes && astMethod.Parameters.Count > 0) {
@ -1342,6 +1348,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -1342,6 +1348,7 @@ namespace ICSharpCode.Decompiler.Ast
static void ConvertCustomAttributes(AstNode attributedNode, ICustomAttributeProvider customAttributeProvider, string attributeTarget = null)
{
EntityDeclaration entityDecl = attributedNode as EntityDeclaration;
if (customAttributeProvider.HasCustomAttributes) {
var attributes = new List<ICSharpCode.NRefactory.CSharp.Attribute>();
foreach (var customAttribute in customAttributeProvider.CustomAttributes.OrderBy(a => a.AttributeType.FullName)) {
@ -1353,6 +1360,15 @@ namespace ICSharpCode.Decompiler.Ast @@ -1353,6 +1360,15 @@ namespace ICSharpCode.Decompiler.Ast
// don't show the ParamArrayAttribute (it's converted to the 'params' modifier)
continue;
}
// if the method is async, remove [DebuggerStepThrough] and [Async
if (entityDecl != null && entityDecl.HasModifier(Modifiers.Async)) {
if (customAttribute.AttributeType.Name == "DebuggerStepThroughAttribute" && customAttribute.AttributeType.Namespace == "System.Diagnostics") {
continue;
}
if (customAttribute.AttributeType.Name == "AsyncStateMachineAttribute" && customAttribute.AttributeType.Namespace == "System.Runtime.CompilerServices") {
continue;
}
}
var attribute = new ICSharpCode.NRefactory.CSharp.Attribute();
attribute.AddAnnotation(customAttribute);

6
src/Libraries/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs

@ -58,6 +58,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -58,6 +58,7 @@ namespace ICSharpCode.Decompiler.Ast
MethodDefinition oldCurrentMethod = context.CurrentMethod;
Debug.Assert(oldCurrentMethod == null || oldCurrentMethod == methodDef);
context.CurrentMethod = methodDef;
context.CurrentMethodIsAsync = false;
try {
AstMethodBodyBuilder builder = new AstMethodBodyBuilder();
builder.methodDef = methodDef;
@ -847,8 +848,11 @@ namespace ICSharpCode.Decompiler.Ast @@ -847,8 +848,11 @@ namespace ICSharpCode.Decompiler.Ast
case ILCode.ExpressionTreeParameterDeclarations:
args[args.Count - 1].AddAnnotation(new ParameterDeclarationAnnotation(byteCode));
return args[args.Count - 1];
case ILCode.Await:
return new UnaryOperatorExpression(UnaryOperatorType.Await, arg1);
case ILCode.NullableOf:
case ILCode.ValueOf: return arg1;
case ILCode.ValueOf:
return arg1;
default:
throw new Exception("Unknown OpCode: " + byteCode.Code);
}

1
src/Libraries/ICSharpCode.Decompiler/Ast/DecompilerContext.cs

@ -33,6 +33,7 @@ namespace ICSharpCode.Decompiler @@ -33,6 +33,7 @@ namespace ICSharpCode.Decompiler
public TypeDefinition CurrentType;
public MethodDefinition CurrentMethod;
public DecompilerSettings Settings = new DecompilerSettings();
public bool CurrentMethodIsAsync;
// public ITypeResolveContext TypeResolveContext;
// public IProjectContent ProjectContent;

8
src/Libraries/ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs

@ -114,6 +114,9 @@ namespace ICSharpCode.Decompiler.Ast @@ -114,6 +114,9 @@ namespace ICSharpCode.Decompiler.Ast
object GetCurrentLocalDefinition()
{
AstNode node = nodeStack.Peek();
if (node is Identifier && node.Parent != null)
node = node.Parent;
var parameterDef = node.Annotation<ParameterDefinition>();
if (parameterDef != null)
return parameterDef;
@ -126,14 +129,11 @@ namespace ICSharpCode.Decompiler.Ast @@ -126,14 +129,11 @@ namespace ICSharpCode.Decompiler.Ast
//if (variable.OriginalVariable != null)
// return variable.OriginalVariable;
return variable;
} else {
}
}
var label = node as LabelStatement;
if (label != null)
{
if (label != null) {
var method = nodeStack.Select(nd => nd.Annotation<MethodReference>()).FirstOrDefault(mr => mr != null);
if (method != null)
return method.ToString() + label.Label;

1
src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs

@ -151,6 +151,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -151,6 +151,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
DecompilerContext subContext = context.Clone();
subContext.CurrentMethod = method;
subContext.CurrentMethodIsAsync = false;
subContext.ReservedVariableNames.AddRange(currentlyUsedVariableNames);
BlockStatement body = AstMethodBodyBuilder.CreateMethodBody(method, subContext, ame.Parameters);
TransformationPipeline.RunTransformationsUntil(body, v => v is DelegateConstruction, subContext);

15
src/Libraries/ICSharpCode.Decompiler/DecompilerSettings.cs

@ -72,6 +72,21 @@ namespace ICSharpCode.Decompiler @@ -72,6 +72,21 @@ namespace ICSharpCode.Decompiler
}
}
bool asyncAwait = true;
/// <summary>
/// Decompile async methods.
/// </summary>
public bool AsyncAwait {
get { return asyncAwait; }
set {
if (asyncAwait != value) {
asyncAwait = value;
OnPropertyChanged("AsyncAwait");
}
}
}
bool automaticProperties = true;
/// <summary>

3
src/Libraries/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -101,6 +101,7 @@ @@ -101,6 +101,7 @@
<Compile Include="FlowAnalysis\SsaOptimization.cs" />
<Compile Include="FlowAnalysis\SsaVariable.cs" />
<Compile Include="FlowAnalysis\TransformToSsa.cs" />
<Compile Include="ILAst\AsyncDecompiler.cs" />
<Compile Include="ILAst\LiftedOperators.cs" />
<Compile Include="ILAst\InitializerPeepholeTransforms.cs" />
<Compile Include="ILAst\DefaultDictionary.cs" />
@ -114,6 +115,8 @@ @@ -114,6 +115,8 @@
<Compile Include="ILAst\PatternMatching.cs" />
<Compile Include="ILAst\PeepholeTransform.cs" />
<Compile Include="ILAst\SimpleControlFlow.cs" />
<Compile Include="ILAst\StateRange.cs" />
<Compile Include="ILAst\SymbolicExecution.cs" />
<Compile Include="ILAst\TypeAnalysis.cs" />
<Compile Include="ILAst\YieldReturnDecompiler.cs" />
<Compile Include="ITextOutput.cs" />

653
src/Libraries/ICSharpCode.Decompiler/ILAst/AsyncDecompiler.cs

@ -0,0 +1,653 @@ @@ -0,0 +1,653 @@
// Copyright (c) 2012 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;
using System.Diagnostics;
using System.Linq;
using Mono.Cecil;
using Mono.Cecil.Cil;
namespace ICSharpCode.Decompiler.ILAst
{
/// <summary>
/// Decompiler step for C# 5 async/await.
/// </summary>
class AsyncDecompiler
{
public static bool IsCompilerGeneratedStateMachine(TypeDefinition type)
{
if (!(type.DeclaringType != null && type.IsCompilerGenerated()))
return false;
foreach (TypeReference i in type.Interfaces) {
if (i.Namespace == "System.Runtime.CompilerServices" && i.Name == "IAsyncStateMachine")
return true;
}
return false;
}
enum AsyncMethodType
{
Void,
Task,
TaskOfT
}
DecompilerContext context;
// These fields are set by MatchTaskCreationPattern()
AsyncMethodType methodType;
int initialState;
TypeDefinition stateMachineStruct;
MethodDefinition moveNextMethod;
FieldDefinition builderField;
FieldDefinition stateField;
Dictionary<FieldDefinition, ILVariable> fieldToParameterMap = new Dictionary<FieldDefinition, ILVariable>();
// These fields are set by AnalyzeMoveNext()
int finalState = -2;
ILTryCatchBlock mainTryCatch;
ILLabel setResultAndExitLabel;
ILLabel exitLabel;
ILExpression resultExpr;
#region RunStep1() method
public static void RunStep1(DecompilerContext context, ILBlock method)
{
if (!context.Settings.AsyncAwait)
return; // abort if async decompilation is disabled
var yrd = new AsyncDecompiler();
yrd.context = context;
if (!yrd.MatchTaskCreationPattern(method))
return;
#if DEBUG
if (Debugger.IsAttached) {
yrd.Run();
} else {
#endif
try {
yrd.Run();
} catch (SymbolicAnalysisFailedException) {
return;
}
#if DEBUG
}
#endif
context.CurrentMethodIsAsync = true;
method.Body.Clear();
method.EntryGoto = null;
method.Body.AddRange(yrd.newTopLevelBody);
ILAstOptimizer.RemoveRedundantCode(method);
}
void Run()
{
AnalyzeMoveNext();
ValidateCatchBlock(mainTryCatch.CatchBlocks[0]);
AnalyzeStateMachine(mainTryCatch.TryBlock);
// AnalyzeStateMachine invokes ConvertBody
MarkGeneratedVariables();
YieldReturnDecompiler.TranslateFieldsToLocalAccess(newTopLevelBody, fieldToParameterMap);
}
#endregion
#region MatchTaskCreationPattern
bool MatchTaskCreationPattern(ILBlock method)
{
if (method.Body.Count < 5)
return false;
// Check the second-to-last instruction (the start call) first, as we can get the most information from that
MethodReference startMethod;
ILExpression loadStartTarget, loadStartArgument;
// call(AsyncTaskMethodBuilder::Start, ldloca(builder), ldloca(stateMachine))
if (!method.Body[method.Body.Count - 2].Match(ILCode.Call, out startMethod, out loadStartTarget, out loadStartArgument))
return false;
if (startMethod.Name != "Start" || startMethod.DeclaringType == null || startMethod.DeclaringType.Namespace != "System.Runtime.CompilerServices")
return false;
switch (startMethod.DeclaringType.Name) {
case "AsyncTaskMethodBuilder`1":
methodType = AsyncMethodType.TaskOfT;
break;
case "AsyncTaskMethodBuilder":
methodType = AsyncMethodType.Task;
break;
case "AsyncVoidMethodBuilder":
methodType = AsyncMethodType.Void;
break;
default:
return false;
}
ILVariable stateMachineVar, builderVar;
if (!loadStartTarget.Match(ILCode.Ldloca, out builderVar))
return false;
if (!loadStartArgument.Match(ILCode.Ldloca, out stateMachineVar))
return false;
stateMachineStruct = stateMachineVar.Type.ResolveWithinSameModule();
if (stateMachineStruct == null || !stateMachineStruct.IsValueType)
return false;
moveNextMethod = stateMachineStruct.Methods.FirstOrDefault(f => f.Name == "MoveNext");
if (moveNextMethod == null)
return false;
// Check third-to-last instruction (copy of builder):
// stloc(builder, ldfld(StateMachine::<>t__builder, ldloca(stateMachine)))
ILExpression loadBuilderExpr;
if (!method.Body[method.Body.Count - 3].MatchStloc(builderVar, out loadBuilderExpr))
return false;
FieldReference builderFieldRef;
ILExpression loadStateMachineForBuilderExpr;
if (!loadBuilderExpr.Match(ILCode.Ldfld, out builderFieldRef, out loadStateMachineForBuilderExpr))
return false;
if (!loadStateMachineForBuilderExpr.MatchLdloca(stateMachineVar))
return false;
builderField = builderFieldRef.ResolveWithinSameModule();
if (builderField == null)
return false;
// Check the last instruction (ret)
if (methodType == AsyncMethodType.Void) {
if (!method.Body[method.Body.Count - 1].Match(ILCode.Ret))
return false;
} else {
// ret(call(AsyncTaskMethodBuilder::get_Task, ldflda(StateMachine::<>t__builder, ldloca(stateMachine))))
ILExpression returnValue;
if (!method.Body[method.Body.Count - 1].Match(ILCode.Ret, out returnValue))
return false;
MethodReference getTaskMethod;
ILExpression builderExpr;
if (!returnValue.Match(ILCode.Call, out getTaskMethod, out builderExpr))
return false;
ILExpression loadStateMachineForBuilderExpr2;
FieldReference builderField2;
if (!builderExpr.Match(ILCode.Ldflda, out builderField2, out loadStateMachineForBuilderExpr2))
return false;
if (builderField2.ResolveWithinSameModule() != builderField || !loadStateMachineForBuilderExpr2.MatchLdloca(stateMachineVar))
return false;
}
// Check the last field assignment - this should be the state field
ILExpression initialStateExpr;
if (!MatchStFld(method.Body[method.Body.Count - 4], stateMachineVar, out stateField, out initialStateExpr))
return false;
if (!initialStateExpr.Match(ILCode.Ldc_I4, out initialState))
return false;
if (initialState != -1)
return false;
// Check the second-to-last field assignment - this should be the builder field
FieldDefinition builderField3;
ILExpression builderInitialization;
if (!MatchStFld(method.Body[method.Body.Count - 5], stateMachineVar, out builderField3, out builderInitialization))
return false;
MethodReference createMethodRef;
if (builderField3 != builderField || !builderInitialization.Match(ILCode.Call, out createMethodRef))
return false;
if (createMethodRef.Name != "Create")
return false;
for (int i = 0; i < method.Body.Count - 5; i++) {
FieldDefinition field;
ILExpression fieldInit;
if (!MatchStFld(method.Body[i], stateMachineVar, out field, out fieldInit))
return false;
ILVariable v;
if (!fieldInit.Match(ILCode.Ldloc, out v))
return false;
if (!v.IsParameter)
return false;
fieldToParameterMap[field] = v;
}
return true;
}
static bool MatchStFld(ILNode stfld, ILVariable stateMachineVar, out FieldDefinition field, out ILExpression expr)
{
field = null;
FieldReference fieldRef;
ILExpression ldloca;
if (!stfld.Match(ILCode.Stfld, out fieldRef, out ldloca, out expr))
return false;
field = fieldRef.ResolveWithinSameModule();
return field != null && ldloca.MatchLdloca(stateMachineVar);
}
#endregion
#region Analyze MoveNext
void AnalyzeMoveNext()
{
ILBlock ilMethod = CreateILAst(moveNextMethod);
if (ilMethod.Body.Count != 6)
throw new SymbolicAnalysisFailedException();
mainTryCatch = ilMethod.Body[0] as ILTryCatchBlock;
if (mainTryCatch == null || mainTryCatch.CatchBlocks.Count != 1)
throw new SymbolicAnalysisFailedException();
if (mainTryCatch.FaultBlock != null || mainTryCatch.FinallyBlock != null)
throw new SymbolicAnalysisFailedException();
setResultAndExitLabel = ilMethod.Body[1] as ILLabel;
if (setResultAndExitLabel == null)
throw new SymbolicAnalysisFailedException();
if (!MatchStateAssignment(ilMethod.Body[2], out finalState))
throw new SymbolicAnalysisFailedException();
// call(AsyncTaskMethodBuilder`1::SetResult, ldflda(StateMachine::<>t__builder, ldloc(this)), ldloc(<>t__result))
MethodReference setResultMethod;
ILExpression builderExpr;
if (methodType == AsyncMethodType.TaskOfT) {
if (!ilMethod.Body[3].Match(ILCode.Call, out setResultMethod, out builderExpr, out resultExpr))
throw new SymbolicAnalysisFailedException();
} else {
if (!ilMethod.Body[3].Match(ILCode.Call, out setResultMethod, out builderExpr))
throw new SymbolicAnalysisFailedException();
}
if (!(setResultMethod.Name == "SetResult" && IsBuilderFieldOnThis(builderExpr)))
throw new SymbolicAnalysisFailedException();
exitLabel = ilMethod.Body[4] as ILLabel;
if (exitLabel == null)
throw new SymbolicAnalysisFailedException();
}
/// <summary>
/// Creates ILAst for the specified method, optimized up to before the 'YieldReturn' step.
/// </summary>
ILBlock CreateILAst(MethodDefinition method)
{
if (method == null || !method.HasBody)
throw new SymbolicAnalysisFailedException();
ILBlock ilMethod = new ILBlock();
ILAstBuilder astBuilder = new ILAstBuilder();
ilMethod.Body = astBuilder.Build(method, true, context);
ILAstOptimizer optimizer = new ILAstOptimizer();
optimizer.Optimize(context, ilMethod, ILAstOptimizationStep.YieldReturn);
return ilMethod;
}
void ValidateCatchBlock(ILTryCatchBlock.CatchBlock catchBlock)
{
if (catchBlock.ExceptionType == null || catchBlock.ExceptionType.Name != "Exception")
throw new SymbolicAnalysisFailedException();
if (catchBlock.Body.Count != 3)
throw new SymbolicAnalysisFailedException();
int stateID;
if (!(MatchStateAssignment(catchBlock.Body[0], out stateID) && stateID == finalState))
throw new SymbolicAnalysisFailedException();
MethodReference setExceptionMethod;
ILExpression builderExpr, exceptionExpr;
if (!catchBlock.Body[1].Match(ILCode.Call, out setExceptionMethod, out builderExpr, out exceptionExpr))
throw new SymbolicAnalysisFailedException();
if (!(setExceptionMethod.Name == "SetException" && IsBuilderFieldOnThis(builderExpr) && exceptionExpr.MatchLdloc(catchBlock.ExceptionVariable)))
throw new SymbolicAnalysisFailedException();
ILLabel label;
if (!(catchBlock.Body[2].Match(ILCode.Leave, out label) && label == exitLabel))
throw new SymbolicAnalysisFailedException();
}
bool IsBuilderFieldOnThis(ILExpression builderExpr)
{
// ldflda(StateMachine::<>t__builder, ldloc(this))
FieldReference fieldRef;
ILExpression target;
return builderExpr.Match(ILCode.Ldflda, out fieldRef, out target)
&& fieldRef.ResolveWithinSameModule() == builderField
&& target.MatchThis();
}
bool MatchStateAssignment(ILNode stfld, out int stateID)
{
// stfld(StateMachine::<>1__state, ldloc(this), ldc.i4(-2))
stateID = 0;
FieldReference fieldRef;
ILExpression target, val;
if (stfld.Match(ILCode.Stfld, out fieldRef, out target, out val)) {
return fieldRef.ResolveWithinSameModule() == stateField
&& target.MatchThis()
&& val.Match(ILCode.Ldc_I4, out stateID);
}
return false;
}
#endregion
#region AnalyzeStateMachine
ILVariable doFinallyBodies;
List<ILNode> newTopLevelBody;
void AnalyzeStateMachine(ILBlock block)
{
var body = block.Body;
if (body.Count == 0)
throw new SymbolicAnalysisFailedException();
if (DetectDoFinallyBodies(body)) {
body.RemoveAt(0);
if (body.Count == 0)
throw new SymbolicAnalysisFailedException();
}
StateRangeAnalysis rangeAnalysis = new StateRangeAnalysis(body[0], StateRangeAnalysisMode.AsyncMoveNext, stateField);
int bodyLength = block.Body.Count;
int pos = rangeAnalysis.AssignStateRanges(body, bodyLength);
rangeAnalysis.EnsureLabelAtPos(body, ref pos, ref bodyLength);
var labelStateRangeMapping = rangeAnalysis.CreateLabelRangeMapping(body, pos, bodyLength);
newTopLevelBody = ConvertBody(body, pos, bodyLength, labelStateRangeMapping);
newTopLevelBody.Insert(0, MakeGoTo(labelStateRangeMapping, initialState));
newTopLevelBody.Add(setResultAndExitLabel);
if (methodType == AsyncMethodType.TaskOfT) {
newTopLevelBody.Add(new ILExpression(ILCode.Ret, null, resultExpr));
} else {
newTopLevelBody.Add(new ILExpression(ILCode.Ret, null));
}
}
bool DetectDoFinallyBodies(List<ILNode> body)
{
ILVariable v;
ILExpression initExpr;
if (!body[0].Match(ILCode.Stloc, out v, out initExpr))
return false;
int initialValue;
if (!(initExpr.Match(ILCode.Ldc_I4, out initialValue) && initialValue == 1))
return false;
doFinallyBodies = v;
return true;
}
#endregion
#region ConvertBody
ILExpression MakeGoTo(LabelRangeMapping mapping, int state)
{
foreach (var pair in mapping) {
if (pair.Value.Contains(state))
return new ILExpression(ILCode.Br, pair.Key);
}
throw new SymbolicAnalysisFailedException();
}
List<ILNode> ConvertBody(List<ILNode> body, int startPos, int bodyLength, LabelRangeMapping mapping)
{
List<ILNode> newBody = new List<ILNode>();
// Copy all instructions from the old body to newBody.
for (int pos = startPos; pos < bodyLength; pos++) {
ILTryCatchBlock tryCatchBlock = body[pos] as ILTryCatchBlock;
ILExpression expr = body[pos] as ILExpression;
if (expr != null && expr.Code == ILCode.Leave && expr.Operand == exitLabel) {
ILVariable awaiterVar;
FieldDefinition awaiterField;
int targetStateID;
HandleAwait(newBody, out awaiterVar, out awaiterField, out targetStateID);
MarkAsGeneratedVariable(awaiterVar);
newBody.Add(new ILExpression(ILCode.Await, null, new ILExpression(ILCode.Ldloca, awaiterVar)));
newBody.Add(MakeGoTo(mapping, targetStateID));
} else if (tryCatchBlock != null) {
ILTryCatchBlock newTryCatchBlock = new ILTryCatchBlock();
var tryBody = tryCatchBlock.TryBlock.Body;
if (tryBody.Count == 0)
throw new SymbolicAnalysisFailedException();
StateRangeAnalysis rangeAnalysis = new StateRangeAnalysis(tryBody[0], StateRangeAnalysisMode.AsyncMoveNext, stateField);
int tryBodyLength = tryBody.Count;
int posInTryBody = rangeAnalysis.AssignStateRanges(tryBody, tryBodyLength);
rangeAnalysis.EnsureLabelAtPos(tryBody, ref posInTryBody, ref tryBodyLength);
var mappingInTryBlock = rangeAnalysis.CreateLabelRangeMapping(tryBody, posInTryBody, tryBodyLength);
var newTryBody = ConvertBody(tryBody, posInTryBody, tryBodyLength, mappingInTryBlock);
newTryBody.Insert(0, MakeGoTo(mappingInTryBlock, initialState));
// If there's a label at the beginning of the state dispatcher, copy that
if (posInTryBody > 0 && tryBody.FirstOrDefault() is ILLabel)
newTryBody.Insert(0, tryBody.First());
newTryCatchBlock.TryBlock = new ILBlock(newTryBody);
newTryCatchBlock.CatchBlocks = new List<ILTryCatchBlock.CatchBlock>(tryCatchBlock.CatchBlocks);
newTryCatchBlock.FaultBlock = tryCatchBlock.FaultBlock;
if (tryCatchBlock.FinallyBlock != null)
newTryCatchBlock.FinallyBlock = new ILBlock(ConvertFinally(tryCatchBlock.FinallyBlock.Body));
newBody.Add(newTryCatchBlock);
} else {
newBody.Add(body[pos]);
}
}
return newBody;
}
List<ILNode> ConvertFinally(List<ILNode> body)
{
List<ILNode> newBody = new List<ILNode>(body);
ILLabel endFinallyLabel;
ILExpression ceqExpr;
if (newBody.Count > 0 && newBody[0].Match(ILCode.Brtrue, out endFinallyLabel, out ceqExpr)) {
ILExpression loadDoFinallyBodies, loadZero;
object unused;
if (ceqExpr.Match(ILCode.Ceq, out unused, out loadDoFinallyBodies, out loadZero)) {
int num;
if (loadDoFinallyBodies.MatchLdloc(doFinallyBodies) && loadZero.Match(ILCode.Ldc_I4, out num) && num == 0) {
newBody.RemoveAt(0);
}
} else if (ceqExpr.Match(ILCode.LogicNot, out loadDoFinallyBodies)) {
if (loadDoFinallyBodies.MatchLdloc(doFinallyBodies)) {
newBody.RemoveAt(0);
}
}
}
return newBody;
}
void HandleAwait(List<ILNode> newBody, out ILVariable awaiterVar, out FieldDefinition awaiterField, out int targetStateID)
{
// Handle the instructions prior to the exit out of the method to detect what is being awaited.
// (analyses the last instructions in newBody and removes the analyzed instructions from newBody)
if (doFinallyBodies != null) {
// stloc(<>t__doFinallyBodies, ldc.i4(0))
ILExpression dfbInitExpr;
if (!newBody.LastOrDefault().MatchStloc(doFinallyBodies, out dfbInitExpr))
throw new SymbolicAnalysisFailedException();
int val;
if (!(dfbInitExpr.Match(ILCode.Ldc_I4, out val) && val == 0))
throw new SymbolicAnalysisFailedException();
newBody.RemoveAt(newBody.Count - 1); // remove doFinallyBodies assignment
}
// call(AsyncTaskMethodBuilder::AwaitUnsafeOnCompleted, ldflda(StateMachine::<>t__builder, ldloc(this)), ldloca(CS$0$0001), ldloc(this))
ILExpression callAwaitUnsafeOnCompleted = newBody.LastOrDefault() as ILExpression;
newBody.RemoveAt(newBody.Count - 1); // remove AwaitUnsafeOnCompleted call
if (callAwaitUnsafeOnCompleted == null || callAwaitUnsafeOnCompleted.Code != ILCode.Call)
throw new SymbolicAnalysisFailedException();
if (((MethodReference)callAwaitUnsafeOnCompleted.Operand).Name != "AwaitUnsafeOnCompleted")
throw new SymbolicAnalysisFailedException();
if (callAwaitUnsafeOnCompleted.Arguments.Count != 3)
throw new SymbolicAnalysisFailedException();
if (!callAwaitUnsafeOnCompleted.Arguments[1].Match(ILCode.Ldloca, out awaiterVar))
throw new SymbolicAnalysisFailedException();
// stfld(StateMachine::<>u__$awaiter6, ldloc(this), ldloc(CS$0$0001))
FieldReference awaiterFieldRef;
ILExpression loadThis, loadAwaiterVar;
if (!newBody.LastOrDefault().Match(ILCode.Stfld, out awaiterFieldRef, out loadThis, out loadAwaiterVar))
throw new SymbolicAnalysisFailedException();
newBody.RemoveAt(newBody.Count - 1); // remove awaiter field assignment
awaiterField = awaiterFieldRef.ResolveWithinSameModule();
if (!(awaiterField != null && loadThis.MatchThis() && loadAwaiterVar.MatchLdloc(awaiterVar)))
throw new SymbolicAnalysisFailedException();
// stfld(StateMachine::<>1__state, ldloc(this), ldc.i4(0))
if (!MatchStateAssignment(newBody.LastOrDefault(), out targetStateID))
throw new SymbolicAnalysisFailedException();
newBody.RemoveAt(newBody.Count - 1); // remove awaiter field assignment
}
#endregion
#region MarkGeneratedVariables
int smallestGeneratedVariableIndex = int.MaxValue;
void MarkAsGeneratedVariable(ILVariable v)
{
if (v.OriginalVariable != null && v.OriginalVariable.Index >= 0) {
smallestGeneratedVariableIndex = Math.Min(smallestGeneratedVariableIndex, v.OriginalVariable.Index);
}
}
void MarkGeneratedVariables()
{
var expressions = new ILBlock(newTopLevelBody).GetSelfAndChildrenRecursive<ILExpression>();
foreach (var v in expressions.Select(e => e.Operand).OfType<ILVariable>()) {
if (v.OriginalVariable != null && v.OriginalVariable.Index >= smallestGeneratedVariableIndex)
v.IsGenerated = true;
}
}
#endregion
#region RunStep2() method
public static void RunStep2(DecompilerContext context, ILBlock method)
{
if (context.CurrentMethodIsAsync) {
Step2(method.Body);
ILAstOptimizer.RemoveRedundantCode(method);
// Repeat the inlining/copy propagation optimization because the conversion of field access
// to local variables can open up additional inlining possibilities.
ILInlining inlining = new ILInlining(method);
inlining.InlineAllVariables();
inlining.CopyPropagation();
}
}
static void Step2(List<ILNode> body)
{
for (int pos = 0; pos < body.Count; pos++) {
ILTryCatchBlock tc = body[pos] as ILTryCatchBlock;
if (tc != null) {
Step2(tc.TryBlock.Body);
} else {
Step2(body, ref pos);
}
}
}
static bool Step2(List<ILNode> body, ref int pos)
{
// stloc(CS$0$0001, callvirt(class System.Threading.Tasks.Task`1<bool>::GetAwaiter, awaiterExpr)
// brtrue(IL_7C, call(valuetype [mscorlib]System.Runtime.CompilerServices.TaskAwaiter`1<bool>::get_IsCompleted, ldloca(CS$0$0001)))
// await(ldloca(CS$0$0001))
// ...
// IL_7C:
// arg_8B_0 = call(valuetype [mscorlib]System.Runtime.CompilerServices.TaskAwaiter`1<bool>::GetResult, ldloca(CS$0$0001))
// initobj(valuetype [mscorlib]System.Runtime.CompilerServices.TaskAwaiter`1<bool>, ldloca(CS$0$0001))
ILExpression loadAwaiter;
ILVariable awaiterVar;
if (!body[pos].Match(ILCode.Await, out loadAwaiter))
return false;
if (!loadAwaiter.Match(ILCode.Ldloca, out awaiterVar))
return false;
ILVariable stackVar;
ILExpression stackExpr;
while (pos >= 1 && body[pos - 1].Match(ILCode.Stloc, out stackVar, out stackExpr))
pos--;
// stloc(CS$0$0001, callvirt(class System.Threading.Tasks.Task`1<bool>::GetAwaiter, awaiterExpr)
ILExpression getAwaiterCall;
if (!(pos >= 2 && body[pos - 2].MatchStloc(awaiterVar, out getAwaiterCall)))
return false;
MethodReference getAwaiterMethod;
ILExpression awaitedExpr;
if (!(getAwaiterCall.Match(ILCode.Call, out getAwaiterMethod, out awaitedExpr) || getAwaiterCall.Match(ILCode.Callvirt, out getAwaiterMethod, out awaitedExpr)))
return false;
if (awaitedExpr.Code == ILCode.AddressOf) {
// remove 'AddressOf()' when calling GetAwaiter() on a value type
awaitedExpr = awaitedExpr.Arguments[0];
}
// brtrue(IL_7C, call(valuetype [mscorlib]System.Runtime.CompilerServices.TaskAwaiter`1<bool>::get_IsCompleted, ldloca(CS$0$0001)))
ILLabel label;
ILExpression getIsCompletedCall;
if (!(pos >= 1 && body[pos - 1].Match(ILCode.Brtrue, out label, out getIsCompletedCall)))
return false;
int labelPos = body.IndexOf(label);
if (labelPos < pos)
return false;
for (int i = pos + 1; i < labelPos; i++) {
// validate that we aren't deleting any unexpected instructions -
// between the await and the label, there should only be the stack, awaiter and state logic
ILExpression expr = body[i] as ILExpression;
if (expr == null)
return false;
switch (expr.Code) {
case ILCode.Stloc:
case ILCode.Initobj:
case ILCode.Stfld:
case ILCode.Await:
// e.g.
// stloc(CS$0$0001, ldfld(StateMachine::<>u__$awaitere, ldloc(this)))
// initobj(valuetype [mscorlib]System.Runtime.CompilerServices.TaskAwaiter`1<bool>, ldloca(CS$0$0002_66))
// stfld('<AwaitInLoopCondition>d__d'::<>u__$awaitere, ldloc(this), ldloc(CS$0$0002_66))
// stfld('<AwaitInLoopCondition>d__d'::<>1__state, ldloc(this), ldc.i4(-1))
break;
default:
return false;
}
}
if (labelPos + 1 >= body.Count)
return false;
ILExpression resultAssignment = body[labelPos + 1] as ILExpression;
ILVariable resultVar;
ILExpression getResultCall;
bool isResultAssignment = resultAssignment.Match(ILCode.Stloc, out resultVar, out getResultCall);
if (!isResultAssignment)
getResultCall = resultAssignment;
if (!(getResultCall.Operand is MethodReference && ((MethodReference)getResultCall.Operand).Name == "GetResult"))
return false;
pos -= 2; // also delete 'stloc', 'brtrue' and 'await'
body.RemoveRange(pos, labelPos - pos);
Debug.Assert(body[pos] == label);
pos++;
if (isResultAssignment) {
Debug.Assert(body[pos] == resultAssignment);
resultAssignment.Arguments[0] = new ILExpression(ILCode.Await, null, awaitedExpr);
} else {
body[pos] = new ILExpression(ILCode.Await, null, awaitedExpr);
}
// if the awaiter variable is cleared out in the next instruction, remove that instruction
if (IsVariableReset(body.ElementAtOrDefault(pos + 1), awaiterVar)) {
body.RemoveAt(pos + 1);
}
return true;
}
static bool IsVariableReset(ILNode expr, ILVariable variable)
{
object unused;
ILExpression ldloca;
return expr.Match(ILCode.Initobj, out unused, out ldloca) && ldloca.MatchLdloca(variable);
}
#endregion
}
}

13
src/Libraries/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs

@ -35,6 +35,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -35,6 +35,7 @@ namespace ICSharpCode.Decompiler.ILAst
InlineVariables,
CopyPropagation,
YieldReturn,
AsyncAwait,
PropertyAccessInstructions,
SplitToMovableBlocks,
TypeInference,
@ -107,6 +108,10 @@ namespace ICSharpCode.Decompiler.ILAst @@ -107,6 +108,10 @@ namespace ICSharpCode.Decompiler.ILAst
if (abortBeforeStep == ILAstOptimizationStep.YieldReturn) return;
YieldReturnDecompiler.Run(context, method);
AsyncDecompiler.RunStep1(context, method);
if (abortBeforeStep == ILAstOptimizationStep.AsyncAwait) return;
AsyncDecompiler.RunStep2(context, method);
if (abortBeforeStep == ILAstOptimizationStep.PropertyAccessInstructions) return;
IntroducePropertyAccessInstructions(method);
@ -256,7 +261,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -256,7 +261,7 @@ namespace ICSharpCode.Decompiler.ILAst
/// Ignore arguments of 'leave'
/// </summary>
/// <param name="method"></param>
void RemoveRedundantCode(ILBlock method)
internal static void RemoveRedundantCode(ILBlock method)
{
Dictionary<ILLabel, int> labelRefCount = new Dictionary<ILLabel, int>();
foreach (ILLabel target in method.GetSelfAndChildrenRecursive<ILExpression>(e => e.IsBranch()).SelectMany(e => e.GetBranchTargets())) {
@ -285,10 +290,16 @@ namespace ICSharpCode.Decompiler.ILAst @@ -285,10 +290,16 @@ namespace ICSharpCode.Decompiler.ILAst
if (i - 1 >= 0 && body[i - 1].Match(ILCode.Stloc, out prevVar, out prevExpr) && prevVar == v)
prevExpr.ILRanges.AddRange(((ILExpression)body[i]).ILRanges);
// Ignore pop
} else {
ILLabel label = body[i] as ILLabel;
if (label != null) {
if (labelRefCount.GetOrDefault(label) > 0)
newBody.Add(label);
} else {
newBody.Add(body[i]);
}
}
}
block.Body = newBody;
}

6
src/Libraries/ICSharpCode.Decompiler/ILAst/ILCodes.cs

@ -333,7 +333,11 @@ namespace ICSharpCode.Decompiler.ILAst @@ -333,7 +333,11 @@ namespace ICSharpCode.Decompiler.ILAst
/// The last child of this node is the call constructing the expression tree, all other children are the
/// assignments to the ParameterExpression variables.
/// </summary>
ExpressionTreeParameterDeclarations
ExpressionTreeParameterDeclarations,
/// <summary>
/// C# 5 await
/// </summary>
Await
}
public static class ILCodeUtil

12
src/Libraries/ICSharpCode.Decompiler/ILAst/PatternMatching.cs

@ -155,5 +155,17 @@ namespace ICSharpCode.Decompiler.ILAst @@ -155,5 +155,17 @@ namespace ICSharpCode.Decompiler.ILAst
ILVariable v;
return node.Match(ILCode.Ldloc, out v) && v == expectedVar;
}
public static bool MatchLdloca(this ILNode node, ILVariable expectedVar)
{
ILVariable v;
return node.Match(ILCode.Ldloca, out v) && v == expectedVar;
}
public static bool MatchStloc(this ILNode node, ILVariable expectedVar, out ILExpression expr)
{
ILVariable v;
return node.Match(ILCode.Stloc, out v, out expr) && v == expectedVar;
}
}
}

310
src/Libraries/ICSharpCode.Decompiler/ILAst/StateRange.cs

@ -0,0 +1,310 @@ @@ -0,0 +1,310 @@
// Copyright (c) 2012 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;
using System.Diagnostics;
using System.Linq;
using Mono.Cecil;
namespace ICSharpCode.Decompiler.ILAst
{
struct Interval
{
public readonly int Start, End;
public Interval(int start, int end)
{
Debug.Assert(start <= end || (start == 0 && end == -1));
this.Start = start;
this.End = end;
}
public override string ToString()
{
return string.Format("({0} to {1})", Start, End);
}
}
class StateRange
{
readonly List<Interval> data = new List<Interval>();
public StateRange()
{
}
public StateRange(int start, int end)
{
this.data.Add(new Interval(start, end));
}
public bool IsEmpty {
get { return data.Count == 0; }
}
public bool Contains(int val)
{
foreach (Interval v in data) {
if (v.Start <= val && val <= v.End)
return true;
}
return false;
}
public void UnionWith(StateRange other)
{
data.AddRange(other.data);
}
/// <summary>
/// Unions this state range with (other intersect (minVal to maxVal))
/// </summary>
public void UnionWith(StateRange other, int minVal, int maxVal)
{
foreach (Interval v in other.data) {
int start = Math.Max(v.Start, minVal);
int end = Math.Min(v.End, maxVal);
if (start <= end)
data.Add(new Interval(start, end));
}
}
/// <summary>
/// Merges overlapping interval ranges.
/// </summary>
public void Simplify()
{
if (data.Count < 2)
return;
data.Sort((a, b) => a.Start.CompareTo(b.Start));
Interval prev = data[0];
int prevIndex = 0;
for (int i = 1; i < data.Count; i++) {
Interval next = data[i];
Debug.Assert(prev.Start <= next.Start);
if (next.Start <= prev.End + 1) { // intervals overlapping or touching
prev = new Interval(prev.Start, Math.Max(prev.End, next.End));
data[prevIndex] = prev;
data[i] = new Interval(0, -1); // mark as deleted
} else {
prev = next;
prevIndex = i;
}
}
data.RemoveAll(i => i.Start > i.End); // remove all entries that were marked as deleted
}
public override string ToString()
{
return string.Join(",", data);
}
public Interval ToEnclosingInterval()
{
if (data.Count == 0)
throw new SymbolicAnalysisFailedException();
return new Interval(data[0].Start, data[data.Count - 1].End);
}
}
enum StateRangeAnalysisMode
{
IteratorMoveNext,
IteratorDispose,
AsyncMoveNext
}
class StateRangeAnalysis
{
readonly StateRangeAnalysisMode mode;
readonly FieldDefinition stateField;
internal DefaultDictionary<ILNode, StateRange> ranges;
SymbolicEvaluationContext evalContext;
internal Dictionary<MethodDefinition, Interval> finallyMethodToStateInterval; // used only for IteratorDispose
/// <summary>
/// Initializes the state range logic:
/// Clears 'ranges' and sets 'ranges[entryPoint]' to the full range (int.MinValue to int.MaxValue)
/// </summary>
public StateRangeAnalysis(ILNode entryPoint, StateRangeAnalysisMode mode, FieldDefinition stateField)
{
this.mode = mode;
this.stateField = stateField;
if (mode == StateRangeAnalysisMode.IteratorDispose) {
finallyMethodToStateInterval = new Dictionary<MethodDefinition, Interval>();
}
ranges = new DefaultDictionary<ILNode, StateRange>(n => new StateRange());
ranges[entryPoint] = new StateRange(int.MinValue, int.MaxValue);
evalContext = new SymbolicEvaluationContext(stateField);
}
public int AssignStateRanges(List<ILNode> body, int bodyLength)
{
if (bodyLength == 0)
return 0;
for (int i = 0; i < bodyLength; i++) {
StateRange nodeRange = ranges[body[i]];
nodeRange.Simplify();
ILLabel label = body[i] as ILLabel;
if (label != null) {
ranges[body[i + 1]].UnionWith(nodeRange);
continue;
}
ILTryCatchBlock tryFinally = body[i] as ILTryCatchBlock;
if (tryFinally != null) {
if (mode == StateRangeAnalysisMode.IteratorDispose) {
if (tryFinally.CatchBlocks.Count != 0 || tryFinally.FaultBlock != null || tryFinally.FinallyBlock == null)
throw new SymbolicAnalysisFailedException();
ranges[tryFinally.TryBlock].UnionWith(nodeRange);
if (tryFinally.TryBlock.Body.Count != 0) {
ranges[tryFinally.TryBlock.Body[0]].UnionWith(nodeRange);
AssignStateRanges(tryFinally.TryBlock.Body, tryFinally.TryBlock.Body.Count);
}
continue;
} else if (mode == StateRangeAnalysisMode.AsyncMoveNext) {
return i;
} else {
throw new SymbolicAnalysisFailedException();
}
}
ILExpression expr = body[i] as ILExpression;
if (expr == null)
throw new SymbolicAnalysisFailedException();
switch (expr.Code) {
case ILCode.Switch:
{
SymbolicValue val = evalContext.Eval(expr.Arguments[0]);
if (val.Type != SymbolicValueType.State)
goto default;
ILLabel[] targetLabels = (ILLabel[])expr.Operand;
for (int j = 0; j < targetLabels.Length; j++) {
int state = j - val.Constant;
ranges[targetLabels[j]].UnionWith(nodeRange, state, state);
}
StateRange nextRange = ranges[body[i + 1]];
nextRange.UnionWith(nodeRange, int.MinValue, -1 - val.Constant);
nextRange.UnionWith(nodeRange, targetLabels.Length - val.Constant, int.MaxValue);
break;
}
case ILCode.Br:
case ILCode.Leave:
ranges[(ILLabel)expr.Operand].UnionWith(nodeRange);
break;
case ILCode.Brtrue:
{
SymbolicValue val = evalContext.Eval(expr.Arguments[0]);
if (val.Type == SymbolicValueType.StateEquals) {
ranges[(ILLabel)expr.Operand].UnionWith(nodeRange, val.Constant, val.Constant);
StateRange nextRange = ranges[body[i + 1]];
nextRange.UnionWith(nodeRange, int.MinValue, val.Constant - 1);
nextRange.UnionWith(nodeRange, val.Constant + 1, int.MaxValue);
break;
} else if (val.Type == SymbolicValueType.StateInEquals) {
ranges[body[i + 1]].UnionWith(nodeRange, val.Constant, val.Constant);
StateRange targetRange = ranges[(ILLabel)expr.Operand];
targetRange.UnionWith(nodeRange, int.MinValue, val.Constant - 1);
targetRange.UnionWith(nodeRange, val.Constant + 1, int.MaxValue);
break;
} else {
goto default;
}
}
case ILCode.Nop:
ranges[body[i + 1]].UnionWith(nodeRange);
break;
case ILCode.Ret:
break;
case ILCode.Stloc:
{
SymbolicValue val = evalContext.Eval(expr.Arguments[0]);
if (val.Type == SymbolicValueType.State && val.Constant == 0) {
evalContext.AddStateVariable((ILVariable)expr.Operand);
goto case ILCode.Nop;
} else {
goto default;
}
}
case ILCode.Call:
// in some cases (e.g. foreach over array) the C# compiler produces a finally method outside of try-finally blocks
if (mode == StateRangeAnalysisMode.IteratorDispose) {
MethodDefinition mdef = (expr.Operand as MethodReference).ResolveWithinSameModule();
if (mdef == null || finallyMethodToStateInterval.ContainsKey(mdef))
throw new SymbolicAnalysisFailedException();
finallyMethodToStateInterval.Add(mdef, nodeRange.ToEnclosingInterval());
break;
} else {
goto default;
}
default:
if (mode == StateRangeAnalysisMode.IteratorDispose) {
throw new SymbolicAnalysisFailedException();
} else {
return i;
}
}
}
return bodyLength;
}
public void EnsureLabelAtPos(List<ILNode> body, ref int pos, ref int bodyLength)
{
if (pos > 0 && body[pos - 1] is ILLabel) {
pos--;
} 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++;
}
}
public LabelRangeMapping CreateLabelRangeMapping(List<ILNode> body, int pos, int bodyLength)
{
LabelRangeMapping result = new LabelRangeMapping();
CreateLabelRangeMapping(body, pos, bodyLength, result, false);
return result;
}
void CreateLabelRangeMapping(List<ILNode> body, int pos, int bodyLength, LabelRangeMapping result, bool onlyInitialLabels)
{
for (int i = pos; i < bodyLength; i++) {
ILLabel label = body[i] as ILLabel;
if (label != null) {
result.Add(new KeyValuePair<ILLabel, StateRange>(label, ranges[label]));
} else {
ILTryCatchBlock tryCatchBlock = body[i] as ILTryCatchBlock;
if (tryCatchBlock != null) {
CreateLabelRangeMapping(tryCatchBlock.TryBlock.Body, 0, tryCatchBlock.TryBlock.Body.Count, result, true);
} else if (onlyInitialLabels) {
break;
}
}
}
}
}
class LabelRangeMapping : List<KeyValuePair<ILLabel, StateRange>> {}
}

148
src/Libraries/ICSharpCode.Decompiler/ILAst/SymbolicExecution.cs

@ -0,0 +1,148 @@ @@ -0,0 +1,148 @@
// 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;
using System.Diagnostics;
using Mono.Cecil;
namespace ICSharpCode.Decompiler.ILAst
{
/// <summary>
/// This exception is thrown when we find something else than we expect from the C# compiler.
/// This aborts the analysis and makes the whole transform fail.
/// </summary>
class SymbolicAnalysisFailedException : Exception {}
enum SymbolicValueType
{
/// <summary>
/// Unknown value
/// </summary>
Unknown,
/// <summary>
/// int: Constant (result of ldc.i4)
/// </summary>
IntegerConstant,
/// <summary>
/// int: State + Constant
/// </summary>
State,
/// <summary>
/// This pointer (result of ldarg.0)
/// </summary>
This,
/// <summary>
/// bool: State == Constant
/// </summary>
StateEquals,
/// <summary>
/// bool: State != Constant
/// </summary>
StateInEquals
}
struct SymbolicValue
{
public readonly int Constant;
public readonly SymbolicValueType Type;
public SymbolicValue(SymbolicValueType type, int constant = 0)
{
this.Type = type;
this.Constant = constant;
}
public override string ToString()
{
return string.Format("[SymbolicValue {0}: {1}]", this.Type, this.Constant);
}
}
class SymbolicEvaluationContext
{
readonly FieldDefinition stateField;
readonly List<ILVariable> stateVariables = new List<ILVariable>();
public SymbolicEvaluationContext(FieldDefinition stateField)
{
this.stateField = stateField;
}
public void AddStateVariable(ILVariable v)
{
if (!stateVariables.Contains(v))
stateVariables.Add(v);
}
SymbolicValue Failed()
{
return new SymbolicValue(SymbolicValueType.Unknown);
}
public SymbolicValue Eval(ILExpression expr)
{
SymbolicValue left, right;
switch (expr.Code) {
case ILCode.Sub:
left = Eval(expr.Arguments[0]);
right = Eval(expr.Arguments[1]);
if (left.Type != SymbolicValueType.State && left.Type != SymbolicValueType.IntegerConstant)
return Failed();
if (right.Type != SymbolicValueType.IntegerConstant)
return Failed();
return new SymbolicValue(left.Type, unchecked ( left.Constant - right.Constant ));
case ILCode.Ldfld:
if (Eval(expr.Arguments[0]).Type != SymbolicValueType.This)
return Failed();
if (CecilExtensions.ResolveWithinSameModule(expr.Operand as FieldReference) != stateField)
return Failed();
return new SymbolicValue(SymbolicValueType.State);
case ILCode.Ldloc:
ILVariable loadedVariable = (ILVariable)expr.Operand;
if (stateVariables.Contains(loadedVariable))
return new SymbolicValue(SymbolicValueType.State);
else if (loadedVariable.IsParameter && loadedVariable.OriginalParameter.Index < 0)
return new SymbolicValue(SymbolicValueType.This);
else
return Failed();
case ILCode.Ldc_I4:
return new SymbolicValue(SymbolicValueType.IntegerConstant, (int)expr.Operand);
case ILCode.Ceq:
case ILCode.Cne:
left = Eval(expr.Arguments[0]);
right = Eval(expr.Arguments[1]);
if (left.Type != SymbolicValueType.State || right.Type != SymbolicValueType.IntegerConstant)
return Failed();
// bool: (state + left.Constant == right.Constant)
// bool: (state == right.Constant - left.Constant)
return new SymbolicValue(expr.Code == ILCode.Ceq ? SymbolicValueType.StateEquals : SymbolicValueType.StateInEquals, unchecked(right.Constant - left.Constant));
case ILCode.LogicNot:
SymbolicValue val = Eval(expr.Arguments[0]);
if (val.Type == SymbolicValueType.StateEquals)
return new SymbolicValue(SymbolicValueType.StateInEquals, val.Constant);
else if (val.Type == SymbolicValueType.StateInEquals)
return new SymbolicValue(SymbolicValueType.StateEquals, val.Constant);
else
return Failed();
default:
return Failed();
}
}
}
}

21
src/Libraries/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

@ -790,8 +790,17 @@ namespace ICSharpCode.Decompiler.ILAst @@ -790,8 +790,17 @@ namespace ICSharpCode.Decompiler.ILAst
case ILCode.YieldBreak:
return null;
case ILCode.Ret:
if (forceInferChildren && expr.Arguments.Count == 1)
InferTypeForExpression(expr.Arguments[0], context.CurrentMethod.ReturnType);
if (forceInferChildren && expr.Arguments.Count == 1) {
TypeReference returnType = context.CurrentMethod.ReturnType;
if (context.CurrentMethodIsAsync && returnType != null && returnType.Namespace == "System.Threading.Tasks") {
if (returnType.Name == "Task") {
returnType = typeSystem.Void;
} else if (returnType.Name == "Task`1" && returnType.IsGenericInstance) {
returnType = ((GenericInstanceType)returnType).GenericArguments[0];
}
}
InferTypeForExpression(expr.Arguments[0], returnType);
}
return null;
case ILCode.YieldReturn:
if (forceInferChildren) {
@ -803,6 +812,14 @@ namespace ICSharpCode.Decompiler.ILAst @@ -803,6 +812,14 @@ namespace ICSharpCode.Decompiler.ILAst
}
}
return null;
case ILCode.Await:
{
TypeReference taskType = InferTypeForExpression(expr.Arguments[0], null);
if (taskType.Name == "Task`1" && taskType.IsGenericInstance && taskType.Namespace == "System.Threading.Tasks") {
return ((GenericInstanceType)taskType).GenericArguments[0];
}
return null;
}
#endregion
case ILCode.Pop:
return null;

418
src/Libraries/ICSharpCode.Decompiler/ILAst/YieldReturnDecompiler.cs

@ -24,7 +24,7 @@ using Mono.Cecil; @@ -24,7 +24,7 @@ using Mono.Cecil;
namespace ICSharpCode.Decompiler.ILAst
{
public class YieldReturnDecompiler
class YieldReturnDecompiler
{
// For a description on the code generated by the C# compiler for yield return:
// http://csharpindepth.com/Articles/Chapter6/IteratorBlockImplementation.aspx
@ -34,11 +34,8 @@ namespace ICSharpCode.Decompiler.ILAst @@ -34,11 +34,8 @@ namespace ICSharpCode.Decompiler.ILAst
// - Figure out which of the fields is the state field
// - Construct an exception table based on states. This allows us to determine, for each state, what the parent try block is.
/// <summary>
/// This exception is thrown when we find something else than we expect from the C# compiler.
/// This aborts the analysis and makes the whole transform fail.
/// </summary>
class YieldAnalysisFailedException : Exception {}
// See http://community.sharpdevelop.net/blogs/danielgrunwald/archive/2011/03/06/ilspy-yield-return.aspx
// for a description of this step.
DecompilerContext context;
TypeDefinition enumeratorType;
@ -66,7 +63,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -66,7 +63,7 @@ namespace ICSharpCode.Decompiler.ILAst
#endif
try {
yrd.Run();
} catch (YieldAnalysisFailedException) {
} catch (SymbolicAnalysisFailedException) {
return;
}
#if DEBUG
@ -211,7 +208,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -211,7 +208,7 @@ namespace ICSharpCode.Decompiler.ILAst
}
}
if (stateField == null)
throw new YieldAnalysisFailedException();
throw new SymbolicAnalysisFailedException();
}
/// <summary>
@ -220,7 +217,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -220,7 +217,7 @@ namespace ICSharpCode.Decompiler.ILAst
ILBlock CreateILAst(MethodDefinition method)
{
if (method == null || !method.HasBody)
throw new YieldAnalysisFailedException();
throw new SymbolicAnalysisFailedException();
ILBlock ilMethod = new ILBlock();
ILAstBuilder astBuilder = new ILAstBuilder();
@ -269,7 +266,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -269,7 +266,7 @@ namespace ICSharpCode.Decompiler.ILAst
}
}
if (currentField == null)
throw new YieldAnalysisFailedException();
throw new SymbolicAnalysisFailedException();
}
#endregion
@ -322,337 +319,30 @@ namespace ICSharpCode.Decompiler.ILAst @@ -322,337 +319,30 @@ namespace ICSharpCode.Decompiler.ILAst
disposeMethod = enumeratorType.Methods.FirstOrDefault(m => m.Name == "System.IDisposable.Dispose");
ILBlock ilMethod = CreateILAst(disposeMethod);
finallyMethodToStateInterval = new Dictionary<MethodDefinition, Interval>();
InitStateRanges(ilMethod.Body[0]);
AssignStateRanges(ilMethod.Body, ilMethod.Body.Count, forDispose: true);
var rangeAnalysis = new StateRangeAnalysis(ilMethod.Body[0], StateRangeAnalysisMode.IteratorDispose, stateField);
rangeAnalysis.AssignStateRanges(ilMethod.Body, ilMethod.Body.Count);
finallyMethodToStateInterval = rangeAnalysis.finallyMethodToStateInterval;
// Now look at the finally blocks:
foreach (var tryFinally in ilMethod.GetSelfAndChildrenRecursive<ILTryCatchBlock>()) {
Interval interval = ranges[tryFinally.TryBlock.Body[0]].ToEnclosingInterval();
Interval interval = rangeAnalysis.ranges[tryFinally.TryBlock.Body[0]].ToEnclosingInterval();
var finallyBody = tryFinally.FinallyBlock.Body;
if (finallyBody.Count != 2)
throw new YieldAnalysisFailedException();
throw new SymbolicAnalysisFailedException();
ILExpression call = finallyBody[0] as ILExpression;
if (call == null || call.Code != ILCode.Call || call.Arguments.Count != 1)
throw new YieldAnalysisFailedException();
throw new SymbolicAnalysisFailedException();
if (!call.Arguments[0].MatchThis())
throw new YieldAnalysisFailedException();
throw new SymbolicAnalysisFailedException();
if (!finallyBody[1].Match(ILCode.Endfinally))
throw new YieldAnalysisFailedException();
throw new SymbolicAnalysisFailedException();
MethodDefinition mdef = GetMethodDefinition(call.Operand as MethodReference);
if (mdef == null || finallyMethodToStateInterval.ContainsKey(mdef))
throw new YieldAnalysisFailedException();
throw new SymbolicAnalysisFailedException();
finallyMethodToStateInterval.Add(mdef, interval);
}
ranges = null;
}
#endregion
#region Assign StateRanges / Symbolic Execution (used for analysis of Dispose() and MoveNext())
#region struct Interval / class StateRange
struct Interval
{
public readonly int Start, End;
public Interval(int start, int end)
{
Debug.Assert(start <= end || (start == 0 && end == -1));
this.Start = start;
this.End = end;
}
public override string ToString()
{
return string.Format("({0} to {1})", Start, End);
}
}
class StateRange
{
readonly List<Interval> data = new List<Interval>();
public StateRange()
{
}
public StateRange(int start, int end)
{
this.data.Add(new Interval(start, end));
}
public bool Contains(int val)
{
foreach (Interval v in data) {
if (v.Start <= val && val <= v.End)
return true;
}
return false;
}
public void UnionWith(StateRange other)
{
data.AddRange(other.data);
}
/// <summary>
/// Unions this state range with (other intersect (minVal to maxVal))
/// </summary>
public void UnionWith(StateRange other, int minVal, int maxVal)
{
foreach (Interval v in other.data) {
int start = Math.Max(v.Start, minVal);
int end = Math.Min(v.End, maxVal);
if (start <= end)
data.Add(new Interval(start, end));
}
}
/// <summary>
/// Merges overlapping interval ranges.
/// </summary>
public void Simplify()
{
if (data.Count < 2)
return;
data.Sort((a, b) => a.Start.CompareTo(b.Start));
Interval prev = data[0];
int prevIndex = 0;
for (int i = 1; i < data.Count; i++) {
Interval next = data[i];
Debug.Assert(prev.Start <= next.Start);
if (next.Start <= prev.End + 1) { // intervals overlapping or touching
prev = new Interval(prev.Start, Math.Max(prev.End, next.End));
data[prevIndex] = prev;
data[i] = new Interval(0, -1); // mark as deleted
} else {
prev = next;
prevIndex = i;
}
}
data.RemoveAll(i => i.Start > i.End); // remove all entries that were marked as deleted
}
public override string ToString()
{
return string.Join(",", data);
}
public Interval ToEnclosingInterval()
{
if (data.Count == 0)
throw new YieldAnalysisFailedException();
return new Interval(data[0].Start, data[data.Count - 1].End);
}
}
#endregion
DefaultDictionary<ILNode, StateRange> ranges;
ILVariable rangeAnalysisStateVariable;
/// <summary>
/// Initializes the state range logic:
/// Clears 'ranges' and sets 'ranges[entryPoint]' to the full range (int.MinValue to int.MaxValue)
/// </summary>
void InitStateRanges(ILNode entryPoint)
{
ranges = new DefaultDictionary<ILNode, StateRange>(n => new StateRange());
ranges[entryPoint] = new StateRange(int.MinValue, int.MaxValue);
rangeAnalysisStateVariable = null;
}
int AssignStateRanges(List<ILNode> body, int bodyLength, bool forDispose)
{
if (bodyLength == 0)
return 0;
for (int i = 0; i < bodyLength; i++) {
StateRange nodeRange = ranges[body[i]];
nodeRange.Simplify();
ILLabel label = body[i] as ILLabel;
if (label != null) {
ranges[body[i + 1]].UnionWith(nodeRange);
continue;
}
ILTryCatchBlock tryFinally = body[i] as ILTryCatchBlock;
if (tryFinally != null) {
if (!forDispose || tryFinally.CatchBlocks.Count != 0 || tryFinally.FaultBlock != null || tryFinally.FinallyBlock == null)
throw new YieldAnalysisFailedException();
ranges[tryFinally.TryBlock].UnionWith(nodeRange);
if (tryFinally.TryBlock.Body.Count != 0) {
ranges[tryFinally.TryBlock.Body[0]].UnionWith(nodeRange);
AssignStateRanges(tryFinally.TryBlock.Body, tryFinally.TryBlock.Body.Count, forDispose);
}
continue;
}
ILExpression expr = body[i] as ILExpression;
if (expr == null)
throw new YieldAnalysisFailedException();
switch (expr.Code) {
case ILCode.Switch:
{
SymbolicValue val = Eval(expr.Arguments[0]);
if (val.Type != SymbolicValueType.State)
throw new YieldAnalysisFailedException();
ILLabel[] targetLabels = (ILLabel[])expr.Operand;
for (int j = 0; j < targetLabels.Length; j++) {
int state = j - val.Constant;
ranges[targetLabels[j]].UnionWith(nodeRange, state, state);
}
StateRange nextRange = ranges[body[i + 1]];
nextRange.UnionWith(nodeRange, int.MinValue, -1 - val.Constant);
nextRange.UnionWith(nodeRange, targetLabels.Length - val.Constant, int.MaxValue);
break;
}
case ILCode.Br:
case ILCode.Leave:
ranges[(ILLabel)expr.Operand].UnionWith(nodeRange);
break;
case ILCode.Brtrue:
{
SymbolicValue val = Eval(expr.Arguments[0]);
if (val.Type == SymbolicValueType.StateEquals) {
ranges[(ILLabel)expr.Operand].UnionWith(nodeRange, val.Constant, val.Constant);
StateRange nextRange = ranges[body[i + 1]];
nextRange.UnionWith(nodeRange, int.MinValue, val.Constant - 1);
nextRange.UnionWith(nodeRange, val.Constant + 1, int.MaxValue);
} else if (val.Type == SymbolicValueType.StateInEquals) {
ranges[body[i + 1]].UnionWith(nodeRange, val.Constant, val.Constant);
StateRange targetRange = ranges[(ILLabel)expr.Operand];
targetRange.UnionWith(nodeRange, int.MinValue, val.Constant - 1);
targetRange.UnionWith(nodeRange, val.Constant + 1, int.MaxValue);
} else {
throw new YieldAnalysisFailedException();
}
break;
}
case ILCode.Nop:
ranges[body[i + 1]].UnionWith(nodeRange);
break;
case ILCode.Ret:
break;
case ILCode.Stloc:
{
SymbolicValue val = Eval(expr.Arguments[0]);
if (val.Type == SymbolicValueType.State && val.Constant == 0 && rangeAnalysisStateVariable == null)
rangeAnalysisStateVariable = (ILVariable)expr.Operand;
else
throw new YieldAnalysisFailedException();
goto case ILCode.Nop;
}
case ILCode.Call:
// in some cases (e.g. foreach over array) the C# compiler produces a finally method outside of try-finally blocks
if (forDispose) {
MethodDefinition mdef = GetMethodDefinition(expr.Operand as MethodReference);
if (mdef == null || finallyMethodToStateInterval.ContainsKey(mdef))
throw new YieldAnalysisFailedException();
finallyMethodToStateInterval.Add(mdef, nodeRange.ToEnclosingInterval());
} else {
throw new YieldAnalysisFailedException();
}
break;
default:
if (forDispose)
throw new YieldAnalysisFailedException();
else
return i;
}
}
return bodyLength;
}
enum SymbolicValueType
{
/// <summary>
/// int: Constant (result of ldc.i4)
/// </summary>
IntegerConstant,
/// <summary>
/// int: State + Constant
/// </summary>
State,
/// <summary>
/// This pointer (result of ldarg.0)
/// </summary>
This,
/// <summary>
/// bool: State == Constant
/// </summary>
StateEquals,
/// <summary>
/// bool: State != Constant
/// </summary>
StateInEquals
}
struct SymbolicValue
{
public readonly int Constant;
public readonly SymbolicValueType Type;
public SymbolicValue(SymbolicValueType type, int constant = 0)
{
this.Type = type;
this.Constant = constant;
}
public override string ToString()
{
return string.Format("[SymbolicValue {0}: {1}]", this.Type, this.Constant);
}
}
SymbolicValue Eval(ILExpression expr)
{
SymbolicValue left, right;
switch (expr.Code) {
case ILCode.Sub:
left = Eval(expr.Arguments[0]);
right = Eval(expr.Arguments[1]);
if (left.Type != SymbolicValueType.State && left.Type != SymbolicValueType.IntegerConstant)
throw new YieldAnalysisFailedException();
if (right.Type != SymbolicValueType.IntegerConstant)
throw new YieldAnalysisFailedException();
return new SymbolicValue(left.Type, unchecked ( left.Constant - right.Constant ));
case ILCode.Ldfld:
if (Eval(expr.Arguments[0]).Type != SymbolicValueType.This)
throw new YieldAnalysisFailedException();
if (GetFieldDefinition(expr.Operand as FieldReference) != stateField)
throw new YieldAnalysisFailedException();
return new SymbolicValue(SymbolicValueType.State);
case ILCode.Ldloc:
ILVariable loadedVariable = (ILVariable)expr.Operand;
if (loadedVariable == rangeAnalysisStateVariable)
return new SymbolicValue(SymbolicValueType.State);
else if (loadedVariable.IsParameter && loadedVariable.OriginalParameter.Index < 0)
return new SymbolicValue(SymbolicValueType.This);
else
throw new YieldAnalysisFailedException();
case ILCode.Ldc_I4:
return new SymbolicValue(SymbolicValueType.IntegerConstant, (int)expr.Operand);
case ILCode.Ceq:
case ILCode.Cne:
left = Eval(expr.Arguments[0]);
right = Eval(expr.Arguments[1]);
if (left.Type != SymbolicValueType.State || right.Type != SymbolicValueType.IntegerConstant)
throw new YieldAnalysisFailedException();
// bool: (state + left.Constant == right.Constant)
// bool: (state == right.Constant - left.Constant)
return new SymbolicValue(expr.Code == ILCode.Ceq ? SymbolicValueType.StateEquals : SymbolicValueType.StateInEquals, unchecked(right.Constant - left.Constant));
case ILCode.LogicNot:
SymbolicValue val = Eval(expr.Arguments[0]);
if (val.Type == SymbolicValueType.StateEquals)
return new SymbolicValue(SymbolicValueType.StateInEquals, val.Constant);
else if (val.Type == SymbolicValueType.StateInEquals)
return new SymbolicValue(SymbolicValueType.StateEquals, val.Constant);
else
throw new YieldAnalysisFailedException();
default:
throw new YieldAnalysisFailedException();
}
rangeAnalysis = null;
}
#endregion
@ -667,10 +357,10 @@ namespace ICSharpCode.Decompiler.ILAst @@ -667,10 +357,10 @@ namespace ICSharpCode.Decompiler.ILAst
ILBlock ilMethod = CreateILAst(moveNextMethod);
if (ilMethod.Body.Count == 0)
throw new YieldAnalysisFailedException();
throw new SymbolicAnalysisFailedException();
ILExpression lastReturnArg;
if (!ilMethod.Body.Last().Match(ILCode.Ret, out lastReturnArg))
throw new YieldAnalysisFailedException();
throw new SymbolicAnalysisFailedException();
// There are two possibilities:
if (lastReturnArg.Code == ILCode.Ldloc) {
@ -678,14 +368,14 @@ namespace ICSharpCode.Decompiler.ILAst @@ -678,14 +368,14 @@ namespace ICSharpCode.Decompiler.ILAst
returnVariable = (ILVariable)lastReturnArg.Operand;
returnLabel = ilMethod.Body.ElementAtOrDefault(ilMethod.Body.Count - 2) as ILLabel;
if (returnLabel == null)
throw new YieldAnalysisFailedException();
throw new SymbolicAnalysisFailedException();
} else {
// b) the compiler directly returns constants
returnVariable = null;
returnLabel = null;
// In this case, the last return must return false.
if (lastReturnArg.Code != ILCode.Ldc_I4 || (int)lastReturnArg.Operand != 0)
throw new YieldAnalysisFailedException();
throw new SymbolicAnalysisFailedException();
}
ILTryCatchBlock tryFaultBlock = ilMethod.Body[0] as ILTryCatchBlock;
@ -694,23 +384,23 @@ namespace ICSharpCode.Decompiler.ILAst @@ -694,23 +384,23 @@ namespace ICSharpCode.Decompiler.ILAst
if (tryFaultBlock != null) {
// there are try-finally blocks
if (returnVariable == null) // in this case, we must use a return variable
throw new YieldAnalysisFailedException();
throw new SymbolicAnalysisFailedException();
// must be a try-fault block:
if (tryFaultBlock.CatchBlocks.Count != 0 || tryFaultBlock.FinallyBlock != null || tryFaultBlock.FaultBlock == null)
throw new YieldAnalysisFailedException();
throw new SymbolicAnalysisFailedException();
ILBlock faultBlock = tryFaultBlock.FaultBlock;
// Ensure the fault block contains the call to Dispose().
if (faultBlock.Body.Count != 2)
throw new YieldAnalysisFailedException();
throw new SymbolicAnalysisFailedException();
MethodReference disposeMethodRef;
ILExpression disposeArg;
if (!faultBlock.Body[0].Match(ILCode.Call, out disposeMethodRef, out disposeArg))
throw new YieldAnalysisFailedException();
throw new SymbolicAnalysisFailedException();
if (GetMethodDefinition(disposeMethodRef) != disposeMethod || !disposeArg.MatchThis())
throw new YieldAnalysisFailedException();
throw new SymbolicAnalysisFailedException();
if (!faultBlock.Body[1].Match(ILCode.Endfinally))
throw new YieldAnalysisFailedException();
throw new SymbolicAnalysisFailedException();
body = tryFaultBlock.TryBlock.Body;
bodyLength = body.Count;
@ -734,39 +424,22 @@ namespace ICSharpCode.Decompiler.ILAst @@ -734,39 +424,22 @@ namespace ICSharpCode.Decompiler.ILAst
bodyLength--;
ILExpression store0 = body.ElementAtOrDefault(bodyLength - 1) as ILExpression;
if (store0 == null || store0.Code != ILCode.Stloc || store0.Operand != returnVariable)
throw new YieldAnalysisFailedException();
throw new SymbolicAnalysisFailedException();
if (store0.Arguments[0].Code != ILCode.Ldc_I4 || (int)store0.Arguments[0].Operand != 0)
throw new YieldAnalysisFailedException();
throw new SymbolicAnalysisFailedException();
bodyLength--; // don't conside the stloc instruction to be part of the body
}
// verify that the last element in the body is a label pointing to the 'ret(false)'
returnFalseLabel = body.ElementAtOrDefault(bodyLength - 1) as ILLabel;
if (returnFalseLabel == null)
throw new YieldAnalysisFailedException();
InitStateRanges(body[0]);
int pos = AssignStateRanges(body, bodyLength, forDispose: false);
if (pos > 0 && body[pos - 1] is ILLabel) {
pos--;
} 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++;
}
throw new SymbolicAnalysisFailedException();
List<KeyValuePair<ILLabel, StateRange>> labels = new List<KeyValuePair<ILLabel, StateRange>>();
for (int i = pos; i < bodyLength; i++) {
ILLabel label = body[i] as ILLabel;
if (label != null) {
labels.Add(new KeyValuePair<ILLabel, StateRange>(label, ranges[label]));
}
}
var rangeAnalysis = new StateRangeAnalysis(body[0], StateRangeAnalysisMode.IteratorMoveNext, stateField);
int pos = rangeAnalysis.AssignStateRanges(body, bodyLength);
rangeAnalysis.EnsureLabelAtPos(body, ref pos, ref bodyLength);
var labels = rangeAnalysis.CreateLabelRangeMapping(body, pos, bodyLength);
ConvertBody(body, pos, bodyLength, labels);
}
#endregion
@ -797,7 +470,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -797,7 +470,7 @@ namespace ICSharpCode.Decompiler.ILAst
// Handle stores to 'state' or 'current'
if (GetFieldDefinition(expr.Operand as FieldReference) == stateField) {
if (expr.Arguments[1].Code != ILCode.Ldc_I4)
throw new YieldAnalysisFailedException();
throw new SymbolicAnalysisFailedException();
currentState = (int)expr.Arguments[1].Operand;
stateChanges.Add(new SetState(newBody.Count, currentState));
} else if (GetFieldDefinition(expr.Operand as FieldReference) == currentField) {
@ -809,18 +482,18 @@ namespace ICSharpCode.Decompiler.ILAst @@ -809,18 +482,18 @@ namespace ICSharpCode.Decompiler.ILAst
// handle store+branch to the returnVariable
ILExpression br = body.ElementAtOrDefault(++pos) as ILExpression;
if (br == null || !(br.Code == ILCode.Br || br.Code == ILCode.Leave) || br.Operand != returnLabel || expr.Arguments[0].Code != ILCode.Ldc_I4)
throw new YieldAnalysisFailedException();
throw new SymbolicAnalysisFailedException();
int val = (int)expr.Arguments[0].Operand;
if (val == 0) {
newBody.Add(MakeGoTo(returnFalseLabel));
} else if (val == 1) {
newBody.Add(MakeGoTo(labels, currentState));
} else {
throw new YieldAnalysisFailedException();
throw new SymbolicAnalysisFailedException();
}
} else if (expr != null && expr.Code == ILCode.Ret) {
if (expr.Arguments.Count != 1 || expr.Arguments[0].Code != ILCode.Ldc_I4)
throw new YieldAnalysisFailedException();
throw new SymbolicAnalysisFailedException();
// handle direct return (e.g. in release builds)
int val = (int)expr.Arguments[0].Operand;
if (val == 0) {
@ -828,24 +501,24 @@ namespace ICSharpCode.Decompiler.ILAst @@ -828,24 +501,24 @@ namespace ICSharpCode.Decompiler.ILAst
} else if (val == 1) {
newBody.Add(MakeGoTo(labels, currentState));
} else {
throw new YieldAnalysisFailedException();
throw new SymbolicAnalysisFailedException();
}
} else if (expr != null && expr.Code == ILCode.Call && expr.Arguments.Count == 1 && expr.Arguments[0].MatchThis()) {
MethodDefinition method = GetMethodDefinition(expr.Operand as MethodReference);
if (method == null)
throw new YieldAnalysisFailedException();
throw new SymbolicAnalysisFailedException();
Interval interval;
if (method == disposeMethod) {
// Explicit call to dispose is used for "yield break;" within the method.
ILExpression br = body.ElementAtOrDefault(++pos) as ILExpression;
if (br == null || !(br.Code == ILCode.Br || br.Code == ILCode.Leave) || br.Operand != returnFalseLabel)
throw new YieldAnalysisFailedException();
throw new SymbolicAnalysisFailedException();
newBody.Add(MakeGoTo(returnFalseLabel));
} else if (finallyMethodToStateInterval.TryGetValue(method, out interval)) {
// Call to Finally-method
int index = stateChanges.FindIndex(ss => ss.NewState >= interval.Start && ss.NewState <= interval.End);
if (index < 0)
throw new YieldAnalysisFailedException();
throw new SymbolicAnalysisFailedException();
ILLabel label = new ILLabel();
label.Name = "JumpOutOfTryFinally" + interval.Start + "_" + interval.End;
@ -883,7 +556,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -883,7 +556,7 @@ namespace ICSharpCode.Decompiler.ILAst
if (pair.Value.Contains(state))
return MakeGoTo(pair.Key);
}
throw new YieldAnalysisFailedException();
throw new SymbolicAnalysisFailedException();
}
ILBlock ConvertFinallyBlock(MethodDefinition finallyMethod)
@ -907,6 +580,11 @@ namespace ICSharpCode.Decompiler.ILAst @@ -907,6 +580,11 @@ namespace ICSharpCode.Decompiler.ILAst
#region TranslateFieldsToLocalAccess
void TranslateFieldsToLocalAccess()
{
TranslateFieldsToLocalAccess(newBody, fieldToParameterMap);
}
internal static void TranslateFieldsToLocalAccess(List<ILNode> newBody, Dictionary<FieldDefinition, ILVariable> fieldToParameterMap)
{
var fieldToLocalMap = new DefaultDictionary<FieldDefinition, ILVariable>(f => new ILVariable { Name = f.Name, Type = f.FieldType });
foreach (ILNode node in newBody) {

4
src/Libraries/ICSharpCode.Decompiler/Properties/AssemblyInfo.cs

@ -19,8 +19,8 @@ using System.Runtime.InteropServices; @@ -19,8 +19,8 @@ using System.Runtime.InteropServices;
// If you need to expose a type to COM, use [ComVisible(true)] on that type.
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("2.0.0.1595")]
[assembly: AssemblyInformationalVersion("2.0.0.1595-5773d3d2")]
[assembly: AssemblyVersion("2.1.0.1603")]
[assembly: AssemblyInformationalVersion("2.1.0.1603-1170e2f8")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly",

144
src/Libraries/ICSharpCode.Decompiler/Tests/Async.cs

@ -0,0 +1,144 @@ @@ -0,0 +1,144 @@
// Copyright (c) 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.
#pragma warning disable 1998
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
public class Async
{
public async void SimpleVoidMethod()
{
Console.WriteLine("Before");
await Task.Delay(TimeSpan.FromSeconds(1.0));
Console.WriteLine("After");
}
public async void VoidMethodWithoutAwait()
{
Console.WriteLine("No Await");
}
public async Task SimpleVoidTaskMethod()
{
Console.WriteLine("Before");
await Task.Delay(TimeSpan.FromSeconds(1.0));
Console.WriteLine("After");
}
public async Task TaskMethodWithoutAwait()
{
Console.WriteLine("No Await");
}
public async Task<bool> SimpleBoolTaskMethod()
{
Console.WriteLine("Before");
await Task.Delay(TimeSpan.FromSeconds(1.0));
Console.WriteLine("After");
return true;
}
public async void TwoAwaitsWithDifferentAwaiterTypes()
{
Console.WriteLine("Before");
if (await this.SimpleBoolTaskMethod())
{
await Task.Delay(TimeSpan.FromSeconds(1.0));
}
Console.WriteLine("After");
}
public async void StreamCopyTo(Stream destination, int bufferSize)
{
byte[] array = new byte[bufferSize];
int count;
while ((count = await destination.ReadAsync(array, 0, array.Length)) != 0)
{
await destination.WriteAsync(array, 0, count);
}
}
public async void StreamCopyToWithConfigureAwait(Stream destination, int bufferSize)
{
byte[] array = new byte[bufferSize];
int count;
while ((count = await destination.ReadAsync(array, 0, array.Length).ConfigureAwait(false)) != 0)
{
await destination.WriteAsync(array, 0, count).ConfigureAwait(false);
}
}
public async void AwaitInLoopCondition()
{
while (await this.SimpleBoolTaskMethod())
{
Console.WriteLine("Body");
}
}
public async Task<int> AwaitInForEach(IEnumerable<Task<int>> elements)
{
int num = 0;
foreach (Task<int> current in elements)
{
num += await current;
}
return num;
}
public async Task TaskMethodWithoutAwaitButWithExceptionHandling()
{
try
{
using (new StringWriter())
{
Console.WriteLine("No Await");
}
}
catch (Exception)
{
Console.WriteLine("Crash");
}
}
public async Task<int> NestedAwait(Task<Task<int>> task)
{
return await(await task);
}
public async Task AwaitWithStack(Task<int> task)
{
Console.WriteLine("A", 1, await task);
}
public async Task AwaitWithStack2(Task<int> task)
{
if (await this.SimpleBoolTaskMethod())
{
Console.WriteLine("A", 1, await task);
}
else
{
int num = 1;
Console.WriteLine("A", 1, num);
}
}
}

4
src/Libraries/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj

@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
<OutputType>Library</OutputType>
<RootNamespace>ICSharpCode.Decompiler.Tests</RootNamespace>
<AssemblyName>ICSharpCode.Decompiler.Tests</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<AppDesignerFolder>Properties</AppDesignerFolder>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<NoStdLib>False</NoStdLib>
@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
<NoWarn>67,169,1058,728,1720,649</NoWarn>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'x86' ">
<PlatformTarget>x86</PlatformTarget>
@ -62,6 +63,7 @@ @@ -62,6 +63,7 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Async.cs" />
<Compile Include="CallOverloadedMethod.cs" />
<Compile Include="CheckedUnchecked.cs" />
<Compile Include="ControlFlow.cs" />

2
src/Libraries/ICSharpCode.Decompiler/Tests/PropertiesAndEvents.cs

@ -24,7 +24,7 @@ public class PropertiesAndEvents @@ -24,7 +24,7 @@ public class PropertiesAndEvents
public event EventHandler AutomaticEvent;
[field: NonSerialized]
public event EventHandler AutomaticEventWithInitializer = delegate
public event EventHandler AutomaticEventWithInitializer = delegate(object sender, EventArgs e)
{
};

6
src/Libraries/ICSharpCode.Decompiler/Tests/TestRunner.cs

@ -34,6 +34,12 @@ namespace ICSharpCode.Decompiler.Tests @@ -34,6 +34,12 @@ namespace ICSharpCode.Decompiler.Tests
[TestFixture]
public class TestRunner
{
[Test]
public void Async()
{
TestFile(@"..\..\Tests\Async.cs");
}
[Test, Ignore("disambiguating overloads is not yet implemented")]
public void CallOverloadedMethod()
{

15
src/Libraries/NRefactory/Project/Src/Lexer/VBNet/ExpressionFinder.atg

@ -1137,10 +1137,19 @@ MultilineIfRemainder = @@ -1137,10 +1137,19 @@ MultilineIfRemainder =
SelectStatement =
"Select" [ "Case" ] Expression StatementTerminator
{
"Case" (
// HACK: '<' is recognized as XML literal, if occurring at the start of an expression
// in the CaseClause however it can only be a less-than-sign and vbc does not allow XML literals.
// we use a simple xmlAllowed flag:
// the flag is only set to false immetiately before the expression is parsed and set to true once '<'
// is recognized as less-than-sign to allow normal behavior of the lexer in later expressions.
"Case" (. xmlAllowed = false; .) (
"Else" |
( [ "Is" ] ComparisonOperator SimpleExpressionWithSuffix | Expression )
{ "," ( [ "Is" ] ComparisonOperator SimpleExpressionWithSuffix | Expression ) }
( (. xmlAllowed = true; .) [ "Is" ] ComparisonOperator SimpleExpressionWithSuffix
| (. xmlAllowed = true; .) Expression )
{ "," (. xmlAllowed = false; .)
( (. xmlAllowed = true; .) [ "Is" ] ComparisonOperator SimpleExpressionWithSuffix
| (. xmlAllowed = true; .) Expression )
}
)
StatementTerminatorAndBlock
}

4
src/Libraries/NRefactory/Project/Src/Lexer/VBNet/ExpressionFinder.cs

@ -121,6 +121,10 @@ namespace ICSharpCode.NRefactory.Parser.VB @@ -121,6 +121,10 @@ namespace ICSharpCode.NRefactory.Parser.VB
set { readXmlIdentifier = value; }
}
public bool XmlAllowed {
get { return xmlAllowed; }
}
public bool NextTokenIsStartOfImportsOrAccessExpression {
get { return nextTokenIsStartOfImportsOrAccessExpression; }
}

2
src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Lexer.cs

@ -317,7 +317,7 @@ namespace ICSharpCode.NRefactory.Parser.VB @@ -317,7 +317,7 @@ namespace ICSharpCode.NRefactory.Parser.VB
return new Token(Tokens.XmlEndInlineVB, new Location(x, y), new Location(Col, Line));
}
#endregion
if (ch == '<' && (ef.NextTokenIsPotentialStartOfExpression || ef.NextTokenIsStartOfImportsOrAccessExpression)) {
if (ch == '<' && ef.XmlAllowed && (ef.NextTokenIsPotentialStartOfExpression || ef.NextTokenIsStartOfImportsOrAccessExpression)) {
xmlModeStack.Push(new XmlModeInfo(ef.NextTokenIsStartOfImportsOrAccessExpression));
XmlModeInfo info = xmlModeStack.Peek();
int x = Col - 1;

3197
src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Parser.cs

File diff suppressed because it is too large Load Diff

1
src/Libraries/NRefactory/Project/Src/Lexer/VBNet/PushParser.frame

@ -37,6 +37,7 @@ partial class ExpressionFinder { @@ -37,6 +37,7 @@ partial class ExpressionFinder {
bool wasQualifierTokenAtStart = false;
bool nextTokenIsPotentialStartOfExpression = false;
bool readXmlIdentifier = false;
bool xmlAllowed = true;
bool identifierExpected = false;
bool nextTokenIsStartOfImportsOrAccessExpression = false;
bool isMissingModifier = false;

6
src/Libraries/NRefactory/Test/Lexer/VBNet/XmlModeLexerTests.cs

@ -783,7 +783,7 @@ End If"; @@ -783,7 +783,7 @@ End If";
public void SelectStatement()
{
string statement = @"Select Case <Test />
Case <Test />, <Test />
Case < 1, (<Test />)
Case Else
End Select";
@ -792,8 +792,8 @@ End Select"; @@ -792,8 +792,8 @@ End Select";
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.LessThan, Tokens.LiteralInteger, Tokens.Comma, Tokens.OpenParenthesis,
Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.CloseParenthesis, Tokens.EOL,
Tokens.Case, Tokens.Else, Tokens.EOL,
Tokens.End, Tokens.Select
);

14
src/Libraries/NRefactory/Test/Parser/Statements/SwitchStatementTests.cs

@ -39,6 +39,20 @@ namespace ICSharpCode.NRefactory.Tests.Ast @@ -39,6 +39,20 @@ namespace ICSharpCode.NRefactory.Tests.Ast
SwitchSection sec = switchStmt.SwitchSections[0];
Assert.AreEqual(0, sec.SwitchLabels.Count);
}
[Test]
public void SpecialCaseStatement()
{
SwitchStatement stmt = ParseUtilVBNet.ParseStatement<SwitchStatement>("Select Case a\nCase < 50\nCase > 20, < 10\nEnd Select");
Assert.AreEqual("a", ((IdentifierExpression)stmt.SwitchExpression).Identifier);
}
[Test]
public void SpecialCaseStatement2()
{
SwitchStatement stmt = ParseUtilVBNet.ParseStatement<SwitchStatement>("Select Case a\nCase < 50\nEnd Select");
Assert.AreEqual("a", ((IdentifierExpression)stmt.SwitchExpression).Identifier);
}
#endregion
}
}

16
src/Main/Base/Project/Src/Gui/Components/ExtTreeView/ExtTreeView.cs

@ -132,7 +132,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -132,7 +132,7 @@ namespace ICSharpCode.SharpDevelop.Gui
#region label editing
string labelEditOldLabel;
//string labelEditOldLabel;
public void StartLabelEdit(ExtTreeNode node)
{
@ -146,10 +146,12 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -146,10 +146,12 @@ namespace ICSharpCode.SharpDevelop.Gui
LabelEdit = true;
node.BeforeLabelEdit();
node.BeginEdit();
// remove node's label so that it doesn't get rendered behind the label editing textbox
// (if the user deletes some characters so that the text box shrinks)
labelEditOldLabel = node.Text;
node.Text = "";
// Workaround disabled due to http://community.sharpdevelop.net/forums/t/14354.aspx
// "Rename fails if filename in Project Explorer is too long for the treeview viewport"
//// remove node's label so that it doesn't get rendered behind the label editing textbox
//// (if the user deletes some characters so that the text box shrinks)
//labelEditOldLabel = node.Text;
//node.Text = "";
}
}
@ -176,8 +178,8 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -176,8 +178,8 @@ namespace ICSharpCode.SharpDevelop.Gui
ExtTreeNode node = e.Node as ExtTreeNode;
if (node != null) {
node.Text = labelEditOldLabel;
labelEditOldLabel = null;
//node.Text = labelEditOldLabel;
//labelEditOldLabel = null;
if (e.Label != null) {
node.AfterLabelEdit(e.Label);
}

7
src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/ServiceReference/ProjectWithServiceReferences.cs

@ -82,10 +82,17 @@ namespace ICSharpCode.SharpDevelop.Gui.Dialogs.ReferenceDialog.ServiceReference @@ -82,10 +82,17 @@ namespace ICSharpCode.SharpDevelop.Gui.Dialogs.ReferenceDialog.ServiceReference
void AddServiceReferencesItemToProject()
{
if (IsServiceReferencesItemMissingFromProject()) {
var projectItem = new ServiceReferencesProjectItem(project);
projectItem.Include = "Service References";
AddProjectItemToProject(projectItem);
}
}
bool IsServiceReferencesItemMissingFromProject()
{
return project.GetItemsOfType(ItemType.ServiceReferences).Count() == 0;
}
void AddServiceReferenceItemToProject(ServiceReferenceFileName fileName)
{

79
src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/Commands/ReferenceFolderNodeCommands.cs

@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Web.Services.Discovery;
using System.Windows.Forms;
@ -180,52 +181,68 @@ namespace ICSharpCode.SharpDevelop.Project.Commands @@ -180,52 +181,68 @@ namespace ICSharpCode.SharpDevelop.Project.Commands
}
}
public class ShowServiceInBrowser: AbstractMenuCommand
public class ShowServiceInBrowser : AbstractMenuCommand
{
private static string NodePath = "//system.serviceModel//client//endpoint";
static string NodePath = "//system.serviceModel//client//endpoint";
public override void Run()
{
// hack try url fvoid = LoadConfigDocument(f);
AbstractProjectBrowserTreeNode node = ProjectBrowserPad.Instance.SelectedNode;
var f = CompilableProject.GetAppConfigFile(node.Project,false);
if (!String.IsNullOrEmpty(f))
{
var configFile = LoadConfigDocument(f);
var endPoint = configFile.SelectSingleNode(NodePath).Attributes["address"].Value;
ProcessStartInfo startInfo = new ProcessStartInfo("IExplore.exe");
startInfo.WindowStyle = ProcessWindowStyle.Normal;
startInfo.Arguments = endPoint;
Process.Start(startInfo);
XmlDocument appConfig = LoadAppConfig();
if (appConfig != null) {
string endpointAddress = FindEndPointAddress(appConfig);
if (endpointAddress != null) {
StartInternetExplorer(endpointAddress);
} else {
MessageService.ShowError("No service found.");
}
} else {
MessageService.ShowError("No app.config file found.");
}
}
} else
XmlDocument LoadAppConfig()
{
MessageService.ShowError("No app.config File found");
AbstractProjectBrowserTreeNode node = ProjectBrowserPad.Instance.SelectedNode;
FileName appConfigFileName = CompilableProject.GetAppConfigFile(node.Project, false);
if (!String.IsNullOrEmpty(appConfigFileName)) {
return LoadAppConfig(appConfigFileName);
}
return null;
}
static XmlDocument LoadConfigDocument(string fileName)
{
XmlDocument doc = null;
try
static XmlDocument LoadAppConfig(string fileName)
{
doc = new XmlDocument();
try {
var doc = new XmlDocument();
doc.Load(fileName);
return doc;
} catch (FileNotFoundException ex) {
LoggingService.Debug("LoadConfigDocument: " + fileName + ": " + ex.Message);
}
catch (System.IO.FileNotFoundException e)
return null;
}
string FindEndPointAddress(XmlDocument appConfig)
{
throw new Exception("No configuration file found.", e);
XmlNode endPoint = appConfig.SelectSingleNode(NodePath);
if (endPoint != null) {
XmlAttribute addressAttribute = endPoint.Attributes["address"];
if (addressAttribute != null) {
return addressAttribute.Value;
}
}
return null;
}
void StartInternetExplorer(string arguments)
{
var startInfo = new ProcessStartInfo("IExplore.exe") {
WindowStyle = ProcessWindowStyle.Normal,
Arguments = arguments
};
Process.Start(startInfo);
}
}
public class AddServiceReferenceToProject : AbstractMenuCommand
{
@ -247,14 +264,12 @@ namespace ICSharpCode.SharpDevelop.Project.Commands @@ -247,14 +264,12 @@ namespace ICSharpCode.SharpDevelop.Project.Commands
}
}
public class RefreshReference : AbstractMenuCommand
{
public override void Run()
{
ReferenceNode node = Owner as ReferenceNode;
if (node != null)
{
var node = Owner as ReferenceNode;
if (node != null) {
ReferenceProjectItem item = node.ReferenceProjectItem;
if (item != null) {
AssemblyParserService.RefreshProjectContentForReference(item);

20
src/Main/Base/Test/ServiceReferences/ProjectWithServiceReferencesTests.cs

@ -63,6 +63,11 @@ namespace ICSharpCode.SharpDevelop.Tests.ServiceReferences @@ -63,6 +63,11 @@ namespace ICSharpCode.SharpDevelop.Tests.ServiceReferences
return msbuildProject.GetItemsOfType(ItemType.ServiceReferences).SingleOrDefault() as ServiceReferencesProjectItem;
}
int GetHowManyWCFMetadataItemsInMSBuildProject()
{
return msbuildProject.GetItemsOfType(ItemType.ServiceReferences).Count();
}
ProjectItem GetFileProjectItemInMSBuildProject(string fileName)
{
return msbuildProject.Items.SingleOrDefault(item => item.FileName == fileName);
@ -175,6 +180,21 @@ namespace ICSharpCode.SharpDevelop.Tests.ServiceReferences @@ -175,6 +180,21 @@ namespace ICSharpCode.SharpDevelop.Tests.ServiceReferences
Assert.AreEqual("Service References", item.Include);
}
[Test]
public void AddServiceReferenceProxyFile_ProjectHasServiceReferences_WCFMetadataItemNotAddedToProjectForServiceReferencesRootFolder()
{
CreateProjectWithMSBuildProject();
var proxyFileName = new ServiceReferenceFileName() { ServiceName = "Service1" };
project.AddServiceReferenceProxyFile(proxyFileName);
proxyFileName = new ServiceReferenceFileName() { ServiceName = "Service2" };
project.AddServiceReferenceProxyFile(proxyFileName);
int count = GetHowManyWCFMetadataItemsInMSBuildProject();
Assert.AreEqual(1, count);
}
[Test]
public void AddServiceReferenceProxyFile_ProjectHasNoServiceReferences_WCFMetadataStorageItemAddedToProjectForServiceReferencesFolder()
{

Loading…
Cancel
Save