Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--.gitmodules8
-rw-r--r--Makefile2
-rwxr-xr-xconfigure14
-rw-r--r--dependency_checker.rb72
-rw-r--r--main/Main.sln38
-rw-r--r--main/Makefile.am10
-rw-r--r--main/Makefile.include5
-rw-r--r--main/build/MacOSX/Info.plist.in55
-rw-r--r--main/build/MacOSX/Makefile.am19
-rw-r--r--main/build/MacOSX/monostub-test.m228
-rw-r--r--main/build/MacOSX/monostub-utils.h246
-rw-r--r--main/build/MacOSX/monostub.m220
-rw-r--r--main/build/Makefile.am2
-rw-r--r--main/configure.in32
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Ast/Annotations.cs4
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Ast/AstBuilder.cs30
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs104
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Ast/TextTokenWriter.cs28
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Ast/Transforms/DeclareVariables.cs31
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs14
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Ast/Transforms/ExpressionTreeConverter.cs2
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUnsafeModifier.cs6
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUsingDeclarations.cs23
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs92
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs40
-rw-r--r--main/contrib/ICSharpCode.Decompiler/CecilExtensions.cs47
-rw-r--r--main/contrib/ICSharpCode.Decompiler/DecompilerException.cs2
-rw-r--r--main/contrib/ICSharpCode.Decompiler/DecompilerSettings.cs16
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs8
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs4
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs22
-rw-r--r--main/contrib/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj12
-rw-r--r--main/contrib/ICSharpCode.Decompiler/ILAst/AsyncDecompiler.cs99
-rw-r--r--main/contrib/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs8
-rw-r--r--main/contrib/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs221
-rw-r--r--main/contrib/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs2
-rw-r--r--main/contrib/ICSharpCode.Decompiler/ILAst/ILInlining.cs20
-rw-r--r--main/contrib/ICSharpCode.Decompiler/ILAst/PatternMatching.cs6
-rw-r--r--main/contrib/ICSharpCode.Decompiler/ILAst/StateRange.cs14
-rw-r--r--main/contrib/ICSharpCode.Decompiler/ILAst/SymbolicExecution.cs15
-rw-r--r--main/contrib/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs15
-rw-r--r--main/contrib/ICSharpCode.Decompiler/ILAst/YieldReturnDecompiler.cs30
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Properties/AssemblyInfo.template.cs27
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Tests/Async.cs155
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Tests/CodeSampleFileParser.cs3
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Tests/ControlFlow.cs97
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Tests/CustomShortCircuitOperators.cs88
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs32
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Tests/DelegateConstruction.cs16
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Tests/DoubleConstants.cs28
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Tests/ExpressionTrees.cs370
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Tests/Helpers/CodeAssert.cs110
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj7
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Tests/IL/ILTests.cs51
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.Output.cs53
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.dllbin0 -> 2560 bytes
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.il140
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Tests/IL/StackTests.exebin0 -> 2048 bytes
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Tests/IL/StackTests.il132
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Tests/LiftedOperators.cs830
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Tests/Lock.cs38
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Tests/PInvoke.cs96
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Tests/QueryExpressions.cs188
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Tests/TestRunner.cs63
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Tests/TypeAnalysisTests.cs153
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Tests/Types/S_TypeDeclarations.cs17
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Tests/Types/S_TypeMemberDeclarations.cs2
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Tests/UndocumentedExpressions.cs41
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Tests/UnsafeCode.cs42
-rw-r--r--main/contrib/ICSharpCode.Decompiler/Tests/ValueTypes.cs17
m---------main/external/debugger-libs0
m---------main/external/fsharpbinding0
m---------main/external/libgit-binary0
m---------main/external/libgit20
m---------main/external/libgit2sharp0
m---------main/external/mono-addins0
m---------main/external/monomac0
m---------main/external/nrefactory0
m---------main/external/nuget-binary0
m---------main/external/xwt0
-rw-r--r--main/src/addins/AspNet/Tests/MonoDevelop.AspNet.Tests.csproj1
-rw-r--r--main/src/addins/AspNet/Tests/WebForms/WebFormsSyntaxModeTests.cs66
-rw-r--r--main/src/addins/AspNet/WebForms/WebFormsSyntaxMode.cs10
-rw-r--r--main/src/addins/CBinding/CBinding.Autotools/CBinding.Autotools.csproj2
-rw-r--r--main/src/addins/CBinding/Gui/GeneralOptionsPanel.cs3
-rw-r--r--main/src/addins/CSharpBinding/AddinInfo.cs1
-rw-r--r--main/src/addins/CSharpBinding/Autotools/Autotools.csproj2
-rw-r--r--main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/MemberCompletionData.cs2
-rw-r--r--main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring.CodeActions/MDRefactoringScript.cs2
-rw-r--r--main/src/addins/CSharpBinding/MonoDevelop.CSharp.Resolver/TextEditorResolverProvider.cs2
-rw-r--r--main/src/addins/CSharpBinding/MonoDevelop.CSharp/PathedDocumentTextEditorExtension.cs97
-rw-r--r--main/src/addins/CSharpBinding/templates/PortableLibrary.xpt.xml2
-rw-r--r--main/src/addins/CSharpBinding/templates/SharedAssetsProject.xpt.xml2
-rw-r--r--main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.csproj1
-rw-r--r--main/src/addins/MacPlatform/Dialogs/MacAddFileDialogHandler.cs3
-rw-r--r--main/src/addins/MacPlatform/Dialogs/MacOpenFileDialogHandler.cs23
-rw-r--r--main/src/addins/MacPlatform/Dialogs/MacSelectFileDialogHandler.cs12
-rw-r--r--main/src/addins/MacPlatform/MacPlatform.cs4
-rw-r--r--main/src/addins/MacPlatform/MainToolbar/MainToolbar.cs164
-rw-r--r--main/src/addins/MacPlatform/MainToolbar/SearchBar.cs16
-rw-r--r--main/src/addins/MacPlatform/MainToolbar/SelectorView.cs211
-rw-r--r--main/src/addins/MacPlatform/MainToolbar/StatusBar.cs69
-rw-r--r--main/src/addins/MacPlatform/icons/build.pngbin326 -> 1460 bytes
-rw-r--r--main/src/addins/MacPlatform/icons/build@2x.pngbin387 -> 1642 bytes
-rw-r--r--main/src/addins/MacPlatform/icons/continue.pngbin349 -> 1470 bytes
-rw-r--r--main/src/addins/MacPlatform/icons/continue@2x.pngbin389 -> 1646 bytes
-rw-r--r--main/src/addins/MacPlatform/icons/device.pngbin228 -> 1302 bytes
-rw-r--r--main/src/addins/MacPlatform/icons/device@2x.pngbin261 -> 1416 bytes
-rw-r--r--main/src/addins/MacPlatform/icons/project.pngbin241 -> 1319 bytes
-rw-r--r--main/src/addins/MacPlatform/icons/project@2x.pngbin254 -> 1397 bytes
-rw-r--r--main/src/addins/MacPlatform/icons/stop.pngbin210 -> 1261 bytes
-rw-r--r--main/src/addins/MacPlatform/icons/stop@2x.pngbin209 -> 1283 bytes
-rw-r--r--main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyBrowserWidget.cs37
-rw-r--r--main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyLoader.cs3
-rw-r--r--main/src/addins/MonoDevelop.Debugger.Soft/MonoDevelop.Debugger.Soft/SoftDebuggerEngine.cs12
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests.NonUserCodeTestLib/MonoDevelop.Debugger.Tests.NonUserCodeTestLib.csproj3
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests.TestApp/TestEvaluation.cs46
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/DebugTests.cs10
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/EvaluationTests.cs129
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.csproj1
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/AttachToProcessDialog.cs3
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BreakpointPad.cs2
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BusyEvaluatorDialog.cs13
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggerConsoleView.cs11
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggerOptionsPanelWidget.cs69
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs5
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DisassemblyView.cs3
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Extensions.cs20
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/LocalsPad.cs80
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValueTreeView.cs2
-rw-r--r--main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/StackTracePad.cs287
-rw-r--r--main/src/addins/MonoDevelop.Debugger/gtk-gui/MonoDevelop.Debugger.BusyEvaluatorDialog.cs110
-rw-r--r--main/src/addins/MonoDevelop.Debugger/gtk-gui/MonoDevelop.Debugger.DebuggerOptionsPanelWidget.cs187
-rw-r--r--main/src/addins/MonoDevelop.Debugger/gtk-gui/generated.cs64
-rw-r--r--main/src/addins/MonoDevelop.Debugger/gtk-gui/gui.stetic277
-rw-r--r--main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Projects/ProjectFileDescriptor.cs30
-rw-r--r--main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/ToolboxWidget.cs160
-rw-r--r--main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/CustomDescriptor.cs11
-rw-r--r--main/src/addins/MonoDevelop.GtkCore/libstetic/libstetic.csproj4
-rw-r--r--main/src/addins/MonoDevelop.GtkCore/libstetic/wrapper/Misc.cs5
-rw-r--r--main/src/addins/MonoDevelop.GtkCore/libsteticui/libsteticui.csproj4
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/PackageManagementStartupHandler.cs4
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackage.cs9
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageManagementProject.cs5
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeSettings.cs30
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableCheckForUpdatesTaskRunner.cs (renamed from main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/TestableCheckForUpdatesTaskRunner.cs)28
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj8
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/BackgroundPackageActionRunnerTests.cs6
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/CheckForUpdatesProgressMonitorTests.cs148
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/DotNetProjectExtensionsTests.cs135
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/FilePathExtensionsTests.cs111
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/InstallPackageActionTests.cs10
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/MinClientVersionTests.cs69
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/MonoDevelopProjectSystemTests.cs13
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageFromRepositoryTests.cs13
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageManagementOptionsTests.cs42
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/UninstallPackageActionTests.cs20
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/UpdatePackageActionTests.cs16
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/UpdatedPackagesInSolutionTests.cs84
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.csproj5
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/BackgroundPackageActionRunner.cs2
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/CheckForUpdatesProgressMonitor.cs104
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/CheckForUpdatesTask.cs12
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/CheckForUpdatesTaskRunner.cs40
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/DotNetProjectExtensions.cs56
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/DotNetProjectImportEventArgs.cs (renamed from main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableCheckForUpdatesProgressMonitor.cs)24
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/FilePathExtensions.cs9
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageManagementEvents.cs2
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageFromRepository.cs5
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementEvents.cs9
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementEventsMonitor.cs23
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementServices.cs2
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementSolutionExtensions.cs43
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageRestoreRunner.cs2
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageRestorer.cs2
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageUpdatesEventMonitor.cs73
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProcessPackageAction.cs4
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProcessPackageOperationsAction.cs2
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProgressMonitorStatusMessageFactory.cs9
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RegisteredPackageSourceSettings.cs2
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SettingsProvider.cs2
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SharpDevelopProjectSystem.cs3
-rw-r--r--main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ThreadSafePackageManagementEvents.cs10
-rw-r--r--main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/AnalysisCommands.cs5
-rw-r--r--main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionEditorExtension.cs2
-rw-r--r--main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.Rename/RenameItemDialog.cs1
-rw-r--r--main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.addin.xml4
-rw-r--r--main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.csproj1
-rw-r--r--main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringService.cs48
-rw-r--r--main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoryCommands.cs72
-rw-r--r--main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.OptionPanels/HighlightingPanel.cs51
-rw-r--r--main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.csproj2
-rw-r--r--main/src/addins/MonoDevelop.SourceEditor2/gtk-gui/gui.stetic1
-rw-r--r--main/src/addins/MonoDeveloperExtensions/NUnit/NUnit.csproj5
-rw-r--r--main/src/addins/NUnit/Commands/NUnitCommands.cs3
-rw-r--r--main/src/addins/NUnit/Gui/TestResultsPad.cs63
-rw-r--r--main/src/addins/NUnit/MonoDevelop.NUnit.csproj2
-rw-r--r--main/src/addins/NUnit/MonoDevelopNUnit.addin.xml2
-rw-r--r--main/src/addins/TextTemplating/TextTransform/TextTransform.csproj1
-rw-r--r--main/src/addins/VBNetBinding/VBNetBinding.csproj2
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseGitRepositoryTests.cs34
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseRepositoryTests.cs8
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/GitIntegrityTests.cs27
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/MonoDevelop.VersionControl.Git.Tests.csproj3
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git.csproj7
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/EditRemoteDialog.cs21
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitCommitDialogExtension.cs16
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitConfigurationDialog.cs12
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitCredentials.cs105
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitRepository.cs226
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitUtil.cs7
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitVersionControl.cs6
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/TfsSmartSubtransport.cs166
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion.Tests/RepositoryTests.cs5
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion.Unix/MonoDevelop.VersionControl.Subversion.Unix.csproj2
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion.csproj4
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion/SubversionRepository.cs2
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion/SubversionVersionControl.cs8
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Dialogs/CommitDialog.cs18
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Dialogs/CommitMessageStylePanelWidget.cs3
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Dialogs/EditRepositoryDialog.cs5
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Dialogs/SelectRepositoryDialog.cs7
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/BlameWidget.cs19
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/LogWidget.cs12
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/VersionControlDocumentInfo.cs6
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/AddRemoveMoveCommand.cs4
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/BlameCommand.cs1
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/ChangeLogWriter.cs1
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/CheckoutCommand.cs2
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Commands.cs41
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/CommitDialogExtension.cs5
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/DefaultBlameViewHandler.cs2
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/IgnoreCommand.cs4
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/LockCommand.cs2
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/PublishCommand.cs3
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Repository.cs16
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/RevertCommand.cs2
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/RevertRevisionsCommands.cs2
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/UnlockCommand.cs2
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/UpdateCommand.cs2
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlItem.cs13
-rw-r--r--main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlService.cs31
-rw-r--r--main/src/addins/VersionControl/Subversion.Win32.Tests/RepositoryTests.cs16
-rw-r--r--main/src/addins/VersionControl/Subversion.Win32/SvnSharpClient.cs17
-rw-r--r--main/src/addins/VersionControl/Subversion.Win32/VersionControl.Subversion.Win32.csproj8
-rw-r--r--main/src/addins/VersionControl/Subversion.Win32/packages.config2
-rw-r--r--main/src/addins/WindowsPlatform/WindowsPlatform/AddinInfo.cs2
-rw-r--r--main/src/addins/WindowsPlatform/WindowsPlatform/Dialogs/CommonFileDialogExtensions.cs6
-rw-r--r--main/src/addins/WindowsPlatform/WindowsPlatform/Dialogs/OpenFileDialogHandler.cs9
-rw-r--r--main/src/addins/WindowsPlatform/WindowsPlatform/Dialogs/SelectFileDialogHandler.cs2
-rw-r--r--main/src/addins/WindowsPlatform/WindowsPlatform/JumpList.cs20
-rw-r--r--main/src/addins/WindowsPlatform/WindowsPlatform/WindowsPlatform.cs4
-rw-r--r--main/src/addins/WindowsPlatform/WindowsPlatform/WindowsPlatform.csproj2
-rw-r--r--main/src/addins/Xml/Properties/MonoDevelop.XmlEditor.addin.xml1
-rw-r--r--main/src/addins/Xml/Tests/MonoDevelop.Xml.Tests.csproj1
-rw-r--r--main/src/core/Mono.Texteditor/Mono.TextEditor.Highlighting/SemanticRule.cs2
-rw-r--r--main/src/core/Mono.Texteditor/Mono.TextEditor.Highlighting/SyntaxModeService.cs16
-rw-r--r--main/src/core/Mono.Texteditor/Mono.TextEditor/Document/TextDocument.cs2
-rw-r--r--main/src/core/Mono.Texteditor/Mono.TextEditor/Gui/GtkWorkarounds.cs36
-rw-r--r--main/src/core/Mono.Texteditor/Mono.TextEditor/Gui/TextArea.cs14
-rw-r--r--main/src/core/Mono.Texteditor/Mono.TextEditor/Gui/TextViewMargin.cs4
-rw-r--r--[-rwxr-xr-x]main/src/core/Mono.Texteditor/Mono.TextEditor/Platform.cs0
-rw-r--r--main/src/core/Mono.Texteditor/Mono.TextEditor/SimpleEditMode.cs2
-rw-r--r--main/src/core/Mono.Texteditor/SyntaxModes/XmlSyntaxMode.xml15
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Core.Assemblies/MonoTargetRuntime.cs5
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Core.Instrumentation/TimeCounter.cs13
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Core.Logging/FileLogger.cs4
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/ConsoleProgressMonitor.cs11
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Core/FilePath.cs14
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Core/Gettext.cs4
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Core/LoggingService.cs34
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Core/SystemInformation.cs11
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildFileFormat.cs2
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProjectHandler.cs3
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProjectService.cs14
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/RemoteProjectBuilder.cs2
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/SlnFileFormat.cs2
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Policies/PolicyService.cs5
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects.SharedAssetsProjects/SharedAssetsProject.cs2
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Text/TextFormatter.cs10
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProject.cs16
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProjectConfiguration.cs2
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs28
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectFile.cs5
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectService.cs5
-rw-r--r--main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Solution.cs3
-rw-r--r--main/src/core/MonoDevelop.Ide/AssemblyInfo.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml35
-rw-r--r--main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml11
-rw-r--r--main/src/core/MonoDevelop.Ide/ExtensionModel/MimeTypes.addin.xml5
-rw-r--r--main/src/core/MonoDevelop.Ide/ExtensionModel/Templates.addin.xml5
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Operations/ChildrenOperation.cs9
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Operations/SelectedOperation.cs53
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkNotebookResult.cs8
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkTreeModelResult.cs127
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkWidgetResult.cs44
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/NSObjectResult.cs84
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/ObjectResult.cs5
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AppQuery.cs10
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AppResult.cs61
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AutoTestClientSession.cs32
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AutoTestService.cs296
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AutoTestSession.cs64
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/ObjectProperties.cs6
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs13
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockNotebook.cs16
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/TabStrip.cs4
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockFrame.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockItem.cs9
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Extensions/ISelectFileDialog.cs27
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainStatusBarContextImpl.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbar.cs29
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarController.cs112
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarModels.cs57
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchInSolutionSearchCategory.cs12
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchPopupWindow.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/FilePathEditor.cs12
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/TextEditor.cs5
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyGrid.cs4
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyGridTable.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsGtk.cs41
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsMac.cs14
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/FileEntry.cs6
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/MenuButton.cs56
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PathBar.cs6
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SelectFileDialog.cs9
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SelectFolderDialog.cs6
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Tabstrip.cs18
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Windows/GtkWPFWidget.cs142
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Windows/GtkWin32Interop.cs118
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionWindowManager.cs10
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplate.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileCommands.cs23
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileTabCommands.cs42
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ProjectCommands.cs11
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ToolsCommands.cs63
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/WindowCommands.cs43
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Desktop/RecentOpen.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindInFilesDialog.cs9
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/ExtensibleTreeView.cs166
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/LogView.cs7
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/DirtyFilesDialog.cs21
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/OpenFileDialog.cs22
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/KeyBindingsPanel.cs28
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/FolderNodeBuilder.cs5
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFileNodeBuilder.cs54
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFolderNodeBuilder.cs4
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectNodeBuilder.cs10
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/ErrorListPad.cs36
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/MonodocTreePad.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DefaultWorkbench.cs3
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Document.cs3
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/ProgressMonitors.cs4
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/StatusProgressMonitor.cs40
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs39
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Navigation/NavigationHistoryService.cs9
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AddExternalFileDialog.cs1
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AddFileDialog.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AssemblyReferencePanel.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/DefaultPolicyOptionsDialog.cs62
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ExportProjectPolicyDialog.cs6
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkNewProjectDialogBackend.UI.cs29
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkNewProjectDialogBackend.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkTemplateCellRenderer.cs41
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewProjectController.cs85
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ProjectTemplateCategorizer.cs7
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/CodeGenerationService.cs23
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemService.cs12
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj47
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Ide.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs20
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs14
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/RootWorkspace.cs11
-rw-r--r--main/src/core/MonoDevelop.Projects.Formats.MSBuild/AssemblyInfo.v14.0.cs9
-rw-r--r--main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild.csproj1
-rw-r--r--main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild.dotnet.v14.0.csproj69
-rw-r--r--main/src/core/MonoDevelop.Projects.Formats.MSBuild/app.v14.0.config16
-rw-r--r--main/src/core/MonoDevelop.Startup/MonoDevelop.Startup.csproj12
-rw-r--r--main/src/core/MonoDevelop.Startup/app.config5
-rw-r--r--main/src/core/MonoDevelop.Startup/app.manifest54
-rw-r--r--main/src/core/MonoDevelop.TextEditor.Tests/MonoDevelop.TextEditor.Tests.csproj1
-rw-r--r--main/tests/Makefile.am10
-rw-r--r--main/tests/TestRunner/TestRunner.csproj1
-rw-r--r--main/tests/UnitTests/MonoDevelop.Core/FilePathTests.cs4
-rw-r--r--main/tests/UnitTests/MonoDevelop.Core/LoggingServiceTests.cs223
-rw-r--r--main/tests/UnitTests/MonoDevelop.Ide.Templates/ProjectTemplateCategorizerTests.cs22
-rw-r--r--main/tests/UnitTests/UnitTests.csproj1
-rw-r--r--main/tests/UserInterfaceTests/Controllers/NewFileController.cs27
-rw-r--r--main/tests/UserInterfaceTests/Controllers/NewProjectController.cs73
-rw-r--r--main/tests/UserInterfaceTests/Controllers/NuGetController.cs87
-rw-r--r--main/tests/UserInterfaceTests/Controllers/NuGetOptions.cs179
-rw-r--r--main/tests/UserInterfaceTests/Controllers/OptionsController.cs148
-rw-r--r--main/tests/UserInterfaceTests/Controllers/SolutionExplorerController.cs62
-rw-r--r--main/tests/UserInterfaceTests/CreateBuildTemplatesTestBase.cs119
-rw-r--r--main/tests/UserInterfaceTests/DialogTests/NewProjectDialogTests.cs3
-rw-r--r--main/tests/UserInterfaceTests/DialogTests/NuGetDialogTests.cs229
-rw-r--r--main/tests/UserInterfaceTests/Exceptions/CreateProjectException.cs37
-rw-r--r--main/tests/UserInterfaceTests/Exceptions/NuGetException.cs41
-rw-r--r--main/tests/UserInterfaceTests/Exceptions/TemplateSelectionException.cs37
-rw-r--r--main/tests/UserInterfaceTests/Ide.cs171
-rw-r--r--main/tests/UserInterfaceTests/IdeQuery.cs20
-rw-r--r--main/tests/UserInterfaceTests/LogMessageValidator.cs56
-rw-r--r--main/tests/UserInterfaceTests/TemplateTestOptions.cs39
-rw-r--r--main/tests/UserInterfaceTests/TemplateTests/ASPNETTemplateTests.cs28
-rw-r--r--main/tests/UserInterfaceTests/TemplateTests/DotNetTemplatesTest.cs15
-rw-r--r--main/tests/UserInterfaceTests/TemplateTests/MiscTemplatesTest.cs24
-rw-r--r--main/tests/UserInterfaceTests/TestService.cs2
-rw-r--r--main/tests/UserInterfaceTests/UITestBase.cs158
-rw-r--r--main/tests/UserInterfaceTests/UserInterfaceTests.csproj36
-rw-r--r--main/tests/UserInterfaceTests/Util.cs28
-rw-r--r--main/tests/UserInterfaceTests/VersionControlTests/Git/GitBase.cs478
-rw-r--r--main/tests/UserInterfaceTests/VersionControlTests/Git/GitRepositoryConfigurationTests.cs356
-rw-r--r--main/tests/UserInterfaceTests/VersionControlTests/Git/GitStashManagerTests.cs119
-rw-r--r--main/tests/UserInterfaceTests/VersionControlTests/Git/GitTests.cs (renamed from main/tests/UserInterfaceTests/VersionControlTests/GitTests.cs)45
-rw-r--r--main/tests/UserInterfaceTests/VersionControlTests/GitRepositoryConfigurationTests.cs310
-rw-r--r--main/tests/UserInterfaceTests/VersionControlTests/VCSBase.cs106
-rw-r--r--main/tests/UserInterfaceTests/Workbench.cs147
-rw-r--r--main/winbuild.bat8
-rw-r--r--main/xbuild.include14
-rwxr-xr-xscripts/configure.sh2
-rwxr-xr-xversion-checks2
-rw-r--r--version.config4
423 files changed, 12193 insertions, 3693 deletions
diff --git a/.gitignore b/.gitignore
index aab458d174..6be31b600d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,6 +15,7 @@ obj/
/main/tests/config
/main/tests/UnitTests/test-results
/main/build/MacOSX/monostub
+/main/build/MacOSx/monostub-test
/main/contrib/bin/
/main/contrib/*/*/bin/
/local-libs
@@ -50,6 +51,7 @@ install-sh
autom4te.cache/
*.user
*.tar.gz
+*.dSYM
tarballs/
test-results/
Thumbs.db
diff --git a/.gitmodules b/.gitmodules
index c07ce77afd..44fbace703 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,7 +1,7 @@
[submodule "main/external/cecil"]
path = main/external/cecil
url = git://github.com/mono/cecil.git
- branch = mono-3.0
+ branch = monodevelop
[submodule "main/external/mono-tools"]
path = main/external/mono-tools
url = git://github.com/mono/mono-tools.git
@@ -43,12 +43,12 @@
url = git://github.com/mono/sharpsvn-binary.git
[submodule "main/external/libgit2sharp"]
path = main/external/libgit2sharp
- url = git://github.com/libgit2/libgit2sharp.git
- branch = xs-5.10-v1
+ url = git://github.com/mono/libgit2sharp.git
+ branch = xs-5.10-v2
[submodule "main/external/libgit-binary"]
path = main/external/libgit-binary
url = git://github.com/mono/libgit-binary.git
[submodule "main/external/libgit2"]
path = main/external/libgit2
url = git://github.com/mono/libgit2.git
- branch = xs-5.10-v1
+ branch = xs-5.10-v2
diff --git a/Makefile b/Makefile
index 1a90af8a5e..baf269d832 100644
--- a/Makefile
+++ b/Makefile
@@ -113,7 +113,7 @@ test:
cd main && $(MAKE) test assembly=$(assembly)
uitest:
- cd main && $(MAKE) uitest assembly=$(assembly)
+ cd main && $(MAKE) uitest assembly=$(assembly) tests=$(tests)
coverage:
cd main && $(MAKE) coverage
diff --git a/configure b/configure
index 42d2ae1231..e40c3d5391 100755
--- a/configure
+++ b/configure
@@ -2,6 +2,7 @@
VERSION=2.1.0
profile=default
tests=no
+release=no
prefix=NONE
test -e "$CONFIG_SITE" && . "$CONFIG_SITE"
test "$prefix" = NONE && prefix=/usr/local
@@ -10,7 +11,7 @@ usage ()
{
profiles=`ls profiles | sed -e "s/$/,/g" | fmt | sed -e 's/,$//' -e "s/ChangeLog, //"`
echo ""
- echo "Usage : configure [--prefix=PREFIX] [--select] [--profile=PROFILE]"
+ echo "Usage : configure [--prefix=PREFIX] [--select] [--profile=PROFILE] [--release-builds]"
echo ""
echo "This script allows selecting and configuring a set of MonoDevelop"
echo "modules to be included in an integrated build."
@@ -49,6 +50,9 @@ usage ()
echo "--enable-tests"
echo " Build the md test suite"
echo ""
+ echo "--enable-release"
+ echo " Builds md in release mode"
+ echo ""
echo "--profile=PROFILE"
echo ""
echo " Configure the build system using the provided profile."
@@ -167,6 +171,9 @@ configure_packages ()
prefixarg=""
fi
done
+ if test xyes == x$release; then
+ ops="$ops --enable-release"
+ fi
title="Configuring package: $path"
nc=`echo $title | wc -m`
@@ -225,6 +232,9 @@ while test x$1 != x; do
--enable-tests)
tests=yes
;;
+ --enable-release)
+ release=yes
+ ;;
--prefix=*)
prefix=`echo $1 | sed 's/--prefix=//'`
;;
@@ -283,6 +293,8 @@ if test `uname` = "Darwin"; then
fi
# add in libsvn's directory as a fallback path. user-set paths will override it
export DYLD_FALLBACK_LIBRARY_PATH="$DYLD_FALLBACK_LIBRARY_PATH:/Library/Developer/CommandLineTools/usr/lib:/usr/local/lib:`pwd`/main/build/bin"
+
+ ruby dependency_checker.rb || exit 1
fi
configure_packages
diff --git a/dependency_checker.rb b/dependency_checker.rb
new file mode 100644
index 0000000000..ff4ba3533e
--- /dev/null
+++ b/dependency_checker.rb
@@ -0,0 +1,72 @@
+require 'pp'
+
+NOT_INSTALLED_VERSION="-1"
+
+XAMARIN_MAC_MIN_VERSION="2.3"
+XAMARIN_MAC_VERSION=lambda { product_version ("/Library/Frameworks/Xamarin.Mac.framework/Versions/Current/bin/mmp") }
+XAMARIN_MAC_URL="http://www.xamarin.com"
+
+MONO_MIN_VERSION="4.2"
+MONO_VERSION=lambda { mono_version("/Library/Frameworks/Mono.framework/Versions/Current/bin/mono") }
+MONO_URL="http://mono-project.com"
+
+class String
+ def red; "\e[31m#{self}\e[0m" end
+end
+
+def compare_version(first, second)
+ val1 = first.split('.').map { |x| x.to_i }
+ val2 = second.split('.').map { |x| x.to_i }
+
+ return val1 <=> val2
+end
+
+def mono_version(binary)
+ if File.exist?("#{binary}")
+ actual_version = `#{binary} --version`
+ # Extract the version number from a string like this:
+ # `Mono JIT compiler version 4.2.0 (explicit/08b7103 Mon Aug 17 16:58:52 EDT 2015)`
+ actual_version = actual_version.split('version ')[1]
+ return actual_version.split(' ')[0]
+ else
+ return NOT_INSTALLED_VERSION
+ end
+end
+
+def product_version(binary)
+ if File.exist?("#{binary}")
+ version = `#{binary} --version`
+ return version.split(' ')[1]
+ else
+ return NOT_INSTALLED_VERSION
+ end
+end
+
+def check_product(product_min_version, product_version, product_url, product_name)
+ actual_version = product_version.call
+ retval = compare_version(actual_version, product_min_version)
+
+ if (retval < 0)
+ if (actual_version == NOT_INSTALLED_VERSION)
+ puts "You do not have #{product_name} installed.".red
+ else
+ puts "Your installed #{product_name} (#{actual_version}) is too old, please use #{product_min_version} or newer".red
+ end
+ puts "You can download it from #{product_url}".red
+ puts
+ end
+ return retval
+end
+
+def check_monodevelop_dependencies()
+ result = [
+ check_product(MONO_MIN_VERSION, MONO_VERSION, MONO_URL, "Mono"),
+ check_product(XAMARIN_MAC_MIN_VERSION, XAMARIN_MAC_VERSION, XAMARIN_MAC_URL, "Xamarin.Mac")
+ ]
+ if (result.min < 0)
+ exit 1
+ end
+end
+
+$stdout.sync = true
+check_monodevelop_dependencies() if __FILE__==$0
diff --git a/main/Main.sln b/main/Main.sln
index dd218b8092..fdbf3080b3 100644
--- a/main/Main.sln
+++ b/main/Main.sln
@@ -1,4 +1,4 @@
-
+
Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{9D360D43-0C05-49D6-84DB-4E7AB2F38F82}"
@@ -292,6 +292,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ide.Tests", "tests\Ide.Test
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsPlatform.Tests", "tests\WindowsPlatform.Tests\WindowsPlatform.Tests.csproj", "{865100E2-A29C-4FCD-B803-1A0B9A0A6EF7}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoDevelop.Projects.Formats.MSBuild.dotnet.v14.0", "src\core\MonoDevelop.Projects.Formats.MSBuild\MonoDevelop.Projects.Formats.MSBuild.dotnet.v14.0.csproj", "{8EE5A588-9445-48EC-97BD-BF066E7FFD51}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -570,16 +572,16 @@ Global
{27096E7F-C91C-4AC6-B289-6897A701DF21}.DebugGnome|Any CPU.Build.0 = Debug|Any CPU
{27096E7F-C91C-4AC6-B289-6897A701DF21}.DebugMac|Any CPU.ActiveCfg = DebugMac|Any CPU
{27096E7F-C91C-4AC6-B289-6897A701DF21}.DebugMac|Any CPU.Build.0 = DebugMac|Any CPU
- {27096E7F-C91C-4AC6-B289-6897A701DF21}.DebugWin32|Any CPU.ActiveCfg = Debug|Any CPU
- {27096E7F-C91C-4AC6-B289-6897A701DF21}.DebugWin32|Any CPU.Build.0 = Debug|Any CPU
+ {27096E7F-C91C-4AC6-B289-6897A701DF21}.DebugWin32|Any CPU.ActiveCfg = DebugWin32|Any CPU
+ {27096E7F-C91C-4AC6-B289-6897A701DF21}.DebugWin32|Any CPU.Build.0 = DebugWin32|Any CPU
{27096E7F-C91C-4AC6-B289-6897A701DF21}.Release|Any CPU.ActiveCfg = Release|Any CPU
{27096E7F-C91C-4AC6-B289-6897A701DF21}.Release|Any CPU.Build.0 = Release|Any CPU
{27096E7F-C91C-4AC6-B289-6897A701DF21}.ReleaseGnome|Any CPU.ActiveCfg = Release|Any CPU
{27096E7F-C91C-4AC6-B289-6897A701DF21}.ReleaseGnome|Any CPU.Build.0 = Release|Any CPU
{27096E7F-C91C-4AC6-B289-6897A701DF21}.ReleaseMac|Any CPU.ActiveCfg = ReleaseMac|Any CPU
{27096E7F-C91C-4AC6-B289-6897A701DF21}.ReleaseMac|Any CPU.Build.0 = ReleaseMac|Any CPU
- {27096E7F-C91C-4AC6-B289-6897A701DF21}.ReleaseWin32|Any CPU.ActiveCfg = Release|Any CPU
- {27096E7F-C91C-4AC6-B289-6897A701DF21}.ReleaseWin32|Any CPU.Build.0 = Release|Any CPU
+ {27096E7F-C91C-4AC6-B289-6897A701DF21}.ReleaseWin32|Any CPU.ActiveCfg = ReleaseWin32|Any CPU
+ {27096E7F-C91C-4AC6-B289-6897A701DF21}.ReleaseWin32|Any CPU.Build.0 = ReleaseWin32|Any CPU
{2A00A871-C641-4116-ADFD-29B7799952B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2A00A871-C641-4116-ADFD-29B7799952B4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2A00A871-C641-4116-ADFD-29B7799952B4}.DebugGnome|Any CPU.ActiveCfg = Debug|Any CPU
@@ -798,8 +800,8 @@ Global
{63D3B27A-D966-4902-90B3-30290E1692F1}.ReleaseGnome|Any CPU.Build.0 = Release|Any CPU
{63D3B27A-D966-4902-90B3-30290E1692F1}.ReleaseMac|Any CPU.ActiveCfg = Release|Any CPU
{63D3B27A-D966-4902-90B3-30290E1692F1}.ReleaseMac|Any CPU.Build.0 = Release|Any CPU
- {63D3B27A-D966-4902-90B3-30290E1692F1}.ReleaseWin32|Any CPU.ActiveCfg = Release|Any CPU
- {63D3B27A-D966-4902-90B3-30290E1692F1}.ReleaseWin32|Any CPU.Build.0 = Release|Any CPU
+ {63D3B27A-D966-4902-90B3-30290E1692F1}.ReleaseWin32|Any CPU.ActiveCfg = Release|x86
+ {63D3B27A-D966-4902-90B3-30290E1692F1}.ReleaseWin32|Any CPU.Build.0 = Release|x86
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU
{63E6915C-7EA4-4D76-AB28-0D7191EEA626}.DebugGnome|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU
@@ -1156,6 +1158,7 @@ Global
{9A415695-CF80-4845-AA80-0DA26CF1E256}.DebugMac|Any CPU.Build.0 = Debug|Any CPU
{9A415695-CF80-4845-AA80-0DA26CF1E256}.DebugWin32|Any CPU.ActiveCfg = Debug|Any CPU
{9A415695-CF80-4845-AA80-0DA26CF1E256}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9A415695-CF80-4845-AA80-0DA26CF1E256}.Release|Any CPU.Build.0 = Release|Any CPU
{9A415695-CF80-4845-AA80-0DA26CF1E256}.ReleaseGnome|Any CPU.ActiveCfg = Release|Any CPU
{9A415695-CF80-4845-AA80-0DA26CF1E256}.ReleaseGnome|Any CPU.Build.0 = Release|Any CPU
{9A415695-CF80-4845-AA80-0DA26CF1E256}.ReleaseMac|Any CPU.ActiveCfg = Release|Any CPU
@@ -1600,8 +1603,8 @@ Global
{DA8EDEA6-7DA8-435D-B1A0-F3A0CA07F424}.Release|Any CPU.Build.0 = Release|Any CPU
{DA8EDEA6-7DA8-435D-B1A0-F3A0CA07F424}.ReleaseGnome|Any CPU.ActiveCfg = Release|x86
{DA8EDEA6-7DA8-435D-B1A0-F3A0CA07F424}.ReleaseGnome|Any CPU.Build.0 = Release|x86
- {DA8EDEA6-7DA8-435D-B1A0-F3A0CA07F424}.ReleaseMac|Any CPU.ActiveCfg = Release|x86
- {DA8EDEA6-7DA8-435D-B1A0-F3A0CA07F424}.ReleaseMac|Any CPU.Build.0 = Release|x86
+ {DA8EDEA6-7DA8-435D-B1A0-F3A0CA07F424}.ReleaseMac|Any CPU.ActiveCfg = Release|Any CPU
+ {DA8EDEA6-7DA8-435D-B1A0-F3A0CA07F424}.ReleaseMac|Any CPU.Build.0 = Release|Any CPU
{DA8EDEA6-7DA8-435D-B1A0-F3A0CA07F424}.ReleaseWin32|Any CPU.ActiveCfg = Release|x86
{DA8EDEA6-7DA8-435D-B1A0-F3A0CA07F424}.ReleaseWin32|Any CPU.Build.0 = Release|x86
{DB96F55E-41C5-4330-A427-15A4EC028BBE}.Debug|Any CPU.ActiveCfg = Debug|x86
@@ -1868,6 +1871,20 @@ Global
{FEC19BDA-4904-4005-8C09-68E82E8BEF6A}.ReleaseMac|Any CPU.Build.0 = Release|Any CPU
{FEC19BDA-4904-4005-8C09-68E82E8BEF6A}.ReleaseWin32|Any CPU.ActiveCfg = Release|Any CPU
{FEC19BDA-4904-4005-8C09-68E82E8BEF6A}.ReleaseWin32|Any CPU.Build.0 = Release|Any CPU
+ {8EE5A588-9445-48EC-97BD-BF066E7FFD51}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {8EE5A588-9445-48EC-97BD-BF066E7FFD51}.DebugMac|Any CPU.ActiveCfg = Debug|x86
+ {8EE5A588-9445-48EC-97BD-BF066E7FFD51}.DebugWin32|Any CPU.ActiveCfg = Debug|x86
+ {8EE5A588-9445-48EC-97BD-BF066E7FFD51}.DebugWin32|Any CPU.Build.0 = Debug|x86
+ {8EE5A588-9445-48EC-97BD-BF066E7FFD51}.Release|Any CPU.ActiveCfg = Release|x86
+ {8EE5A588-9445-48EC-97BD-BF066E7FFD51}.DebugGnome|Any CPU.ActiveCfg = Debug|x86
+ {8EE5A588-9445-48EC-97BD-BF066E7FFD51}.ReleaseMac|Any CPU.ActiveCfg = Release|x86
+ {8EE5A588-9445-48EC-97BD-BF066E7FFD51}.ReleaseWin32|Any CPU.ActiveCfg = Release|x86
+ {8EE5A588-9445-48EC-97BD-BF066E7FFD51}.ReleaseWin32|Any CPU.Build.0 = Release|x86
+ {8EE5A588-9445-48EC-97BD-BF066E7FFD51}.ReleaseGnome|Any CPU.ActiveCfg = Release|x86
+ {8EE5A588-9445-48EC-97BD-BF066E7FFD51}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {8EE5A588-9445-48EC-97BD-BF066E7FFD51}.Debug|x86.Build.0 = Debug|Any CPU
+ {8EE5A588-9445-48EC-97BD-BF066E7FFD51}.Release|x86.ActiveCfg = Release|Any CPU
+ {8EE5A588-9445-48EC-97BD-BF066E7FFD51}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{7525BB88-6142-4A26-93B9-A30C6983390A} = {9D360D43-0C05-49D6-84DB-4E7AB2F38F82}
@@ -1997,6 +2014,7 @@ Global
{9E4BA410-8338-42EC-AF9C-422C35ECED81} = {78C10DAE-D3D7-44FC-93DF-831D8D54ECF9}
{73D4CC8B-BAB9-4A29-841B-F25C6311F067} = {78C10DAE-D3D7-44FC-93DF-831D8D54ECF9}
{865100E2-A29C-4FCD-B803-1A0B9A0A6EF7} = {78C10DAE-D3D7-44FC-93DF-831D8D54ECF9}
+ {8EE5A588-9445-48EC-97BD-BF066E7FFD51} = {8F48ECA6-CFFF-4EBF-BC92-817199EDE9AF}
EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution
StartupItem = src\core\MonoDevelop.Startup\MonoDevelop.Startup.csproj
@@ -2044,8 +2062,6 @@ Global
$12.inheritsSet = null
$12.scope = image/svg+xml
$0.XmlFormattingPolicy = $13
- $13.inheritsSet = null
- $13.scope = image/svgxml
outputpath = build\bin\
MakePkgConfig = False
MakeLibPC = True
diff --git a/main/Makefile.am b/main/Makefile.am
index 4f8c22d2a5..7420f7107e 100644
--- a/main/Makefile.am
+++ b/main/Makefile.am
@@ -18,6 +18,7 @@ all-local: vcrevision restore-packages sln_build
clean: clean-local
clean-local: sln_clean
+ cd build && $(MAKE) clean
restore-packages:
nuget restore
@@ -108,7 +109,14 @@ apidocs:
MD_LAUNCH=$(MD_LAUNCH_SETUP) $(MD_LAUNCH_EXTRA_ENV) UBUNTU_MENUPROXY=0 LIBOVERLAY_SCROLLBAR=0 exec -a "monodevelop" $(RUNTIME)
+if ENABLE_MACPLATFORM
+run: run-bundle
+else
run: run-sgen
+endif
+
+run-bundle: $(PROGRAM)
+ $(MD_LAUNCH_SETUP) $(MD_LAUNCH_EXTRA_ENV) $(MD_BIN_PATH)/MonoDevelop --no-redirect
run-boehm: runmd
@@ -156,7 +164,7 @@ test:
cd tests && $(MAKE) test assembly=$(assembly)
uitest:
- cd tests && $(MAKE) uitest assembly=$(assembly) categories=$(categories)
+ cd tests && $(MAKE) uitest assembly=$(assembly) categories=$(categories) tests=$(tests)
coverage:
cd tests && $(MAKE) coverage
diff --git a/main/Makefile.include b/main/Makefile.include
index 9a4ca5ad94..aad162dc13 100644
--- a/main/Makefile.include
+++ b/main/Makefile.include
@@ -10,11 +10,6 @@ abs_top_builddir ?= $(top_builddir)
MD_BIN_PATH=$(abs_top_builddir)/build/bin
MD_LAUNCH_SETUP= \
- PATH="$(PATH)" \
- PKG_CONFIG_PATH="$(PKG_CONFIG_PATH)" \
- LD_LIBRARY_PATH="$(LD_LIBRARY_PATH)" \
- DYLD_FALLBACK_LIBRARY_PATH="$(DYLD_FALLBACK_LIBRARY_PATH)" \
- MONO_GAC_PREFIX="$(MONO_GAC_PREFIX)" \
MONODEVELOP_LOCALE_PATH="$(abs_top_builddir)/build/locale" \
MONODEVELOP_TEST_PROFILE="$(MD_BIN_PATH)/test-profile"
diff --git a/main/build/MacOSX/Info.plist.in b/main/build/MacOSX/Info.plist.in
index 36151d1f8d..eb4657371a 100644
--- a/main/build/MacOSX/Info.plist.in
+++ b/main/build/MacOSX/Info.plist.in
@@ -71,6 +71,12 @@
<string>Editor</string>
<key>LSIsAppleDefaultForType</key>
<true/>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>com.microsoft.c-sharp</string>
+ </array>
+ <key>LSHandlerRank</key>
+ <string>Editor</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
@@ -115,6 +121,12 @@
<string>Editor</string>
<key>LSIsAppleDefaultForType</key>
<true/>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>org.fsharp.f-sharp</string>
+ </array>
+ <key>LSHandlerRank</key>
+ <string>Editor</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
@@ -185,7 +197,7 @@
<key>LSApplicationCategoryType</key>
<string>public.app-category.developer-tools</string>
<key>LSMinimumSystemVersion</key>
- <string>10.9</string>
+ <string>10.10</string>
<key>CFBundleIdentifier</key>
<string>com.xamarin.monodevelop</string>
<key>CFBundleInfoDictionaryVersion</key>
@@ -208,5 +220,46 @@
<true/>
<key>ReleaseId</key>
<string>@RELEASE_ID@</string>
+ <key>UTImportedTypeDeclarations</key>
+ <array>
+ <dict>
+ <key>UTTypeIdentifier</key>
+ <string>com.microsoft.c-sharp</string>
+ <key>UTTypeReferenceURL</key>
+ <string>http://www.microsoft.com/en-us/download/details.aspx?id=7029</string>
+ <key>UTTypeDescription</key>
+ <string>C# source</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>cs</string>
+ </array>
+ </dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.source-code</string>
+ </array>
+ </dict>
+ <dict>
+ <key>UTTypeIdentifier</key>
+ <string>org.fsharp.f-sharp</string>
+ <key>UTTypeReferenceURL</key>
+ <string>http://fsharp.org/specs/language-spec/</string>
+ <key>UTTypeDescription</key>
+ <string>F# source</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>fs</string>
+ </array>
+ </dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.source-code</string>
+ </array>
+ </dict>
+ </array>
</dict>
</plist>
diff --git a/main/build/MacOSX/Makefile.am b/main/build/MacOSX/Makefile.am
index cee1795909..001ac02948 100644
--- a/main/build/MacOSX/Makefile.am
+++ b/main/build/MacOSX/Makefile.am
@@ -12,27 +12,34 @@ MD_CONFIGURE=$(top_srcdir)/../scripts/configure.sh
PACKAGE_UPDATE_ID=$(shell $(MD_CONFIGURE) get-releaseid)
BUNDLE_VERSION=$(shell $(MD_CONFIGURE) get-version)
-CLEANFILES = render.exe
+CLEANFILES = render.exe monostub monostub-test
#DISTCLEANFILES =
EXTRA_DIST = dmg-bg.png DS_Store Info.plist.in make-dmg-bundle.sh render.cs
-all: app
+MONOSTUB_EXTRA_SOURCES = monostub-utils.h
+
+all: monostub monostub-test
render.exe: render.cs
- gmcs -r:System.Drawing render.cs
+ mcs -r:System.Drawing render.cs
dmg: render.exe app
./make-dmg-bundle.sh
monostub: monostub.m $(MONOSTUB_EXTRA_SOURCES)
- gcc -Wall -mmacosx-version-min=10.9 -m32 -o $@ $^ -framework AppKit
-# gcc -Wall -mmacosx-version-min=10.9 -m32 -o $@ $^ -framework AppKit -isysroot $(SDK_PATH)
+ gcc -Wall -mmacosx-version-min=10.10 -m32 -o $@ monostub.m -framework AppKit
+# gcc -Wall -mmacosx-version-min=10.10 -m32 -o $@ monostub.m -framework AppKit -isysroot $(SDK_PATH)
+ cp monostub ../bin/MonoDevelop
+
+monostub-test: monostub-test.m $(MONOSTUB_EXTRA_SOURCES)
+ gcc -g -Wall -mmacosx-version-min=10.10 -m32 -o $@ monostub-test.m -framework AppKit
+ ./monostub-test
clean-local:
rm -rf MonoDevelop.app
rm -f MonoDevelop*.dmg
-app: monostub
+app: monostub monostub-test
@echo ""
@echo "Creating directories in app bundle"
@echo ""
diff --git a/main/build/MacOSX/monostub-test.m b/main/build/MacOSX/monostub-test.m
new file mode 100644
index 0000000000..b9f76cd0a9
--- /dev/null
+++ b/main/build/MacOSX/monostub-test.m
@@ -0,0 +1,228 @@
+#include <stdio.h>
+
+#include "monostub-utils.h"
+
+void fail(void)
+{
+ NSLog(@"%@", [NSThread callStackSymbols]);
+ exit(1);
+}
+
+void check_string_equal(const char *expected, const char *actual)
+{
+ if (strcmp(expected, actual)) {
+ printf("Expected '%s'\nActual '%s'\n", expected, actual);
+ fail();
+ }
+}
+
+void check_bool_equal(int expected, int actual)
+{
+ if (expected != actual) {
+ printf("Expected '%d'\nActual '%d'\n", expected, actual);
+ fail();
+ }
+}
+
+void test_mono_lib_path(void)
+{
+ char *expected = "/Library/Frameworks/Mono.framework/Libraries/test";
+ char *actual = MONO_LIB_PATH("test");
+
+ check_string_equal(expected, actual);
+}
+
+void test_check_mono_version(void)
+{
+ typedef struct {
+ char *mono_version, *req_mono_version;
+ int expected;
+ } version_check;
+
+ version_check versions[] = {
+ // Lower than requirement
+ { "3.0", "3.1", FALSE },
+
+ // Higher than requirement
+ { "3.1", "3.0", TRUE },
+
+ // Release lower than requirement.
+ // FIXME
+ //{ "3.1", "3.1.1", FALSE },
+
+ // Release higher than requirement.
+ { "3.1.1", "3.1", TRUE },
+
+ // Bogus requirement value.
+ { "3.1", "BOGUS STRING", FALSE },
+ };
+
+ version_check *version;
+ int i;
+ for (i = 0; i < sizeof(versions) / sizeof(version_check); ++i) {
+ version = &versions[i];
+ check_bool_equal(version->expected, check_mono_version(version->mono_version, version->req_mono_version));
+ }
+}
+
+void test_str_append(void)
+{
+ char *str = "asdf";
+ char *conc = str_append(str, str);
+
+ check_string_equal("asdfasdf", conc);
+}
+
+void test_generate_fallback_path (void)
+{
+ char *actual = generate_fallback_path(".");
+
+ check_string_equal("./Resources/lib:./Resources/lib/monodevelop/bin:/Library/Frameworks/Mono.framework/Libraries:/lib:/usr/lib:/Library/Developer/CommandLineTools/usr/lib:/usr/local/lib", actual);
+}
+
+void test_env2bool(void)
+{
+ typedef struct {
+ bool expected, defaultValue;
+ const char *var, *value;
+ } bool_check;
+
+ bool_check bools[] = {
+ // If variable does not exist, return default.
+ { TRUE, TRUE, "WILL_NOT_EXIST", NULL },
+ { FALSE, FALSE, "WILL_NOT_EXIST", NULL },
+
+ // Check that truth-y values are true.
+ { TRUE, FALSE, "WILL_EXIST", "TRUE" },
+ { TRUE, FALSE, "WILL_EXIST", "YES" },
+ { TRUE, FALSE, "WILL_EXIST", "1" },
+
+ // Check that false-y values are false.
+ { FALSE, TRUE, "WILL_EXIST", "BOGUS" },
+ { FALSE, TRUE, "WILL_EXIST", "0" },
+ };
+
+ bool_check *current;
+ int i;
+ for (i = 0; i < sizeof(bools) / sizeof(bool_check); ++i) {
+ current = &bools[i];
+ if (current->value)
+ setenv(current->var, current->value, 1);
+
+ check_bool_equal(current->expected, env2bool(current->var, current->defaultValue));
+ }
+}
+
+void test_push_env(void)
+{
+ typedef struct {
+ bool expected;
+ const char *var, *initial, *to_find, *updated;
+ } push_env_check;
+
+ const char *three_part = "/usr/lib:/lib:/etc";
+ push_env_check checks[] = {
+ // We don't have an initial value.
+ { TRUE, "WILL_NOT_EXIST", NULL, "/usr/lib", "/usr/lib" },
+
+ // First component matches.
+ { FALSE, "WILL_EXIST", three_part, "/usr/lib", three_part },
+
+ // Middle component matches.
+ { FALSE, "WILL_EXIST", three_part, "/lib", three_part },
+
+ // End component matches.
+ { FALSE, "WILL_EXIST", three_part, "/etc", three_part },
+
+ // Add a non existing component.
+ { TRUE, "WILL_EXIST", three_part, "/Library", "/Library:/usr/lib:/lib:/etc" },
+ };
+
+ push_env_check *current;
+ int i;
+ for (i = 0; i < sizeof(checks) / sizeof(push_env_check); ++i) {
+ current = &checks[i];
+ if (current->initial)
+ setenv(current->var, current->initial, 1);
+
+ check_bool_equal(current->expected, push_env_to_start(current->var, current->to_find));
+ check_string_equal(current->updated, getenv(current->var));
+ }
+}
+
+void check_path_has_components(char *path, const char **components, int count)
+{
+ char *token, *tofree, *copy;
+
+ for (int i = 0; i < count; ++i) {
+ BOOL found = FALSE;
+ tofree = copy = strdup(path);
+
+ while ((token = strsep(&copy, ":"))) {
+ if (!strncmp(token, components[i], strlen(components[i])))
+ found = TRUE;
+ }
+
+ if (!found) {
+ printf("Expected '%s'\nIn '%s'", components[i], tofree);
+ fail();
+ }
+ free(tofree);
+ }
+}
+
+void test_update_environment(void)
+{
+ const char *path_components[] = {
+ "/Library/Frameworks/Mono.framework/Commands",
+ "./Resources",
+ "./MacOS",
+ };
+ const char *dyld_components[] = {
+ "/usr/local/lib",
+ "/Library/Developer/CommandLineTools/usr/lib",
+ "/usr/lib",
+ "/lib",
+ "/Library/Frameworks/Mono.framework/Libraries",
+ "./Resources/lib/monodevelop/bin",
+ "./Resources/lib",
+ };
+ const char *pkg_components[] = {
+ "./Resources/lib/pkgconfig",
+ "/Library/Frameworks/Mono.framework/External/pkgconfig",
+ };
+ const char *gac_components[] = {
+ "./Resources",
+ };
+ const char *numeric_components[] = {
+ "C",
+ };
+
+ // Check that we only get updates one time, that's how monostub works.
+ check_bool_equal(TRUE, update_environment("."));
+ check_bool_equal(FALSE, update_environment("."));
+
+
+ check_path_has_components(getenv("DYLD_FALLBACK_LIBRARY_PATH"), dyld_components, sizeof(dyld_components) / sizeof(char *));
+ check_path_has_components(getenv("PATH"), path_components, sizeof(path_components) / sizeof(char *));
+ check_path_has_components(getenv("PKG_CONFIG_PATH"), pkg_components, sizeof(pkg_components) / sizeof(char *));
+ check_path_has_components(getenv("MONO_GAC_PREFIX"), gac_components, sizeof(gac_components) / sizeof(char *));
+ check_path_has_components(getenv("LC_NUMERIC"), numeric_components, sizeof(numeric_components) / sizeof(char *));
+}
+
+void (*tests[])(void) = {
+ test_mono_lib_path,
+ test_check_mono_version,
+ test_str_append,
+ test_generate_fallback_path,
+ test_env2bool,
+ test_push_env,
+ test_update_environment,
+};
+
+int main(int argc, char **argv)
+{
+ for (int i = 0; i < sizeof(tests) / sizeof(void *); ++i)
+ tests[i]();
+ return 0;
+}
diff --git a/main/build/MacOSX/monostub-utils.h b/main/build/MacOSX/monostub-utils.h
new file mode 100644
index 0000000000..b3e4d271f8
--- /dev/null
+++ b/main/build/MacOSX/monostub-utils.h
@@ -0,0 +1,246 @@
+#include <stdlib.h>
+#include <string.h>
+
+#import <Cocoa/Cocoa.h>
+
+#define MONO_LIB_PATH(lib) "/Library/Frameworks/Mono.framework/Libraries/"lib
+
+static int
+check_mono_version (const char *version, const char *req_version)
+{
+ char *req_end, *end;
+ long req_val, val;
+
+ while (*req_version) {
+ req_val = strtol (req_version, &req_end, 10);
+ if (req_version == req_end || (*req_end && *req_end != '.')) {
+ fprintf (stderr, "Bad version requirement string '%s'\n", req_end);
+ return FALSE;
+ }
+
+ req_version = req_end;
+ if (*req_version)
+ req_version++;
+
+ val = strtol (version, &end, 10);
+ if (version == end || val < req_val)
+ return FALSE;
+
+ if (val > req_val)
+ return TRUE;
+
+ if (*req_version == '.' && *end != '.')
+ return FALSE;
+
+ version = end + 1;
+ }
+
+ return TRUE;
+}
+
+static char *
+str_append (const char *base, const char *append)
+{
+ size_t baselen = strlen (base);
+ size_t len = strlen (append);
+ char *buf;
+
+ if (!(buf = malloc (baselen + len + 1)))
+ return NULL;
+
+ memcpy (buf, base, baselen);
+ strcpy (buf + baselen, append);
+
+ return buf;
+}
+
+static char *
+generate_fallback_path (const char *contentsDir)
+{
+ char *lib_dir;
+ char *monodevelop_bin_dir;
+ char *value;
+ char *result;
+
+ /* Inject our Resources/lib dir */
+ lib_dir = str_append (contentsDir, "/Resources/lib:");
+
+ /* Inject our Resources/lib/monodevelop/bin dir so we can load libxammac.dylib */
+ monodevelop_bin_dir = str_append (contentsDir, "/Resources/lib/monodevelop/bin:");
+
+ if (lib_dir == NULL || monodevelop_bin_dir == NULL)
+ abort ();
+
+ value = str_append (lib_dir, monodevelop_bin_dir);
+ if (value == NULL)
+ abort ();
+
+ /* Mono's lib dir, and CommandLineTool's lib dir into the DYLD_FALLBACK_LIBRARY_PATH */
+ result = str_append (value, "/Library/Frameworks/Mono.framework/Libraries:/lib:/usr/lib:/Library/Developer/CommandLineTools/usr/lib:/usr/local/lib");
+
+ free (lib_dir);
+ free (monodevelop_bin_dir);
+ free (value);
+ return result;
+}
+
+static bool
+env2bool (const char *env, bool defaultValue)
+{
+ const char *value;
+ bool nz = NO;
+ int i;
+
+ if (!(value = getenv (env)))
+ return defaultValue;
+
+ if (!strcasecmp (value, "true"))
+ return YES;
+
+ if (!strcasecmp (value, "yes"))
+ return YES;
+
+ /* check to see if the value is numeric. All numeric values evaluate to true *except* zero */
+ for (i = 0; value[i]; i++) {
+ if (!isdigit ((int) ((unsigned char) value[i])))
+ return NO;
+
+ if (value[i] != '0')
+ nz = YES;
+ }
+
+ return nz;
+}
+
+static bool
+push_env (const char *variable, const char *value, BOOL push_to_end)
+{
+ const char *current;
+ size_t len;
+ char *buf;
+ BOOL updated = YES;
+
+ if ((current = getenv (variable)) && *current) {
+ char *token, *copy, *tofree;
+ size_t current_length;
+
+ tofree = copy = strdup (current);
+ current_length = strlen (current);
+ len = strlen (value);
+ while ((token = strsep(&copy, ":"))) {
+ if (!strncmp (token, value, len)) {
+ while ((strsep(&copy, ":")))
+ continue;
+
+ updated = NO;
+ goto done;
+ }
+ }
+
+ if (!(buf = malloc (len + current_length + 2)))
+ return NO;
+
+ if (push_to_end) {
+ memcpy (buf, current, current_length);
+ buf[current_length] = ':';
+ strcpy (buf + current_length + 1, value);
+ } else {
+ memcpy (buf, value, len);
+ buf[len] = ':';
+ strcpy (buf + len + 1, current);
+ }
+ setenv (variable, buf, 1);
+ free (buf);
+done:
+ free (tofree);
+ } else {
+ setenv (variable, value, 1);
+ }
+
+ return updated;
+}
+
+static bool
+push_env_to_start (const char *variable, const char *value)
+{
+ return push_env (variable, value, NO);
+}
+
+static bool
+push_env_to_end (const char *variable, const char *value)
+{
+ return push_env (variable, value, YES);
+}
+
+static bool
+replace_env (const char *variable, const char *value)
+{
+ const char *old = getenv (variable);
+
+ if (old && !strcmp (old, value))
+ return false;
+
+ setenv (variable, value, true);
+ return true;
+}
+
+static bool
+update_environment (const char *contentsDir)
+{
+ bool updated = NO;
+ char *value;
+
+ if ((value = generate_fallback_path (contentsDir))) {
+ char *token;
+
+ while ((token = strsep(&value, ":"))) {
+ if (push_env_to_end ("DYLD_FALLBACK_LIBRARY_PATH", token))
+ updated = YES;
+ }
+
+ free (value);
+ }
+
+ if (push_env_to_start ("PKG_CONFIG_PATH", "/Library/Frameworks/Mono.framework/External/pkgconfig"))
+ updated = YES;
+
+ /* Enable the use of stuff bundled into the app bundle and the Mono "External" directory */
+ if ((value = str_append (contentsDir, "/Resources/lib/pkgconfig"))) {
+ if (push_env_to_start ("PKG_CONFIG_PATH", value))
+ updated = YES;
+
+ free (value);
+ }
+
+ if ((value = str_append (contentsDir, "/Resources"))) {
+ if (push_env_to_start ("MONO_GAC_PREFIX", value))
+ updated = YES;
+
+ free (value);
+ }
+
+ if ((value = str_append (contentsDir, "/MacOS"))) {
+ if (push_env_to_start ("PATH", value))
+ updated = YES;
+
+ free (value);
+ }
+
+ // Note: older versions of Xamarin Studio incorrectly set the PATH to the Resources dir instead of the MacOS dir
+ // and older versions of mtouch relied on this broken behavior.
+ if ((value = str_append (contentsDir, "/Resources"))) {
+ if (push_env_to_start ("PATH", value))
+ updated = YES;
+
+ free (value);
+ }
+
+ if (push_env_to_start ("PATH", "/Library/Frameworks/Mono.framework/Commands"))
+ updated = YES;
+
+ if (replace_env ("LC_NUMERIC", "C"))
+ updated = YES;
+
+ return updated;
+}
+
diff --git a/main/build/MacOSX/monostub.m b/main/build/MacOSX/monostub.m
index b38169814d..0cc32bc1c0 100644
--- a/main/build/MacOSX/monostub.m
+++ b/main/build/MacOSX/monostub.m
@@ -1,7 +1,6 @@
//gcc -m32 monostub.m -o monostub -framework AppKit
#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -11,10 +10,9 @@
#include <dlfcn.h>
#include <errno.h>
#include <ctype.h>
+#include <time.h>
-#import <Cocoa/Cocoa.h>
-
-#define MONO_LIB_PATH(lib) "/Library/Frameworks/Mono.framework/Versions/Current/lib/"lib
+#include "monostub-utils.h"
typedef int (* mono_main) (int argc, char **argv);
typedef void (* mono_free) (void *ptr);
@@ -53,38 +51,6 @@ exit_with_message (char *reason, char *argv0)
exit (1);
}
-static int
-check_mono_version (const char *version, const char *req_version)
-{
- char *req_end, *end;
- long req_val, val;
-
- while (*req_version) {
- req_val = strtol (req_version, &req_end, 10);
- if (req_version == req_end || (*req_end && *req_end != '.')) {
- fprintf (stderr, "Bad version requirement string '%s'\n", req_end);
- return FALSE;
- }
-
- req_version = req_end;
- if (*req_version)
- req_version++;
-
- val = strtol (version, &end, 10);
- if (version == end || val < req_val)
- return FALSE;
-
- if (val > req_val)
- return TRUE;
-
- if (*req_version == '.' && *end != '.')
- return FALSE;
-
- version = end + 1;
- }
-
- return TRUE;
-}
typedef struct _ListNode {
struct _ListNode *next;
@@ -208,179 +174,21 @@ get_mono_env_options (int *count)
return argv;
}
-static bool
-push_env (const char *variable, const char *value)
-{
- const char *current;
- size_t len;
- char *buf;
-
- if ((current = getenv (variable)) && *current) {
- len = strlen (value);
-
- if (!strncmp (current, value, len) && (current[len] == ':' || current[len] == '\0'))
- return NO;
-
- if (!(buf = malloc (len + strlen (current) + 2)))
- return NO;
-
- memcpy (buf, value, len);
- buf[len] = ':';
- strcpy (buf + len + 1, current);
- setenv (variable, buf, 1);
- free (buf);
- } else {
- setenv (variable, value, 1);
- }
-
- //printf ("Updated the %s environment variable.\n", variable);
-
- return YES;
-}
-
-static char *
-str_append (const char *base, const char *append)
-{
- size_t baselen = strlen (base);
- size_t len = strlen (append);
- char *buf;
-
- if (!(buf = malloc (baselen + len + 1)))
- return NULL;
-
- memcpy (buf, base, baselen);
- strcpy (buf + baselen, append);
-
- return buf;
-}
-
-static char *
-generate_fallback_path (const char *contentsDir)
-{
- char *lib_dir;
- char *monodevelop_bin_dir;
- char *value;
- char *result;
-
- /* Inject our Resources/lib dir */
- lib_dir = str_append (contentsDir, "/Resources/lib:");
-
- /* Inject our Resources/lib/monodevelop/bin dir so we can load libxammac.dylib */
- monodevelop_bin_dir = str_append (contentsDir, "/Resources/lib/monodevelop/bin:");
-
- if (lib_dir == NULL || monodevelop_bin_dir == NULL)
- abort ();
-
- value = str_append (lib_dir, monodevelop_bin_dir);
- if (value == NULL)
- abort ();
-
- /* Mono's lib dir, and CommandLineTool's lib dir into the DYLD_FALLBACK_LIBRARY_PATH */
- result = str_append (value, "/Library/Frameworks/Mono.framework/Versions/Current/lib:/lib:/usr/lib:/Library/Developer/CommandLineTools/usr/lib:/usr/local/lib");
-
- free (lib_dir);
- free (monodevelop_bin_dir);
- free (value);
- return result;
-}
-
-static bool
-update_environment (const char *contentsDir)
-{
- bool updated = NO;
- char *value;
-
- if ((value = generate_fallback_path (contentsDir))) {
- if (push_env ("DYLD_FALLBACK_LIBRARY_PATH", value))
- updated = YES;
-
- free (value);
- }
-
- /* Enable the use of stuff bundled into the app bundle and the Mono "External" directory */
- if ((value = str_append (contentsDir, "/Resources/lib/pkgconfig:/Library/Frameworks/Mono.framework/External/pkgconfig"))) {
- if (push_env ("PKG_CONFIG_PATH", value))
- updated = YES;
-
- free (value);
- }
-
- if ((value = str_append (contentsDir, "/Resources"))) {
- if (push_env ("MONO_GAC_PREFIX", value))
- updated = YES;
-
- free (value);
- }
-
- if ((value = str_append (contentsDir, "/MacOS"))) {
- char *compat;
-
- // Note: older versions of Xamarin Studio incorrectly set the PATH to the Resources dir instead of the MacOS dir
- // and older versions of mtouch relied on this broken behavior.
- if ((compat = str_append (contentsDir, "/Resources"))) {
- size_t compatlen = strlen (compat);
- size_t valuelen = strlen (value);
- char *combined;
-
- if ((combined = malloc (compatlen + valuelen + 2))) {
- memcpy (combined, compat, compatlen);
- combined[compatlen] = ':';
- strcpy (combined + compatlen + 1, value);
-
- if (push_env ("PATH", combined))
- updated = YES;
-
- free (combined);
- } else {
- // if we can't combine them, set the old (incorrect) compat value
- if (push_env ("PATH", compat))
- updated = YES;
- }
-
- free (compat);
- } else {
- if (push_env ("PATH", value))
- updated = YES;
- }
-
- free (value);
- }
-
- return updated;
-}
-
-static bool
-env2bool (const char *env, bool defaultValue)
-{
- const char *value;
- bool nz = NO;
- int i;
-
- if (!(value = getenv (env)))
- return defaultValue;
-
- if (!strcasecmp (value, "true"))
- return YES;
-
- if (!strcasecmp (value, "yes"))
- return YES;
-
- /* check to see if the value is numeric. All numeric values evaluate to true *except* zero */
- for (i = 0; value[i]; i++) {
- if (!isdigit ((int) ((unsigned char) value[i])))
- return NO;
-
- if (value[i] != '0')
- nz = YES;
- }
-
- return nz;
-}
-
int main (int argc, char **argv)
{
+ //clock_t start = clock();
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *binDir = [[NSString alloc] initWithUTF8String: "Contents/Resources/lib/monodevelop/bin"];
+
+ // Check if we are running inside an actual app bundle. If we are not, then assume we're being run
+ // as part of `make run` and then binDir should be '.'
+ NSString *entryExecutable = [[NSString alloc] initWithUTF8String: argv[0]];
+ NSArray *components = [NSArray arrayWithObjects:[entryExecutable stringByDeletingLastPathComponent], @"..", @"..", binDir, nil];
+ NSString *binDirFullPath = [NSString pathWithComponents:components];
+ BOOL isDir = NO;
+ if (![[NSFileManager defaultManager] fileExistsAtPath: binDirFullPath isDirectory: &isDir] || !isDir)
+ binDir = [[NSString alloc] initWithUTF8String: "."];
+
NSString *appDir = [[NSBundle mainBundle] bundlePath];
// can be overridden with plist string MonoMinVersion
NSString *req_mono_version = @"3.10";
@@ -480,5 +288,7 @@ int main (int argc, char **argv)
free (extra_argv);
[pool drain];
+ //clock_t end = clock();
+ //printf("%f seconds to start\n", (float)(end - start) / CLOCKS_PER_SEC);
return _mono_main (argc + extra_argc + injected, new_argv);
}
diff --git a/main/build/Makefile.am b/main/build/Makefile.am
index 9217be1a33..b8863d3775 100644
--- a/main/build/Makefile.am
+++ b/main/build/Makefile.am
@@ -1,5 +1,5 @@
-if ENABLE_MACBUNDLE
+if ENABLE_MACPLATFORM
SUBDIRS = MacOSX
else
diff --git a/main/configure.in b/main/configure.in
index 34c3991891..9072e378d2 100644
--- a/main/configure.in
+++ b/main/configure.in
@@ -39,12 +39,17 @@ if ! $PKG_CONFIG --atleast-version=$MONO_REQUIRED_VERSION mono; then
AC_MSG_ERROR([You need mono $MONO_REQUIRED_VERSION or newer])
fi
-#ensure we have the same env as when configured
-AC_SUBST(PATH)
-AC_SUBST(PKG_CONFIG_PATH)
-AC_SUBST(LD_LIBRARY_PATH)
-AC_SUBST(DYLD_FALLBACK_LIBRARY_PATH)
-AC_SUBST(MONO_GAC_PREFIX)
+###
+# Disable the environment capturing as it breaks on El Capitan and we end up storing empty env vars
+# which means we break things like `DYLD_FALLBACK_LIBRARY_PATH` because that env has a default meaning
+# when it is *not set*, but this code causes it to be set to an empty value so we can't load libc.
+###
+##ensure we have the same env as when configured
+#AC_SUBST(PATH)
+#AC_SUBST(PKG_CONFIG_PATH)
+#AC_SUBST(LD_LIBRARY_PATH)
+#AC_SUBST(DYLD_FALLBACK_LIBRARY_PATH)
+#AC_SUBST(MONO_GAC_PREFIX)
default_gnomeplatform=no
default_windowsplatform=no
@@ -178,6 +183,13 @@ AC_ARG_ENABLE(git,
AM_CONDITIONAL(ENABLE_GIT, test x$enable_git = xyes)
+AC_ARG_ENABLE(release,
+ AC_HELP_STRING([--enable-release],
+ [build release mode [default=no]]),
+ enable_release=${enableval}, enable_release=no)
+
+AM_CONDITIONAL(RELEASE_BUILDS, [test x$enable_release = xyes])
+
platform_bindings=""
# Gnome platform addin
@@ -213,13 +225,6 @@ fi
AM_CONDITIONAL(ENABLE_MACPLATFORM, [test x$enable_macplatform = xyes])
-# Mac bundle
-AC_ARG_ENABLE(macbundle,
- AC_HELP_STRING([--enable-macbundle],
- [enable Mac bundle packaging [default=no]]),
- enable_macbundle=${enableval}, enable_macbundle=no)
-AM_CONDITIONAL(ENABLE_MACBUNDLE, [test x$enable_macbundle = xyes])
-
# Windows platform addin
AC_ARG_ENABLE(windowsplatform,
AC_HELP_STRING([--enable-windowsplatform],
@@ -381,4 +386,5 @@ echo " * Subversion (Unix): $enable_subversion"
echo " * Git: $enable_git"
echo " * Platform bindings: $platform_bindings"
echo " * Unit tests: $enable_tests"
+echo " * Release builds: $enable_release"
echo ""
diff --git a/main/contrib/ICSharpCode.Decompiler/Ast/Annotations.cs b/main/contrib/ICSharpCode.Decompiler/Ast/Annotations.cs
index 7b22dd0136..1c957292ec 100644
--- a/main/contrib/ICSharpCode.Decompiler/Ast/Annotations.cs
+++ b/main/contrib/ICSharpCode.Decompiler/Ast/Annotations.cs
@@ -10,10 +10,12 @@ namespace ICSharpCode.Decompiler.Ast
public class TypeInformation
{
public readonly TypeReference InferredType;
+ public readonly TypeReference ExpectedType;
- public TypeInformation(TypeReference inferredType)
+ public TypeInformation(TypeReference inferredType, TypeReference expectedType)
{
this.InferredType = inferredType;
+ this.ExpectedType = expectedType;
}
}
diff --git a/main/contrib/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/main/contrib/ICSharpCode.Decompiler/Ast/AstBuilder.cs
index b488cf4840..82d6a71554 100644
--- a/main/contrib/ICSharpCode.Decompiler/Ast/AstBuilder.cs
+++ b/main/contrib/ICSharpCode.Decompiler/Ast/AstBuilder.cs
@@ -176,14 +176,19 @@ namespace ICSharpCode.Decompiler.Ast
RunTransformations();
syntaxTree.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true });
- var outputFormatter = new TextTokenWriter(output) { FoldBraces = context.Settings.FoldBraces };
+ var outputFormatter = new TextTokenWriter(output, context) { FoldBraces = context.Settings.FoldBraces };
var formattingPolicy = context.Settings.CSharpFormattingOptions;
syntaxTree.AcceptVisitor(new CSharpOutputVisitor(outputFormatter, formattingPolicy));
}
public void AddAssembly(AssemblyDefinition assemblyDefinition, bool onlyAssemblyLevel = false)
{
- if (assemblyDefinition.Name.Version != null) {
+ AddAssembly(assemblyDefinition.MainModule, onlyAssemblyLevel);
+ }
+
+ public void AddAssembly(ModuleDefinition moduleDefinition, bool onlyAssemblyLevel = false)
+ {
+ if (moduleDefinition.Assembly != null && moduleDefinition.Assembly.Name.Version != null) {
syntaxTree.AddChild(
new AttributeSection {
AttributeTarget = "assembly",
@@ -192,22 +197,24 @@ namespace ICSharpCode.Decompiler.Ast
Type = new SimpleType("AssemblyVersion")
.WithAnnotation(new TypeReference(
"System.Reflection", "AssemblyVersionAttribute",
- assemblyDefinition.MainModule, assemblyDefinition.MainModule.TypeSystem.Corlib)),
+ moduleDefinition, moduleDefinition.TypeSystem.Corlib)),
Arguments = {
- new PrimitiveExpression(assemblyDefinition.Name.Version.ToString())
+ new PrimitiveExpression(moduleDefinition.Assembly.Name.Version.ToString())
}
}
}
}, EntityDeclaration.AttributeRole);
}
- ConvertCustomAttributes(syntaxTree, assemblyDefinition, "assembly");
- ConvertSecurityAttributes(syntaxTree, assemblyDefinition, "assembly");
- ConvertCustomAttributes(syntaxTree, assemblyDefinition.MainModule, "module");
- AddTypeForwarderAttributes(syntaxTree, assemblyDefinition.MainModule, "assembly");
+ if (moduleDefinition.Assembly != null) {
+ ConvertCustomAttributes(syntaxTree, moduleDefinition.Assembly, "assembly");
+ ConvertSecurityAttributes(syntaxTree, moduleDefinition.Assembly, "assembly");
+ }
+ ConvertCustomAttributes(syntaxTree, moduleDefinition, "module");
+ AddTypeForwarderAttributes(syntaxTree, moduleDefinition, "assembly");
if (!onlyAssemblyLevel) {
- foreach (TypeDefinition typeDef in assemblyDefinition.MainModule.Types) {
+ foreach (TypeDefinition typeDef in moduleDefinition.Types) {
// Skip the <Module> class
if (typeDef.Name == "<Module>") continue;
// Skip any hidden types
@@ -330,19 +337,22 @@ namespace ICSharpCode.Decompiler.Ast
if (typeDef.IsEnum) {
long expectedEnumMemberValue = 0;
bool forcePrintingInitializers = IsFlagsEnum(typeDef);
+ TypeCode baseType = TypeCode.Int32;
foreach (FieldDefinition field in typeDef.Fields) {
if (!field.IsStatic) {
// the value__ field
if (field.FieldType != typeDef.Module.TypeSystem.Int32) {
astType.AddChild(ConvertType(field.FieldType), Roles.BaseType);
+ baseType = TypeAnalysis.GetTypeCode(field.FieldType);
}
} else {
EnumMemberDeclaration enumMember = new EnumMemberDeclaration();
+ ConvertCustomAttributes(enumMember, field);
enumMember.AddAnnotation(field);
enumMember.Name = CleanName(field.Name);
long memberValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.Constant, false);
if (forcePrintingInitializers || memberValue != expectedEnumMemberValue) {
- enumMember.AddChild(new PrimitiveExpression(field.Constant), EnumMemberDeclaration.InitializerRole);
+ enumMember.AddChild(new PrimitiveExpression(CSharpPrimitiveCast.Cast(baseType, field.Constant, false)), EnumMemberDeclaration.InitializerRole);
}
expectedEnumMemberValue = memberValue + 1;
astType.AddChild(enumMember, Roles.TypeMemberRole);
diff --git a/main/contrib/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs b/main/contrib/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
index fae41f6860..e98e8dbc71 100644
--- a/main/contrib/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
+++ b/main/contrib/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
@@ -52,8 +52,8 @@ namespace ICSharpCode.Decompiler.Ast
/// These are used to update the parameter names when the decompiler generates names for the parameters.</param>
/// <returns>Block for the method body</returns>
public static BlockStatement CreateMethodBody(MethodDefinition methodDef,
- DecompilerContext context,
- IEnumerable<ParameterDeclaration> parameters = null)
+ DecompilerContext context,
+ IEnumerable<ParameterDeclaration> parameters = null)
{
MethodDefinition oldCurrentMethod = context.CurrentMethod;
Debug.Assert(oldCurrentMethod == null || oldCurrentMethod == methodDef);
@@ -103,8 +103,8 @@ namespace ICSharpCode.Decompiler.Ast
if (parameters != null) {
foreach (var pair in (from p in parameters
- join v in astBuilder.Parameters on p.Annotation<ParameterDefinition>() equals v.OriginalParameter
- select new { p, v.Name }))
+ join v in astBuilder.Parameters on p.Annotation<ParameterDefinition>() equals v.OriginalParameter
+ select new { p, v.Name }))
{
pair.p.Name = pair.Name;
}
@@ -204,7 +204,7 @@ namespace ICSharpCode.Decompiler.Ast
tryCatchStmt.TryBlock = TransformBlock(tryCatchNode.TryBlock);
foreach (var catchClause in tryCatchNode.CatchBlocks) {
if (catchClause.ExceptionVariable == null
- && (catchClause.ExceptionType == null || catchClause.ExceptionType.MetadataType == MetadataType.Object))
+ && (catchClause.ExceptionType == null || catchClause.ExceptionType.MetadataType == MetadataType.Object))
{
tryCatchStmt.CatchClauses.Add(new Ast.CatchClause { Body = TransformBlock(catchClause) });
} else {
@@ -262,7 +262,7 @@ namespace ICSharpCode.Decompiler.Ast
result = node;
if (result != null)
- result = result.WithAnnotation(new TypeInformation(expr.InferredType));
+ result = result.WithAnnotation(new TypeInformation(expr.InferredType, expr.ExpectedType));
if (result != null)
return result.WithAnnotation(ilRanges);
@@ -291,16 +291,10 @@ namespace ICSharpCode.Decompiler.Ast
{
BinaryOperatorExpression boe;
if (byteCode.InferredType is PointerType) {
- if (byteCode.Arguments[0].ExpectedType is PointerType) {
- arg2 = DivideBySize(arg2, ((PointerType)byteCode.InferredType).ElementType);
- boe = new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2);
- boe.AddAnnotation(IntroduceUnsafeModifier.PointerArithmeticAnnotation);
- } else if (byteCode.Arguments[1].ExpectedType is PointerType) {
- arg1 = DivideBySize(arg1, ((PointerType)byteCode.InferredType).ElementType);
- boe = new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2);
+ boe = new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2);
+ if (byteCode.Arguments[0].ExpectedType is PointerType ||
+ byteCode.Arguments[1].ExpectedType is PointerType) {
boe.AddAnnotation(IntroduceUnsafeModifier.PointerArithmeticAnnotation);
- } else {
- boe = new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2);
}
} else {
boe = new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2);
@@ -314,12 +308,9 @@ namespace ICSharpCode.Decompiler.Ast
{
BinaryOperatorExpression boe;
if (byteCode.InferredType is PointerType) {
+ boe = new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2);
if (byteCode.Arguments[0].ExpectedType is PointerType) {
- arg2 = DivideBySize(arg2, ((PointerType)byteCode.InferredType).ElementType);
- boe = new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2);
boe.WithAnnotation(IntroduceUnsafeModifier.PointerArithmeticAnnotation);
- } else {
- boe = new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2);
}
} else {
boe = new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2);
@@ -460,12 +451,30 @@ namespace ICSharpCode.Decompiler.Ast
// can also mean Inequality, when used with object references
TypeReference arg1Type = byteCode.Arguments[0].InferredType;
if (arg1Type != null && !arg1Type.IsValueType) goto case ILCode.Cne;
+
+ // when comparing signed integral values using Cgt_Un with 0
+ // the Ast should actually contain InEquality since "(uint)a > 0u" is identical to "a != 0"
+ if (arg1Type.IsSignedIntegralType())
+ {
+ var p = arg2 as Ast.PrimitiveExpression;
+ if (p != null && p.Value.IsZero()) goto case ILCode.Cne;
+ }
+
goto case ILCode.Cgt;
}
case ILCode.Cle_Un: {
// can also mean Equality, when used with object references
TypeReference arg1Type = byteCode.Arguments[0].InferredType;
if (arg1Type != null && !arg1Type.IsValueType) goto case ILCode.Ceq;
+
+ // when comparing signed integral values using Cle_Un with 0
+ // the Ast should actually contain Equality since "(uint)a <= 0u" is identical to "a == 0"
+ if (arg1Type.IsSignedIntegralType())
+ {
+ var p = arg2 as Ast.PrimitiveExpression;
+ if (p != null && p.Value.IsZero()) goto case ILCode.Ceq;
+ }
+
goto case ILCode.Cle;
}
case ILCode.Cle: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThanOrEqual, arg2);
@@ -706,7 +715,7 @@ namespace ICSharpCode.Decompiler.Ast
}
return new StackAllocExpression {
Type = AstBuilder.ConvertType(type),
- CountExpression = DivideBySize(arg1, type)
+ CountExpression = arg1
};
}
case ILCode.Mkrefany:
@@ -849,7 +858,7 @@ namespace ICSharpCode.Decompiler.Ast
args[args.Count - 1].AddAnnotation(new ParameterDeclarationAnnotation(byteCode));
return args[args.Count - 1];
case ILCode.Await:
- return new UnaryOperatorExpression(UnaryOperatorType.Await, arg1);
+ return new UnaryOperatorExpression(UnaryOperatorType.Await, UnpackDirectionExpression(arg1));
case ILCode.NullableOf:
case ILCode.ValueOf:
return arg1;
@@ -902,45 +911,6 @@ namespace ICSharpCode.Decompiler.Ast
}
}
- /// <summary>
- /// Divides expr by the size of 'type'.
- /// </summary>
- Expression DivideBySize(Expression expr, TypeReference type)
- {
- CastExpression cast = expr as CastExpression;
- if (cast != null && cast.Type is PrimitiveType && ((PrimitiveType)cast.Type).Keyword == "int")
- expr = cast.Expression.Detach();
-
- Expression sizeOfExpression;
- switch (TypeAnalysis.GetInformationAmount(type)) {
- case 1:
- case 8:
- sizeOfExpression = new PrimitiveExpression(1);
- break;
- case 16:
- sizeOfExpression = new PrimitiveExpression(2);
- break;
- case 32:
- sizeOfExpression = new PrimitiveExpression(4);
- break;
- case 64:
- sizeOfExpression = new PrimitiveExpression(8);
- break;
- default:
- sizeOfExpression = new SizeOfExpression { Type = AstBuilder.ConvertType(type) };
- break;
- }
-
- BinaryOperatorExpression boe = expr as BinaryOperatorExpression;
- if (boe != null && boe.Operator == BinaryOperatorType.Multiply && sizeOfExpression.IsMatch(boe.Right))
- return boe.Left.Detach();
-
- if (sizeOfExpression.IsMatch(expr))
- return new PrimitiveExpression(1);
-
- return new BinaryOperatorExpression(expr, BinaryOperatorType.Divide, sizeOfExpression);
- }
-
Expression MakeDefaultValue(TypeReference type)
{
TypeDefinition typeDef = type.Resolve();
@@ -975,10 +945,7 @@ namespace ICSharpCode.Decompiler.Ast
// Unpack any DirectionExpression that is used as target for the call
// (calling methods on value types implicitly passes the first argument by reference)
- if (target is DirectionExpression) {
- target = ((DirectionExpression)target).Expression;
- target.Remove(); // detach from DirectionExpression
- }
+ target = UnpackDirectionExpression(target);
if (cecilMethodDef != null) {
// convert null.ToLower() to ((string)null).ToLower()
@@ -1078,6 +1045,15 @@ namespace ICSharpCode.Decompiler.Ast
return target.Invoke(cecilMethod.Name, ConvertTypeArguments(cecilMethod), methodArgs).WithAnnotation(cecilMethod);
}
+ static Expression UnpackDirectionExpression(Expression target)
+ {
+ if (target is DirectionExpression) {
+ return ((DirectionExpression)target).Expression.Detach();
+ } else {
+ return target;
+ }
+ }
+
static void AdjustArgumentsForMethodCall(MethodReference cecilMethod, List<Expression> methodArgs)
{
// Convert 'ref' into 'out' where necessary
diff --git a/main/contrib/ICSharpCode.Decompiler/Ast/TextTokenWriter.cs b/main/contrib/ICSharpCode.Decompiler/Ast/TextTokenWriter.cs
index b77284cb24..4f52b89d0d 100644
--- a/main/contrib/ICSharpCode.Decompiler/Ast/TextTokenWriter.cs
+++ b/main/contrib/ICSharpCode.Decompiler/Ast/TextTokenWriter.cs
@@ -30,6 +30,7 @@ namespace ICSharpCode.Decompiler.Ast
public class TextTokenWriter : TokenWriter
{
readonly ITextOutput output;
+ readonly DecompilerContext context;
readonly Stack<AstNode> nodeStack = new Stack<AstNode>();
int braceLevelWithinType = -1;
bool inDocumentationComment = false;
@@ -40,15 +41,22 @@ namespace ICSharpCode.Decompiler.Ast
public bool FoldBraces = false;
- public TextTokenWriter(ITextOutput output)
+ public TextTokenWriter(ITextOutput output, DecompilerContext context)
{
if (output == null)
throw new ArgumentNullException("output");
+ if (context == null)
+ throw new ArgumentNullException("context");
this.output = output;
+ this.context = context;
}
public override void WriteIdentifier(Identifier identifier)
{
+ if (identifier.IsVerbatim || CSharpOutputVisitor.IsKeyword(identifier.Name, identifier)) {
+ output.Write('@');
+ }
+
var definition = GetCurrentDefinition();
if (definition != null) {
output.WriteDefinition(identifier.Name, definition, false);
@@ -89,6 +97,24 @@ namespace ICSharpCode.Decompiler.Ast
if (memberRef == null && node.Role == Roles.TargetExpression && (node.Parent is InvocationExpression || node.Parent is ObjectCreateExpression)) {
memberRef = node.Parent.Annotation<MemberReference>();
}
+ if (node is IdentifierExpression && node.Role == Roles.TargetExpression && node.Parent is InvocationExpression && memberRef != null) {
+ var declaringType = memberRef.DeclaringType.Resolve();
+ if (declaringType != null && declaringType.IsDelegate())
+ return null;
+ }
+ return FilterMemberReference(memberRef);
+ }
+
+ MemberReference FilterMemberReference(MemberReference memberRef)
+ {
+ if (memberRef == null)
+ return null;
+
+ if (context.Settings.AutomaticEvents && memberRef is FieldDefinition) {
+ var field = (FieldDefinition)memberRef;
+ return field.DeclaringType.Events.FirstOrDefault(ev => ev.Name == field.Name) ?? memberRef;
+ }
+
return memberRef;
}
diff --git a/main/contrib/ICSharpCode.Decompiler/Ast/Transforms/DeclareVariables.cs b/main/contrib/ICSharpCode.Decompiler/Ast/Transforms/DeclareVariables.cs
index 3b38762651..ed1155ba15 100644
--- a/main/contrib/ICSharpCode.Decompiler/Ast/Transforms/DeclareVariables.cs
+++ b/main/contrib/ICSharpCode.Decompiler/Ast/Transforms/DeclareVariables.cs
@@ -144,6 +144,15 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
if (TryConvertAssignmentExpressionIntoVariableDeclaration((Expression)usingStmt.ResourceAcquisition, type, variableName))
continue;
}
+ IfElseStatement ies = stmt as IfElseStatement;
+ if (ies != null) {
+ foreach (var child in IfElseChainChildren(ies)) {
+ BlockStatement subBlock = child as BlockStatement;
+ if (subBlock != null)
+ DeclareVariableInBlock(daa, subBlock, type, variableName, v, allowPassIntoLoops);
+ }
+ continue;
+ }
foreach (AstNode child in stmt.Children) {
BlockStatement subBlock = child as BlockStatement;
if (subBlock != null) {
@@ -268,6 +277,15 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
}
}
}
+
+ IfElseStatement ies = stmt as IfElseStatement;
+ if (ies != null) {
+ foreach (var child in IfElseChainChildren(ies)) {
+ if (!(child is BlockStatement) && UsesVariable(child, variableName))
+ return false;
+ }
+ return true;
+ }
// We can move the variable into a sub-block only if the variable is used in only that sub-block (and not in expressions such as the loop condition)
for (AstNode child = stmt.FirstChild; child != null; child = child.NextSibling) {
@@ -285,6 +303,19 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
}
return true;
}
+
+ static IEnumerable<AstNode> IfElseChainChildren(IfElseStatement ies)
+ {
+ IfElseStatement prev;
+ do {
+ yield return ies.Condition;
+ yield return ies.TrueStatement;
+ prev = ies;
+ ies = ies.FalseStatement as IfElseStatement;
+ } while (ies != null);
+ if (!prev.FalseStatement.IsNull)
+ yield return prev.FalseStatement;
+ }
static bool HasNestedBlocks(AstNode node)
{
diff --git a/main/contrib/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs b/main/contrib/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs
index 9c5aa97f6e..0741466f95 100644
--- a/main/contrib/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs
+++ b/main/contrib/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs
@@ -180,8 +180,8 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
foreach (AstNode node in body.Descendants) {
if (node is ThisReferenceExpression)
node.ReplaceWith(target.Clone());
-
}
+ Expression replacement;
if (isLambda) {
LambdaExpression lambda = new LambdaExpression();
lambda.CopyAnnotationsFrom(ame);
@@ -189,11 +189,19 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
Expression returnExpr = ((ReturnStatement)body.Statements.Single()).Expression;
returnExpr.Remove();
lambda.Body = returnExpr;
- objectCreateExpression.ReplaceWith(lambda);
+ replacement = lambda;
} else {
ame.Body = body;
- objectCreateExpression.ReplaceWith(ame);
+ replacement = ame;
+ }
+ var expectedType = objectCreateExpression.Annotation<TypeInformation>().ExpectedType.Resolve();
+ if (expectedType != null && !expectedType.IsDelegate()) {
+ var simplifiedDelegateCreation = (ObjectCreateExpression)objectCreateExpression.Clone();
+ simplifiedDelegateCreation.Arguments.Clear();
+ simplifiedDelegateCreation.Arguments.Add(replacement);
+ replacement = simplifiedDelegateCreation;
}
+ objectCreateExpression.ReplaceWith(replacement);
return true;
}
diff --git a/main/contrib/ICSharpCode.Decompiler/Ast/Transforms/ExpressionTreeConverter.cs b/main/contrib/ICSharpCode.Decompiler/Ast/Transforms/ExpressionTreeConverter.cs
index 32f7cb0dbe..ffd6f5ac76 100644
--- a/main/contrib/ICSharpCode.Decompiler/Ast/Transforms/ExpressionTreeConverter.cs
+++ b/main/contrib/ICSharpCode.Decompiler/Ast/Transforms/ExpressionTreeConverter.cs
@@ -804,7 +804,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
return new IndexerExpression(targetConverted, indexConverted);
}
IList<Expression> indexesConverted = ConvertExpressionsArray(index);
- if (indexConverted != null) {
+ if (indexesConverted != null) {
return new IndexerExpression(targetConverted, indexesConverted);
}
return null;
diff --git a/main/contrib/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUnsafeModifier.cs b/main/contrib/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUnsafeModifier.cs
index 43548e38d4..a9e72564f3 100644
--- a/main/contrib/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUnsafeModifier.cs
+++ b/main/contrib/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUnsafeModifier.cs
@@ -35,7 +35,11 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
protected override bool VisitChildren(AstNode node, object data)
{
bool result = false;
- for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
+ AstNode next;
+ for (AstNode child = node.FirstChild; child != null; child = next) {
+ // Store next to allow the loop to continue
+ // if the visitor removes/replaces child.
+ next = child.NextSibling;
result |= child.AcceptVisitor(this, data);
}
if (result && node is EntityDeclaration && !(node is Accessor)) {
diff --git a/main/contrib/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUsingDeclarations.cs b/main/contrib/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUsingDeclarations.cs
index 5c3784fa4c..4182eec8f2 100644
--- a/main/contrib/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUsingDeclarations.cs
+++ b/main/contrib/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUsingDeclarations.cs
@@ -38,24 +38,23 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
public void Run(AstNode compilationUnit)
{
- if (!context.Settings.UsingDeclarations)
- return;
-
// First determine all the namespaces that need to be imported:
compilationUnit.AcceptVisitor(new FindRequiredImports(this), null);
importedNamespaces.Add("System"); // always import System, even when not necessary
- // Now add using declarations for those namespaces:
- foreach (string ns in importedNamespaces.OrderByDescending(n => n)) {
- // we go backwards (OrderByDescending) through the list of namespaces because we insert them backwards
- // (always inserting at the start of the list)
- string[] parts = ns.Split('.');
- AstType nsType = new SimpleType(parts[0]);
- for (int i = 1; i < parts.Length; i++) {
- nsType = new MemberType { Target = nsType, MemberName = parts[i] };
+ if (context.Settings.UsingDeclarations) {
+ // Now add using declarations for those namespaces:
+ foreach (string ns in importedNamespaces.OrderByDescending(n => n)) {
+ // we go backwards (OrderByDescending) through the list of namespaces because we insert them backwards
+ // (always inserting at the start of the list)
+ string[] parts = ns.Split('.');
+ AstType nsType = new SimpleType(parts[0]);
+ for (int i = 1; i < parts.Length; i++) {
+ nsType = new MemberType { Target = nsType, MemberName = parts[i] };
+ }
+ compilationUnit.InsertChildAfter(null, new UsingDeclaration { Import = nsType }, SyntaxTree.MemberRole);
}
- compilationUnit.InsertChildAfter(null, new UsingDeclaration { Import = nsType }, SyntaxTree.MemberRole);
}
if (!context.Settings.FullyQualifyAmbiguousTypeNames)
diff --git a/main/contrib/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs b/main/contrib/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs
index 22d1afe627..bff2cc6b95 100644
--- a/main/contrib/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs
+++ b/main/contrib/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs
@@ -99,6 +99,9 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
if (result != null)
return result;
}
+ AstNode simplifiedIfElse = SimplifyCascadingIfElseStatements(ifElseStatement);
+ if (simplifiedIfElse != null)
+ return simplifiedIfElse;
return base.VisitIfElseStatement(ifElseStatement, data);
}
@@ -614,6 +617,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
static readonly AstNode lockTryCatchPattern = new TryCatchStatement {
TryBlock = new BlockStatement {
+ new OptionalNode(new VariableDeclarationStatement()).ToStatement(),
new TypePattern(typeof(System.Threading.Monitor)).ToType().Invoke(
"Enter", new AnyNode("enter"),
new DirectionExpression {
@@ -626,21 +630,57 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
new IfElseStatement {
Condition = new Backreference("flag"),
TrueStatement = new BlockStatement {
- new TypePattern(typeof(System.Threading.Monitor)).ToType().Invoke("Exit", new NamedNode("exit", new IdentifierExpression(Pattern.AnyString)))
+ new TypePattern(typeof(System.Threading.Monitor)).ToType().Invoke("Exit", new AnyNode("exit"))
}
}
}};
+
+ static readonly AstNode oldMonitorCallPattern = new ExpressionStatement(
+ new TypePattern(typeof(System.Threading.Monitor)).ToType().Invoke("Enter", new AnyNode("enter"))
+ );
+
+ static readonly AstNode oldLockTryCatchPattern = new TryCatchStatement
+ {
+ TryBlock = new BlockStatement {
+ new Repeat(new AnyNode()).ToStatement()
+ },
+ FinallyBlock = new BlockStatement {
+ new TypePattern(typeof(System.Threading.Monitor)).ToType().Invoke("Exit", new AnyNode("exit"))
+ }
+ };
+
+ bool AnalyzeLockV2(ExpressionStatement node, out Expression enter, out Expression exit)
+ {
+ enter = null;
+ exit = null;
+ Match m1 = oldMonitorCallPattern.Match(node);
+ if (!m1.Success) return false;
+ Match m2 = oldLockTryCatchPattern.Match(node.NextSibling);
+ if (!m2.Success) return false;
+ enter = m1.Get<Expression>("enter").Single();
+ exit = m2.Get<Expression>("exit").Single();
+ return true;
+ }
+
+ bool AnalyzeLockV4(ExpressionStatement node, out Expression enter, out Expression exit)
+ {
+ enter = null;
+ exit = null;
+ Match m1 = lockFlagInitPattern.Match(node);
+ if (!m1.Success) return false;
+ Match m2 = lockTryCatchPattern.Match(node.NextSibling);
+ if (!m2.Success) return false;
+ enter = m2.Get<Expression>("enter").Single();
+ exit = m2.Get<Expression>("exit").Single();
+ return m1.Get<IdentifierExpression>("variable").Single().Identifier == m2.Get<IdentifierExpression>("flag").Single().Identifier;
+ }
public LockStatement TransformLock(ExpressionStatement node)
{
- Match m1 = lockFlagInitPattern.Match(node);
- if (!m1.Success) return null;
- AstNode tryCatch = node.NextSibling;
- Match m2 = lockTryCatchPattern.Match(tryCatch);
- if (!m2.Success) return null;
- if (m1.Get<IdentifierExpression>("variable").Single().Identifier == m2.Get<IdentifierExpression>("flag").Single().Identifier) {
- Expression enter = m2.Get<Expression>("enter").Single();
- IdentifierExpression exit = m2.Get<IdentifierExpression>("exit").Single();
+ Expression enter, exit;
+ bool isV2 = AnalyzeLockV2(node, out enter, out exit);
+ if (isV2 || AnalyzeLockV4(node, out enter, out exit)) {
+ AstNode tryCatch = node.NextSibling;
if (!exit.IsMatch(enter)) {
// If exit and enter are not the same, then enter must be "exit = ..."
AssignmentExpression assign = enter as AssignmentExpression;
@@ -656,7 +696,8 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
LockStatement l = new LockStatement();
l.Expression = enter.Detach();
l.EmbeddedStatement = ((TryCatchStatement)tryCatch).TryBlock.Detach();
- ((BlockStatement)l.EmbeddedStatement).Statements.First().Remove(); // Remove 'Enter()' call
+ if (!isV2) // Remove 'Enter()' call
+ ((BlockStatement)l.EmbeddedStatement).Statements.First().Remove();
tryCatch.ReplaceWith(l);
node.Remove(); // remove flag variable
return l;
@@ -1047,5 +1088,36 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
return null;
}
#endregion
+
+ #region Simplify cascading if-else-if statements
+ static readonly IfElseStatement cascadingIfElsePattern = new IfElseStatement
+ {
+ Condition = new AnyNode(),
+ TrueStatement = new AnyNode(),
+ FalseStatement = new BlockStatement {
+ Statements = {
+ new NamedNode(
+ "nestedIfStatement",
+ new IfElseStatement {
+ Condition = new AnyNode(),
+ TrueStatement = new AnyNode(),
+ FalseStatement = new OptionalNode(new AnyNode())
+ }
+ )
+ }
+ }
+ };
+
+ AstNode SimplifyCascadingIfElseStatements(IfElseStatement node)
+ {
+ Match m = cascadingIfElsePattern.Match(node);
+ if (m.Success) {
+ IfElseStatement elseIf = m.Get<IfElseStatement>("nestedIfStatement").Single();
+ node.FalseStatement = elseIf.Detach();
+ }
+
+ return null;
+ }
+ #endregion
}
}
diff --git a/main/contrib/ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs b/main/contrib/ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs
index 8de45cca56..f0f5ece532 100644
--- a/main/contrib/ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs
+++ b/main/contrib/ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs
@@ -32,9 +32,11 @@ namespace ICSharpCode.Decompiler.Ast
if (resolveTypeArguments)
return BaseTypes(derivedType).Any(t => t.Item == baseType);
else {
- var comparableBaseType = baseType.ResolveOrThrow();
+ var comparableBaseType = baseType.Resolve();
+ if (comparableBaseType == null)
+ return false;
while (derivedType.BaseType != null) {
- var resolvedBaseType = derivedType.BaseType.ResolveOrThrow();
+ var resolvedBaseType = derivedType.BaseType.Resolve();
if (resolvedBaseType == null)
return false;
if (comparableBaseType == resolvedBaseType)
@@ -185,24 +187,32 @@ namespace ICSharpCode.Decompiler.Ast
if (derivedType == null)
throw new ArgumentNullException("derivedType");
- var visibility = IsVisibleFromDerived(baseMember);
- if (visibility.HasValue)
- return visibility.Value;
+ MethodAttributes attrs = GetAccessAttributes(baseMember) & MethodAttributes.MemberAccessMask;
+ if (attrs == MethodAttributes.Private)
+ return false;
if (baseMember.DeclaringType.Module == derivedType.Module)
return true;
- // TODO: Check also InternalsVisibleToAttribute.
- return false;
- }
- private static bool? IsVisibleFromDerived(IMemberDefinition member)
- {
- MethodAttributes attrs = GetAccessAttributes(member) & MethodAttributes.MemberAccessMask;
- if (attrs == MethodAttributes.Private)
+ if (attrs == MethodAttributes.Assembly || attrs == MethodAttributes.FamANDAssem) {
+ var derivedTypeAsm = derivedType.Module.Assembly;
+ var asm = baseMember.DeclaringType.Module.Assembly;
+
+ if (asm.HasCustomAttributes) {
+ var attributes = asm.CustomAttributes
+ .Where(attr => attr.AttributeType.FullName == "System.Runtime.CompilerServices.InternalsVisibleToAttribute");
+ foreach (var attribute in attributes) {
+ string assemblyName = attribute.ConstructorArguments[0].Value as string;
+ assemblyName = assemblyName.Split(',')[0]; // strip off any public key info
+ if (assemblyName == derivedTypeAsm.Name.Name)
+ return true;
+ }
+ }
+
return false;
- if (attrs == MethodAttributes.Assembly || attrs == MethodAttributes.FamANDAssem)
- return null;
- return true;
+ }
+
+ return true;
}
private static MethodAttributes GetAccessAttributes(IMemberDefinition member)
diff --git a/main/contrib/ICSharpCode.Decompiler/CecilExtensions.cs b/main/contrib/ICSharpCode.Decompiler/CecilExtensions.cs
index cc047e09cd..0c7cb1e409 100644
--- a/main/contrib/ICSharpCode.Decompiler/CecilExtensions.cs
+++ b/main/contrib/ICSharpCode.Decompiler/CecilExtensions.cs
@@ -126,6 +126,41 @@ namespace ICSharpCode.Decompiler
return false;
return type.IsValueType || type.IsVoid();
}
+
+ /// <summary>
+ /// checks if the given TypeReference is one of the following types:
+ /// [sbyte, short, int, long, IntPtr]
+ /// </summary>
+ public static bool IsSignedIntegralType(this TypeReference type)
+ {
+ return type.MetadataType == MetadataType.SByte ||
+ type.MetadataType == MetadataType.Int16 ||
+ type.MetadataType == MetadataType.Int32 ||
+ type.MetadataType == MetadataType.Int64 ||
+ type.MetadataType == MetadataType.IntPtr;
+ }
+
+ /// <summary>
+ /// checks if the given value is a numeric zero-value.
+ /// NOTE that this only works for types: [sbyte, short, int, long, IntPtr, byte, ushort, uint, ulong, float, double and decimal]
+ /// </summary>
+ public static bool IsZero(this object value)
+ {
+ return value.Equals((sbyte)0) ||
+ value.Equals((short)0) ||
+ value.Equals(0) ||
+ value.Equals(0L) ||
+ value.Equals(IntPtr.Zero) ||
+ value.Equals((byte)0) ||
+ value.Equals((ushort)0) ||
+ value.Equals(0u) ||
+ value.Equals(0UL) ||
+ value.Equals(0.0f) ||
+ value.Equals(0.0) ||
+ value.Equals((decimal)0);
+
+ }
+
#endregion
/// <summary>
@@ -190,6 +225,7 @@ namespace ICSharpCode.Decompiler
return null;
}
+ [Obsolete("throwing exceptions is considered a bug")]
public static TypeDefinition ResolveOrThrow(this TypeReference typeReference)
{
var resolved = typeReference.Resolve();
@@ -323,5 +359,16 @@ namespace ICSharpCode.Decompiler
}
return false;
}
+
+ public static bool IsDelegate(this TypeDefinition type)
+ {
+ if (type.BaseType != null && type.BaseType.Namespace == "System") {
+ if (type.BaseType.Name == "MulticastDelegate")
+ return true;
+ if (type.BaseType.Name == "Delegate" && type.Name != "MulticastDelegate")
+ return true;
+ }
+ return false;
+ }
}
}
diff --git a/main/contrib/ICSharpCode.Decompiler/DecompilerException.cs b/main/contrib/ICSharpCode.Decompiler/DecompilerException.cs
index d62b516da4..5f5f022fc5 100644
--- a/main/contrib/ICSharpCode.Decompiler/DecompilerException.cs
+++ b/main/contrib/ICSharpCode.Decompiler/DecompilerException.cs
@@ -23,7 +23,7 @@ using Mono.Cecil;
namespace ICSharpCode.Decompiler
{
/// <summary>
- /// Desctiption of DecompilerException.
+ /// Description of DecompilerException.
/// </summary>
public class DecompilerException : Exception, ISerializable
{
diff --git a/main/contrib/ICSharpCode.Decompiler/DecompilerSettings.cs b/main/contrib/ICSharpCode.Decompiler/DecompilerSettings.cs
index c3790203da..a354291ed2 100644
--- a/main/contrib/ICSharpCode.Decompiler/DecompilerSettings.cs
+++ b/main/contrib/ICSharpCode.Decompiler/DecompilerSettings.cs
@@ -295,6 +295,21 @@ namespace ICSharpCode.Decompiler
}
}
+ bool makeAssignmentExpressions = true;
+
+ /// <summary>
+ /// Gets/Sets whether to use assignment expressions such as in while ((count = Do()) != 0) ;
+ /// </summary>
+ public bool MakeAssignmentExpressions {
+ get { return makeAssignmentExpressions; }
+ set {
+ if (makeAssignmentExpressions != value) {
+ makeAssignmentExpressions = value;
+ OnPropertyChanged("MakeAssignmentExpressions");
+ }
+ }
+ }
+
bool alwaysGenerateExceptionVariableForCatchBlocks = false;
/// <summary>
@@ -318,6 +333,7 @@ namespace ICSharpCode.Decompiler
if (csharpFormattingOptions == null) {
csharpFormattingOptions = FormattingOptionsFactory.CreateAllman();
csharpFormattingOptions.IndentSwitchBody = false;
+ csharpFormattingOptions.ArrayInitializerWrapping = Wrapping.WrapAlways;
}
return csharpFormattingOptions;
}
diff --git a/main/contrib/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs b/main/contrib/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs
index 4c2080045e..ea6e54dbea 100644
--- a/main/contrib/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs
+++ b/main/contrib/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs
@@ -359,6 +359,10 @@ namespace ICSharpCode.Decompiler.Disassembler
} else if (operand is float) {
float val = (float)operand;
if (val == 0) {
+ if (1 / val == float.NegativeInfinity) {
+ // negative zero is a special case
+ writer.Write('-');
+ }
writer.Write("0.0");
} else if (float.IsInfinity(val) || float.IsNaN(val)) {
byte[] data = BitConverter.GetBytes(val);
@@ -375,6 +379,10 @@ namespace ICSharpCode.Decompiler.Disassembler
} else if (operand is double) {
double val = (double)operand;
if (val == 0) {
+ if (1 / val == double.NegativeInfinity) {
+ // negative zero is a special case
+ writer.Write('-');
+ }
writer.Write("0.0");
} else if (double.IsInfinity(val) || double.IsNaN(val)) {
byte[] data = BitConverter.GetBytes(val);
diff --git a/main/contrib/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs b/main/contrib/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs
index a45a718207..ef6d32e69d 100644
--- a/main/contrib/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs
+++ b/main/contrib/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs
@@ -54,8 +54,8 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteLine("// Method begins at RVA 0x{0:x4}", method.RVA);
output.WriteLine("// Code size {0} (0x{0:x})", body.CodeSize);
output.WriteLine(".maxstack {0}", body.MaxStackSize);
- if (method.DeclaringType.Module.Assembly.EntryPoint == method)
- output.WriteLine (".entrypoint");
+ if (method.DeclaringType.Module.Assembly != null && method.DeclaringType.Module.Assembly.EntryPoint == method)
+ output.WriteLine (".entrypoint");
if (method.Body.HasVariables) {
output.Write(".locals ");
diff --git a/main/contrib/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs b/main/contrib/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
index 1a7d1a4f71..fcdb2b926e 100644
--- a/main/contrib/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
+++ b/main/contrib/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
@@ -33,7 +33,7 @@ namespace ICSharpCode.Decompiler.Disassembler
/// </summary>
public sealed class ReflectionDisassembler
{
- ITextOutput output;
+ readonly ITextOutput output;
CancellationToken cancellationToken;
bool isInType; // whether we are currently disassembling a whole type (-> defaultCollapsed for foldings)
MethodBodyDisassembler methodBodyDisassembler;
@@ -213,8 +213,9 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteLine();
}
}
+ WriteParameterAttributes(0, method.MethodReturnType, method.MethodReturnType);
foreach (var p in method.Parameters) {
- WriteParameterAttributes(p);
+ WriteParameterAttributes(p.Index + 1, p, p);
}
WriteSecurityDeclarations(method);
@@ -613,22 +614,17 @@ namespace ICSharpCode.Decompiler.Disassembler
}
}
- bool HasParameterAttributes(ParameterDefinition p)
+ void WriteParameterAttributes(int index, IConstantProvider cp, ICustomAttributeProvider cap)
{
- return p.HasConstant || p.HasCustomAttributes;
- }
-
- void WriteParameterAttributes(ParameterDefinition p)
- {
- if (!HasParameterAttributes(p))
+ if (!cp.HasConstant && !cap.HasCustomAttributes)
return;
- output.Write(".param [{0}]", p.Index + 1);
- if (p.HasConstant) {
+ output.Write(".param [{0}]", index);
+ if (cp.HasConstant) {
output.Write(" = ");
- WriteConstant(p.Constant);
+ WriteConstant(cp.Constant);
}
output.WriteLine();
- WriteAttributes(p.CustomAttributes);
+ WriteAttributes(cap.CustomAttributes);
}
void WriteConstant(object constant)
diff --git a/main/contrib/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/main/contrib/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
index b46b95935f..08ad03daf0 100644
--- a/main/contrib/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
+++ b/main/contrib/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
@@ -56,6 +56,7 @@
<Compile Include="Ast\DecompilerContext.cs" />
<Compile Include="Ast\NameVariables.cs" />
<Compile Include="Ast\NRefactoryExtensions.cs" />
+ <Compile Include="Ast\TextTokenWriter.cs" />
<Compile Include="Ast\Transforms\AddCheckedBlocks.cs" />
<Compile Include="Ast\Transforms\CombineQueryExpressions.cs" />
<Compile Include="Ast\Transforms\ContextTrackingVisitor.cs" />
@@ -97,6 +98,8 @@
<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" />
<Compile Include="ILAst\GotoRemoval.cs" />
@@ -109,6 +112,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" />
@@ -116,11 +121,6 @@
<Compile Include="ReferenceResolvingException.cs" />
<Compile Include="TextOutputWriter.cs" />
<None Include="Properties\AssemblyInfo.template.cs" />
- <Compile Include="ILAst\LiftedOperators.cs" />
- <Compile Include="ILAst\StateRange.cs" />
- <Compile Include="ILAst\SymbolicExecution.cs" />
- <Compile Include="ILAst\AsyncDecompiler.cs" />
- <Compile Include="Ast\TextTokenWriter.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\external\cecil\Mono.Cecil.csproj">
@@ -147,4 +147,4 @@
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
</ItemGroup>
-</Project>
+</Project> \ No newline at end of file
diff --git a/main/contrib/ICSharpCode.Decompiler/ILAst/AsyncDecompiler.cs b/main/contrib/ICSharpCode.Decompiler/ILAst/AsyncDecompiler.cs
index 4535c0f82a..c8a7f9b76a 100644
--- a/main/contrib/ICSharpCode.Decompiler/ILAst/AsyncDecompiler.cs
+++ b/main/contrib/ICSharpCode.Decompiler/ILAst/AsyncDecompiler.cs
@@ -58,6 +58,7 @@ namespace ICSharpCode.Decompiler.ILAst
FieldDefinition builderField;
FieldDefinition stateField;
Dictionary<FieldDefinition, ILVariable> fieldToParameterMap = new Dictionary<FieldDefinition, ILVariable>();
+ ILVariable cachedStateVar;
// These fields are set by AnalyzeMoveNext()
int finalState = -2;
@@ -155,7 +156,7 @@ namespace ICSharpCode.Decompiler.ILAst
ILExpression loadStateMachineForBuilderExpr;
if (!loadBuilderExpr.Match(ILCode.Ldfld, out builderFieldRef, out loadStateMachineForBuilderExpr))
return false;
- if (!loadStateMachineForBuilderExpr.MatchLdloca(stateMachineVar))
+ if (!(loadStateMachineForBuilderExpr.MatchLdloca(stateMachineVar) || loadStateMachineForBuilderExpr.MatchLdloc(stateMachineVar)))
return false;
builderField = builderFieldRef.ResolveWithinSameModule();
if (builderField == null)
@@ -235,36 +236,50 @@ namespace ICSharpCode.Decompiler.ILAst
{
ILBlock ilMethod = CreateILAst(moveNextMethod);
- if (ilMethod.Body.Count != 6)
+ int startIndex;
+ if (ilMethod.Body.Count == 6) {
+ startIndex = 0;
+ } else if (ilMethod.Body.Count == 7) {
+ // stloc(cachedState, ldfld(valuetype StateMachineStruct::<>1__state, ldloc(this)))
+ ILExpression cachedStateInit;
+ if (!ilMethod.Body[0].Match(ILCode.Stloc, out cachedStateVar, out cachedStateInit))
+ throw new SymbolicAnalysisFailedException();
+ ILExpression instanceExpr;
+ FieldReference loadedField;
+ if (!cachedStateInit.Match(ILCode.Ldfld, out loadedField, out instanceExpr) || loadedField.ResolveWithinSameModule() != stateField || !instanceExpr.MatchThis())
+ throw new SymbolicAnalysisFailedException();
+ startIndex = 1;
+ } else {
throw new SymbolicAnalysisFailedException();
+ }
- mainTryCatch = ilMethod.Body[0] as ILTryCatchBlock;
+ mainTryCatch = ilMethod.Body[startIndex + 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;
+ setResultAndExitLabel = ilMethod.Body[startIndex + 1] as ILLabel;
if (setResultAndExitLabel == null)
throw new SymbolicAnalysisFailedException();
- if (!MatchStateAssignment(ilMethod.Body[2], out finalState))
+ if (!MatchStateAssignment(ilMethod.Body[startIndex + 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))
+ if (!ilMethod.Body[startIndex + 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))
+ if (!ilMethod.Body[startIndex + 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;
+ exitLabel = ilMethod.Body[startIndex + 4] as ILLabel;
if (exitLabel == null)
throw new SymbolicAnalysisFailedException();
}
@@ -318,7 +333,7 @@ namespace ICSharpCode.Decompiler.ILAst
bool MatchStateAssignment(ILNode stfld, out int stateID)
{
- // stfld(StateMachine::<>1__state, ldloc(this), ldc.i4(-2))
+ // stfld(StateMachine::<>1__state, ldloc(this), ldc.i4(stateId))
stateID = 0;
FieldReference fieldRef;
ILExpression target, val;
@@ -329,6 +344,31 @@ namespace ICSharpCode.Decompiler.ILAst
}
return false;
}
+
+ bool MatchRoslynStateAssignment(List<ILNode> block, int index, out int stateID)
+ {
+ // v = ldc.i4(stateId)
+ // stloc(cachedState, v)
+ // stfld(StateMachine::<>1__state, ldloc(this), v)
+ stateID = 0;
+ if (index < 0)
+ return false;
+ ILVariable v;
+ ILExpression val;
+ if (!block[index].Match(ILCode.Stloc, out v, out val) || !val.Match(ILCode.Ldc_I4, out stateID))
+ return false;
+ ILExpression loadV;
+ if (!block[index + 1].MatchStloc(cachedStateVar, out loadV) || !loadV.MatchLdloc(v))
+ return false;
+ ILExpression target;
+ FieldReference fieldRef;
+ if (block[index + 2].Match(ILCode.Stfld, out fieldRef, out target, out loadV)) {
+ return fieldRef.ResolveWithinSameModule() == stateField
+ && target.MatchThis()
+ && loadV.MatchLdloc(v);
+ }
+ return false;
+ }
#endregion
#region AnalyzeStateMachine
@@ -345,7 +385,7 @@ namespace ICSharpCode.Decompiler.ILAst
if (body.Count == 0)
throw new SymbolicAnalysisFailedException();
}
- StateRangeAnalysis rangeAnalysis = new StateRangeAnalysis(body[0], StateRangeAnalysisMode.AsyncMoveNext, stateField);
+ StateRangeAnalysis rangeAnalysis = new StateRangeAnalysis(body[0], StateRangeAnalysisMode.AsyncMoveNext, stateField, cachedStateVar);
int bodyLength = block.Body.Count;
int pos = rangeAnalysis.AssignStateRanges(body, bodyLength);
rangeAnalysis.EnsureLabelAtPos(body, ref pos, ref bodyLength);
@@ -405,7 +445,7 @@ namespace ICSharpCode.Decompiler.ILAst
var tryBody = tryCatchBlock.TryBlock.Body;
if (tryBody.Count == 0)
throw new SymbolicAnalysisFailedException();
- StateRangeAnalysis rangeAnalysis = new StateRangeAnalysis(tryBody[0], StateRangeAnalysisMode.AsyncMoveNext, stateField);
+ StateRangeAnalysis rangeAnalysis = new StateRangeAnalysis(tryBody[0], StateRangeAnalysisMode.AsyncMoveNext, stateField, cachedStateVar);
int tryBodyLength = tryBody.Count;
int posInTryBody = rangeAnalysis.AssignStateRanges(tryBody, tryBodyLength);
rangeAnalysis.EnsureLabelAtPos(tryBody, ref posInTryBody, ref tryBodyLength);
@@ -435,18 +475,16 @@ namespace ICSharpCode.Decompiler.ILAst
List<ILNode> ConvertFinally(List<ILNode> body)
{
List<ILNode> newBody = new List<ILNode>(body);
+ if (newBody.Count == 0)
+ return newBody;
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) {
+ if (newBody[0].Match(ILCode.Brtrue, out endFinallyLabel, out ceqExpr)) {
+ ILExpression condition;
+ if (MatchLogicNot(ceqExpr, out condition)) {
+ if (condition.MatchLdloc(doFinallyBodies)) {
newBody.RemoveAt(0);
- }
- } else if (ceqExpr.Match(ILCode.LogicNot, out loadDoFinallyBodies)) {
- if (loadDoFinallyBodies.MatchLdloc(doFinallyBodies)) {
+ } else if (condition.Code == ILCode.Clt && condition.Arguments[0].MatchLdloc(cachedStateVar) && condition.Arguments[1].MatchLdcI4(0)) {
newBody.RemoveAt(0);
}
}
@@ -454,6 +492,17 @@ namespace ICSharpCode.Decompiler.ILAst
return newBody;
}
+ bool MatchLogicNot(ILExpression expr, out ILExpression arg)
+ {
+ ILExpression loadZero;
+ object unused;
+ if (expr.Match(ILCode.Ceq, out unused, out arg, out loadZero)) {
+ int num;
+ return loadZero.Match(ILCode.Ldc_I4, out num) && num == 0;
+ }
+ return expr.Match(ILCode.LogicNot, out arg);
+ }
+
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.
@@ -475,7 +524,8 @@ namespace ICSharpCode.Decompiler.ILAst
newBody.RemoveAt(newBody.Count - 1); // remove AwaitUnsafeOnCompleted call
if (callAwaitUnsafeOnCompleted == null || callAwaitUnsafeOnCompleted.Code != ILCode.Call)
throw new SymbolicAnalysisFailedException();
- if (((MethodReference)callAwaitUnsafeOnCompleted.Operand).Name != "AwaitUnsafeOnCompleted")
+ string methodName = ((MethodReference)callAwaitUnsafeOnCompleted.Operand).Name;
+ if (methodName != "AwaitUnsafeOnCompleted" && methodName != "AwaitOnCompleted")
throw new SymbolicAnalysisFailedException();
if (callAwaitUnsafeOnCompleted.Arguments.Count != 3)
throw new SymbolicAnalysisFailedException();
@@ -493,9 +543,10 @@ namespace ICSharpCode.Decompiler.ILAst
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
+ if (MatchStateAssignment(newBody.LastOrDefault(), out targetStateID))
+ newBody.RemoveAt(newBody.Count - 1); // remove awaiter field assignment
+ else if (MatchRoslynStateAssignment(newBody, newBody.Count - 3, out targetStateID))
+ newBody.RemoveRange(newBody.Count - 3, 3); // remove awaiter field assignment
}
#endregion
diff --git a/main/contrib/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs b/main/contrib/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs
index da8c6c6beb..e30398e042 100644
--- a/main/contrib/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs
+++ b/main/contrib/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs
@@ -413,11 +413,11 @@ namespace ICSharpCode.Decompiler.ILAst
}
}
- // Occasionally the compilers or obfuscators generate unreachable code (which might be intentonally invalid)
- // I belive it is safe to just remove it
+ // Occasionally the compilers or obfuscators generate unreachable code (which might be intentionally invalid)
+ // I believe it is safe to just remove it
body.RemoveAll(b => b.StackBefore == null);
- // Genertate temporary variables to replace stack
+ // Generate temporary variables to replace stack
foreach(ByteCode byteCode in body) {
int argIdx = 0;
int popCount = byteCode.PopCount ?? byteCode.StackBefore.Length;
@@ -652,7 +652,7 @@ namespace ICSharpCode.Decompiler.ILAst
// Find the first and widest scope
int tryStart = ehs.Min(eh => eh.TryStart.Offset);
int tryEnd = ehs.Where(eh => eh.TryStart.Offset == tryStart).Max(eh => eh.TryEnd.Offset);
- var handlers = ehs.Where(eh => eh.TryStart.Offset == tryStart && eh.TryEnd.Offset == tryEnd).OrderBy(eh => eh.TryStart.Offset).ToList();
+ var handlers = ehs.Where(eh => eh.TryStart.Offset == tryStart && eh.TryEnd.Offset == tryEnd).ToList();
// Remember that any part of the body migt have been removed due to unreachability
diff --git a/main/contrib/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs b/main/contrib/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs
index 5de51b9b1a..ecf1e9fc5f 100644
--- a/main/contrib/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs
+++ b/main/contrib/ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs
@@ -20,6 +20,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
+using ICSharpCode.Decompiler.FlowAnalysis;
using ICSharpCode.NRefactory.Utils;
using Mono.Cecil;
using Mono.Cecil.Cil;
@@ -37,6 +38,7 @@ namespace ICSharpCode.Decompiler.ILAst
PropertyAccessInstructions,
SplitToMovableBlocks,
TypeInference,
+ HandlePointerArithmetic,
SimplifyShortCircuit,
SimplifyTernaryOperator,
SimplifyNullCoalescing,
@@ -123,6 +125,9 @@ namespace ICSharpCode.Decompiler.ILAst
// Types are needed for the ternary operator optimization
TypeAnalysis.Run(context, method);
+ if (abortBeforeStep == ILAstOptimizationStep.HandlePointerArithmetic) return;
+ HandlePointerArithmetic(method);
+
foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>()) {
bool modified;
do {
@@ -168,11 +173,15 @@ namespace ICSharpCode.Decompiler.ILAst
modified |= block.RunOptimization(TransformObjectInitializers);
if (abortBeforeStep == ILAstOptimizationStep.MakeAssignmentExpression) return;
- modified |= block.RunOptimization(MakeAssignmentExpression);
+ if (context.Settings.MakeAssignmentExpressions) {
+ modified |= block.RunOptimization(MakeAssignmentExpression);
+ }
modified |= block.RunOptimization(MakeCompoundAssignments);
if (abortBeforeStep == ILAstOptimizationStep.IntroducePostIncrement) return;
- modified |= block.RunOptimization(IntroducePostIncrement);
+ if (context.Settings.IntroduceIncrementAndDecrement) {
+ modified |= block.RunOptimization(IntroducePostIncrement);
+ }
if (abortBeforeStep == ILAstOptimizationStep.InlineExpressionTreeParameterDeclarations) return;
if (context.Settings.ExpressionTrees) {
@@ -223,11 +232,13 @@ namespace ICSharpCode.Decompiler.ILAst
new ILInlining(method).InlineAllVariables();
if (abortBeforeStep == ILAstOptimizationStep.CachedDelegateInitialization) return;
- foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>()) {
- for (int i = 0; i < block.Body.Count; i++) {
- // TODO: Move before loops
- CachedDelegateInitializationWithField(block, ref i);
- CachedDelegateInitializationWithLocal(block, ref i);
+ if (context.Settings.AnonymousMethods) {
+ foreach(ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>()) {
+ for (int i = 0; i < block.Body.Count; i++) {
+ // TODO: Move before loops
+ CachedDelegateInitializationWithField(block, ref i);
+ CachedDelegateInitializationWithLocal(block, ref i);
+ }
}
}
@@ -337,15 +348,15 @@ namespace ICSharpCode.Decompiler.ILAst
expr.ILRanges.Clear();
continue;
case ILCode.__Brfalse: op = ILCode.LogicNot; break;
- case ILCode.__Beq: op = ILCode.Ceq; break;
+ case ILCode.__Beq: op = ILCode.Ceq; break;
case ILCode.__Bne_Un: op = ILCode.Cne; break;
- case ILCode.__Bgt: op = ILCode.Cgt; break;
+ case ILCode.__Bgt: op = ILCode.Cgt; break;
case ILCode.__Bgt_Un: op = ILCode.Cgt_Un; break;
- case ILCode.__Ble: op = ILCode.Cle; break;
+ case ILCode.__Ble: op = ILCode.Cle; break;
case ILCode.__Ble_Un: op = ILCode.Cle_Un; break;
- case ILCode.__Blt: op = ILCode.Clt; break;
+ case ILCode.__Blt: op = ILCode.Clt; break;
case ILCode.__Blt_Un: op = ILCode.Clt_Un; break;
- case ILCode.__Bge: op = ILCode.Cge; break;
+ case ILCode.__Bge: op = ILCode.Cge; break;
case ILCode.__Bge_Un: op = ILCode.Cge_Un; break;
default:
continue;
@@ -424,9 +435,9 @@ namespace ICSharpCode.Decompiler.ILAst
// Might be 'newobj(SomeDelegate, target, ldvirtftn(F, target))'.
ILVariable target;
if (expr.Arguments[0].Match(ILCode.Ldloc, out target)
- && expr.Arguments[1].Code == ILCode.Ldvirtftn
- && expr.Arguments[1].Arguments.Count == 1
- && expr.Arguments[1].Arguments[0].MatchLdloc(target))
+ && expr.Arguments[1].Code == ILCode.Ldvirtftn
+ && expr.Arguments[1].Arguments.Count == 1
+ && expr.Arguments[1].Arguments[0].MatchLdloc(target))
{
// Remove the 'target' argument from the ldvirtftn instruction.
// It's not needed in the translation to C#, and needs to be eliminated so that the target expression
@@ -461,9 +472,9 @@ namespace ICSharpCode.Decompiler.ILAst
// Start a new basic block if necessary
if (currNode is ILLabel ||
- currNode is ILTryCatchBlock || // Counts as label
- lastNode.IsConditionalControlFlow() ||
- lastNode.IsUnconditionalControlFlow())
+ currNode is ILTryCatchBlock || // Counts as label
+ lastNode.IsConditionalControlFlow() ||
+ lastNode.IsUnconditionalControlFlow())
{
// Try to reuse the label
ILLabel label = currNode as ILLabel ?? new ILLabel() { Name = "Block_" + (nextLabelIndex++).ToString() };
@@ -656,6 +667,180 @@ namespace ICSharpCode.Decompiler.ILAst
return combinedVariable;
});
}
+
+ void HandlePointerArithmetic(ILNode method)
+ {
+ foreach (ILExpression expr in method.GetSelfAndChildrenRecursive<ILExpression>()) {
+ List<ILExpression> args = expr.Arguments;
+ switch (expr.Code) {
+ case ILCode.Localloc:
+ {
+ PointerType type = expr.InferredType as PointerType;
+ if (type != null) {
+ ILExpression arg0 = args[0];
+ ILExpression expr2 = expr;
+ DivideOrMultiplyBySize(ref expr2, ref arg0, type.ElementType, true);
+ // expr shouldn't change
+ if (expr2 != expr)
+ throw new InvalidOperationException();
+ args[0] = arg0;
+ }
+ break;
+ }
+ case ILCode.Add:
+ case ILCode.Add_Ovf:
+ case ILCode.Add_Ovf_Un:
+ {
+ ILExpression arg0 = args[0];
+ ILExpression arg1 = args[1];
+ if (expr.InferredType is PointerType) {
+ if (arg0.ExpectedType is PointerType) {
+ DivideOrMultiplyBySize(ref arg0, ref arg1, ((PointerType)expr.InferredType).ElementType, true);
+ } else if (arg1.ExpectedType is PointerType)
+ DivideOrMultiplyBySize(ref arg1, ref arg0, ((PointerType)expr.InferredType).ElementType, true);
+ }
+ args[0] = arg0;
+ args[1] = arg1;
+ break;
+ }
+ case ILCode.Sub:
+ case ILCode.Sub_Ovf:
+ case ILCode.Sub_Ovf_Un:
+ {
+ ILExpression arg0 = args[0];
+ ILExpression arg1 = args[1];
+ if (expr.InferredType is PointerType) {
+ if (arg0.ExpectedType is PointerType && !(arg1.InferredType is PointerType))
+ DivideOrMultiplyBySize(ref arg0, ref arg1, ((PointerType)expr.InferredType).ElementType, true);
+ }
+ args[0] = arg0;
+ args[1] = arg1;
+ break;
+ }
+ case ILCode.Conv_I8:
+ {
+ ILExpression arg0 = args[0];
+ // conv.i8(div:intptr(p0 - p1))
+ if (arg0.Code == ILCode.Div && arg0.InferredType.FullName == "System.IntPtr")
+ {
+ ILExpression dividend = arg0.Arguments[0];
+ if (dividend.InferredType.FullName == "System.IntPtr" &&
+ (dividend.Code == ILCode.Sub || dividend.Code == ILCode.Sub_Ovf || dividend.Code == ILCode.Sub_Ovf_Un))
+ {
+ PointerType pointerType0 = dividend.Arguments[0].InferredType as PointerType;
+ PointerType pointerType1 = dividend.Arguments[1].InferredType as PointerType;
+
+ if (pointerType0 != null && pointerType1 != null) {
+ if (pointerType0.ElementType.FullName == "System.Void" ||
+ pointerType0.ElementType.FullName != pointerType1.ElementType.FullName) {
+ pointerType0 = pointerType1 = new PointerType(typeSystem.Byte);
+ dividend.Arguments[0] = Cast(dividend.Arguments[0], pointerType0);
+ dividend.Arguments[1] = Cast(dividend.Arguments[1], pointerType1);
+ }
+
+ DivideOrMultiplyBySize(ref dividend, ref arg0, pointerType0.ElementType, false);
+ // dividend shouldn't change
+ if (args[0].Arguments[0] != dividend)
+ throw new InvalidOperationException();
+ }
+ }
+ }
+ args[0] = arg0;
+ break;
+ }
+ }
+ }
+ }
+
+ static ILExpression UnwrapIntPtrCast(ILExpression expr)
+ {
+ if (expr.Code != ILCode.Conv_I && expr.Code != ILCode.Conv_U)
+ return expr;
+
+ ILExpression arg = expr.Arguments[0];
+ switch (arg.InferredType.MetadataType) {
+ case MetadataType.Byte:
+ case MetadataType.SByte:
+ case MetadataType.UInt16:
+ case MetadataType.Int16:
+ case MetadataType.UInt32:
+ case MetadataType.Int32:
+ case MetadataType.UInt64:
+ case MetadataType.Int64:
+ return arg;
+ }
+
+ return expr;
+ }
+
+ static ILExpression Cast(ILExpression expr, TypeReference type)
+ {
+ return new ILExpression(ILCode.Castclass, type, expr)
+ {
+ InferredType = type,
+ ExpectedType = type
+ };
+ }
+
+ void DivideOrMultiplyBySize(ref ILExpression pointerExpr, ref ILExpression adjustmentExpr, TypeReference elementType, bool divide)
+ {
+ adjustmentExpr = UnwrapIntPtrCast(adjustmentExpr);
+
+ ILExpression sizeOfExpression;
+ switch (TypeAnalysis.GetInformationAmount(elementType)) {
+ case 0: // System.Void
+ pointerExpr = Cast(pointerExpr, new PointerType(typeSystem.Byte));
+ goto case 1;
+ case 1:
+ case 8:
+ sizeOfExpression = new ILExpression(ILCode.Ldc_I4, 1);
+ break;
+ case 16:
+ sizeOfExpression = new ILExpression(ILCode.Ldc_I4, 2);
+ break;
+ case 32:
+ sizeOfExpression = new ILExpression(ILCode.Ldc_I4, 4);
+ break;
+ case 64:
+ sizeOfExpression = new ILExpression(ILCode.Ldc_I4, 8);
+ break;
+ default:
+ sizeOfExpression = new ILExpression(ILCode.Sizeof, elementType);
+ break;
+ }
+
+ if (divide && (adjustmentExpr.Code == ILCode.Mul || adjustmentExpr.Code == ILCode.Mul_Ovf || adjustmentExpr.Code == ILCode.Mul_Ovf_Un) ||
+ !divide && (adjustmentExpr.Code == ILCode.Div || adjustmentExpr.Code == ILCode.Div_Un)) {
+ ILExpression mulArg = adjustmentExpr.Arguments[1];
+ if (mulArg.Code == sizeOfExpression.Code && sizeOfExpression.Operand.Equals(mulArg.Operand)) {
+ adjustmentExpr = UnwrapIntPtrCast(adjustmentExpr.Arguments[0]);
+ return;
+ }
+ }
+
+ if (adjustmentExpr.Code == sizeOfExpression.Code) {
+ if (sizeOfExpression.Operand.Equals(adjustmentExpr.Operand)) {
+ adjustmentExpr = new ILExpression(ILCode.Ldc_I4, 1);
+ return;
+ }
+
+ if (adjustmentExpr.Code == ILCode.Ldc_I4) {
+ int offsetInBytes = (int)adjustmentExpr.Operand;
+ int elementSize = (int)sizeOfExpression.Operand;
+
+ if (offsetInBytes % elementSize != 0) {
+ pointerExpr = Cast(pointerExpr, new PointerType(typeSystem.Byte));
+ return;
+ }
+
+ adjustmentExpr.Operand = offsetInBytes / elementSize;
+ return;
+ }
+ }
+
+ if (!(sizeOfExpression.Code == ILCode.Ldc_I4 && (int)sizeOfExpression.Operand == 1))
+ adjustmentExpr = new ILExpression(divide ? ILCode.Div_Un : ILCode.Mul, null, adjustmentExpr, sizeOfExpression);
+ }
public static void ReplaceVariables(ILNode node, Func<ILVariable, ILVariable> variableMapping)
{
diff --git a/main/contrib/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs b/main/contrib/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs
index 7fd74a60e8..179b40a673 100644
--- a/main/contrib/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs
+++ b/main/contrib/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs
@@ -21,8 +21,10 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
+using System.Text;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Disassembler;
+using ICSharpCode.NRefactory.Utils;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Cecil = Mono.Cecil;
diff --git a/main/contrib/ICSharpCode.Decompiler/ILAst/ILInlining.cs b/main/contrib/ICSharpCode.Decompiler/ILAst/ILInlining.cs
index 880592b103..11140ef083 100644
--- a/main/contrib/ICSharpCode.Decompiler/ILAst/ILInlining.cs
+++ b/main/contrib/ICSharpCode.Decompiler/ILAst/ILInlining.cs
@@ -50,32 +50,36 @@ namespace ICSharpCode.Decompiler.ILAst
AnalyzeNode(method);
}
- void AnalyzeNode(ILNode node)
+ /// <summary>
+ /// For each variable reference, adds <paramref name="direction"/> to the num* dicts.
+ /// Direction will be 1 for analysis, and -1 when removing a node from analysis.
+ /// </summary>
+ void AnalyzeNode(ILNode node, int direction = 1)
{
ILExpression expr = node as ILExpression;
if (expr != null) {
ILVariable locVar = expr.Operand as ILVariable;
if (locVar != null) {
if (expr.Code == ILCode.Stloc) {
- numStloc[locVar] = numStloc.GetOrDefault(locVar) + 1;
+ numStloc[locVar] = numStloc.GetOrDefault(locVar) + direction;
} else if (expr.Code == ILCode.Ldloc) {
- numLdloc[locVar] = numLdloc.GetOrDefault(locVar) + 1;
+ numLdloc[locVar] = numLdloc.GetOrDefault(locVar) + direction;
} else if (expr.Code == ILCode.Ldloca) {
- numLdloca[locVar] = numLdloca.GetOrDefault(locVar) + 1;
+ numLdloca[locVar] = numLdloca.GetOrDefault(locVar) + direction;
} else {
throw new NotSupportedException(expr.Code.ToString());
}
}
foreach (ILExpression child in expr.Arguments)
- AnalyzeNode(child);
+ AnalyzeNode(child, direction);
} else {
var catchBlock = node as ILTryCatchBlock.CatchBlock;
if (catchBlock != null && catchBlock.ExceptionVariable != null) {
- numStloc[catchBlock.ExceptionVariable] = numStloc.GetOrDefault(catchBlock.ExceptionVariable) + 1;
+ numStloc[catchBlock.ExceptionVariable] = numStloc.GetOrDefault(catchBlock.ExceptionVariable) + direction;
}
foreach (ILNode child in node.GetChildren())
- AnalyzeNode(child);
+ AnalyzeNode(child, direction);
}
}
@@ -194,6 +198,7 @@ namespace ICSharpCode.Decompiler.ILAst
// The variable is never loaded
if (inlinedExpression.HasNoSideEffects()) {
// Remove completely
+ AnalyzeNode(body[pos], -1);
body.RemoveAt(pos);
return true;
} else if (inlinedExpression.CanBeExpressionStatement() && v.IsGenerated) {
@@ -334,6 +339,7 @@ namespace ICSharpCode.Decompiler.ILAst
case ILCode.Stfld:
case ILCode.Ldfld:
case ILCode.Ldflda:
+ case ILCode.Await:
return true;
}
}
diff --git a/main/contrib/ICSharpCode.Decompiler/ILAst/PatternMatching.cs b/main/contrib/ICSharpCode.Decompiler/ILAst/PatternMatching.cs
index 31fcf62b15..441088b903 100644
--- a/main/contrib/ICSharpCode.Decompiler/ILAst/PatternMatching.cs
+++ b/main/contrib/ICSharpCode.Decompiler/ILAst/PatternMatching.cs
@@ -167,5 +167,11 @@ namespace ICSharpCode.Decompiler.ILAst
ILVariable v;
return node.Match(ILCode.Stloc, out v, out expr) && v == expectedVar;
}
+
+ public static bool MatchLdcI4(this ILNode node, int expectedValue)
+ {
+ int v;
+ return node.Match(ILCode.Ldc_I4, out v) && v == expectedValue;
+ }
}
}
diff --git a/main/contrib/ICSharpCode.Decompiler/ILAst/StateRange.cs b/main/contrib/ICSharpCode.Decompiler/ILAst/StateRange.cs
index 4a55e1d0b6..3a3dfc2f34 100644
--- a/main/contrib/ICSharpCode.Decompiler/ILAst/StateRange.cs
+++ b/main/contrib/ICSharpCode.Decompiler/ILAst/StateRange.cs
@@ -137,23 +137,25 @@ namespace ICSharpCode.Decompiler.ILAst
internal DefaultDictionary<ILNode, StateRange> ranges;
SymbolicEvaluationContext evalContext;
- internal Dictionary<MethodDefinition, Interval> finallyMethodToStateInterval; // used only for IteratorDispose
+ internal Dictionary<MethodDefinition, StateRange> finallyMethodToStateRange; // 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)
+ public StateRangeAnalysis(ILNode entryPoint, StateRangeAnalysisMode mode, FieldDefinition stateField, ILVariable cachedStateVar = null)
{
this.mode = mode;
this.stateField = stateField;
if (mode == StateRangeAnalysisMode.IteratorDispose) {
- finallyMethodToStateInterval = new Dictionary<MethodDefinition, Interval>();
+ finallyMethodToStateRange = new Dictionary<MethodDefinition, StateRange>();
}
ranges = new DefaultDictionary<ILNode, StateRange>(n => new StateRange());
ranges[entryPoint] = new StateRange(int.MinValue, int.MaxValue);
evalContext = new SymbolicEvaluationContext(stateField);
+ if (cachedStateVar != null)
+ evalContext.AddStateVariable(cachedStateVar);
}
public int AssignStateRanges(List<ILNode> body, int bodyLength)
@@ -213,7 +215,7 @@ namespace ICSharpCode.Decompiler.ILAst
break;
case ILCode.Brtrue:
{
- SymbolicValue val = evalContext.Eval(expr.Arguments[0]);
+ SymbolicValue val = evalContext.Eval(expr.Arguments[0]).AsBool();
if (val.Type == SymbolicValueType.StateEquals) {
ranges[(ILLabel)expr.Operand].UnionWith(nodeRange, val.Constant, val.Constant);
StateRange nextRange = ranges[body[i + 1]];
@@ -249,9 +251,9 @@ namespace ICSharpCode.Decompiler.ILAst
// 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))
+ if (mdef == null || finallyMethodToStateRange.ContainsKey(mdef))
throw new SymbolicAnalysisFailedException();
- finallyMethodToStateInterval.Add(mdef, nodeRange.ToEnclosingInterval());
+ finallyMethodToStateRange.Add(mdef, nodeRange);
break;
} else {
goto default;
diff --git a/main/contrib/ICSharpCode.Decompiler/ILAst/SymbolicExecution.cs b/main/contrib/ICSharpCode.Decompiler/ILAst/SymbolicExecution.cs
index 98255f2f2d..5fb40acf92 100644
--- a/main/contrib/ICSharpCode.Decompiler/ILAst/SymbolicExecution.cs
+++ b/main/contrib/ICSharpCode.Decompiler/ILAst/SymbolicExecution.cs
@@ -67,7 +67,16 @@ namespace ICSharpCode.Decompiler.ILAst
this.Type = type;
this.Constant = constant;
}
-
+
+ public SymbolicValue AsBool()
+ {
+ if (Type == SymbolicValueType.State) {
+ // convert state integer to bool:
+ // if (state + c) = if (state + c != 0) = if (state != -c)
+ return new SymbolicValue(SymbolicValueType.StateInEquals, unchecked(-Constant));
+ }
+ return this;
+ }
public override string ToString()
{
return string.Format("[SymbolicValue {0}: {1}]", this.Type, this.Constant);
@@ -133,7 +142,7 @@ namespace ICSharpCode.Decompiler.ILAst
// 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]);
+ SymbolicValue val = Eval(expr.Arguments[0]).AsBool();
if (val.Type == SymbolicValueType.StateEquals)
return new SymbolicValue(SymbolicValueType.StateInEquals, val.Constant);
else if (val.Type == SymbolicValueType.StateInEquals)
@@ -141,7 +150,7 @@ namespace ICSharpCode.Decompiler.ILAst
else
return Failed();
default:
- return Failed();
+ return Failed();
}
}
}
diff --git a/main/contrib/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs b/main/contrib/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs
index b050353ab4..6ed1f4dc05 100644
--- a/main/contrib/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs
+++ b/main/contrib/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs
@@ -450,7 +450,7 @@ namespace ICSharpCode.Decompiler.ILAst
return (TypeReference)expr.Operand;
case ILCode.Localloc:
if (forceInferChildren) {
- InferTypeForExpression(expr.Arguments[0], typeSystem.Int32);
+ InferTypeForExpression(expr.Arguments[0], null);
}
if (expectedType is PointerType)
return expectedType;
@@ -539,6 +539,8 @@ namespace ICSharpCode.Decompiler.ILAst
if (forceInferChildren)
InferTypeForExpression(expr.Arguments[1], typeSystem.Int32);
TypeReference type = NumericPromotion(InferTypeForExpression(expr.Arguments[0], null));
+ if (type == null)
+ return null;
TypeReference expectedInputType = null;
switch (type.MetadataType) {
case MetadataType.Int32:
@@ -827,7 +829,7 @@ namespace ICSharpCode.Decompiler.ILAst
case ILCode.Await:
{
TypeReference taskType = InferTypeForExpression(expr.Arguments[0], null);
- if (taskType.Name == "Task`1" && taskType.IsGenericInstance && taskType.Namespace == "System.Threading.Tasks") {
+ if (taskType != null && taskType.Name == "Task`1" && taskType.IsGenericInstance && taskType.Namespace == "System.Threading.Tasks") {
return ((GenericInstanceType)taskType).GenericArguments[0];
}
return null;
@@ -1011,7 +1013,7 @@ namespace ICSharpCode.Decompiler.ILAst
TypeReference leftPreferred = DoInferTypeForExpression(left, expectedType);
if (leftPreferred is PointerType) {
left.InferredType = left.ExpectedType = leftPreferred;
- InferTypeForExpression(right, typeSystem.IntPtr);
+ InferTypeForExpression(right, null);
return leftPreferred;
}
if (IsEnum(leftPreferred)) {
@@ -1022,7 +1024,7 @@ namespace ICSharpCode.Decompiler.ILAst
}
TypeReference rightPreferred = DoInferTypeForExpression(right, expectedType);
if (rightPreferred is PointerType) {
- InferTypeForExpression(left, typeSystem.IntPtr);
+ InferTypeForExpression(left, null);
right.InferredType = right.ExpectedType = rightPreferred;
return rightPreferred;
}
@@ -1042,7 +1044,10 @@ namespace ICSharpCode.Decompiler.ILAst
TypeReference leftPreferred = DoInferTypeForExpression(left, expectedType);
if (leftPreferred is PointerType) {
left.InferredType = left.ExpectedType = leftPreferred;
- InferTypeForExpression(right, typeSystem.IntPtr);
+ TypeReference rightPreferred = InferTypeForExpression(right, null);
+ // subtracting two pointers is not a pointer
+ if (rightPreferred is PointerType)
+ return typeSystem.IntPtr;
return leftPreferred;
}
if (IsEnum(leftPreferred)) {
diff --git a/main/contrib/ICSharpCode.Decompiler/ILAst/YieldReturnDecompiler.cs b/main/contrib/ICSharpCode.Decompiler/ILAst/YieldReturnDecompiler.cs
index b4b6183bf8..2da165f610 100644
--- a/main/contrib/ICSharpCode.Decompiler/ILAst/YieldReturnDecompiler.cs
+++ b/main/contrib/ICSharpCode.Decompiler/ILAst/YieldReturnDecompiler.cs
@@ -312,7 +312,7 @@ namespace ICSharpCode.Decompiler.ILAst
// This is (int.MinValue, int.MaxValue) for the first instruction.
// These ranges are propagated depending on the conditional jumps performed by the code.
- Dictionary<MethodDefinition, Interval> finallyMethodToStateInterval;
+ Dictionary<MethodDefinition, StateRange> finallyMethodToStateRange;
void ConstructExceptionTable()
{
@@ -321,11 +321,11 @@ namespace ICSharpCode.Decompiler.ILAst
var rangeAnalysis = new StateRangeAnalysis(ilMethod.Body[0], StateRangeAnalysisMode.IteratorDispose, stateField);
rangeAnalysis.AssignStateRanges(ilMethod.Body, ilMethod.Body.Count);
- finallyMethodToStateInterval = rangeAnalysis.finallyMethodToStateInterval;
+ finallyMethodToStateRange = rangeAnalysis.finallyMethodToStateRange;
// Now look at the finally blocks:
foreach (var tryFinally in ilMethod.GetSelfAndChildrenRecursive<ILTryCatchBlock>()) {
- Interval interval = rangeAnalysis.ranges[tryFinally.TryBlock.Body[0]].ToEnclosingInterval();
+ var range = rangeAnalysis.ranges[tryFinally.TryBlock.Body[0]];
var finallyBody = tryFinally.FinallyBlock.Body;
if (finallyBody.Count != 2)
throw new SymbolicAnalysisFailedException();
@@ -338,9 +338,9 @@ namespace ICSharpCode.Decompiler.ILAst
throw new SymbolicAnalysisFailedException();
MethodDefinition mdef = GetMethodDefinition(call.Operand as MethodReference);
- if (mdef == null || finallyMethodToStateInterval.ContainsKey(mdef))
+ if (mdef == null || finallyMethodToStateRange.ContainsKey(mdef))
throw new SymbolicAnalysisFailedException();
- finallyMethodToStateInterval.Add(mdef, interval);
+ finallyMethodToStateRange.Add(mdef, range);
}
rangeAnalysis = null;
}
@@ -430,10 +430,9 @@ namespace ICSharpCode.Decompiler.ILAst
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)'
+ // The last element in the body usually is a label pointing to the 'ret(false)'
returnFalseLabel = body.ElementAtOrDefault(bodyLength - 1) as ILLabel;
- if (returnFalseLabel == null)
- throw new SymbolicAnalysisFailedException();
+ // Note: in Roslyn-compiled code, returnFalseLabel may be null.
var rangeAnalysis = new StateRangeAnalysis(body[0], StateRangeAnalysisMode.IteratorMoveNext, stateField);
int pos = rangeAnalysis.AssignStateRanges(body, bodyLength);
@@ -485,7 +484,7 @@ namespace ICSharpCode.Decompiler.ILAst
throw new SymbolicAnalysisFailedException();
int val = (int)expr.Arguments[0].Operand;
if (val == 0) {
- newBody.Add(MakeGoTo(returnFalseLabel));
+ newBody.Add(new ILExpression(ILCode.YieldBreak, null));
} else if (val == 1) {
newBody.Add(MakeGoTo(labels, currentState));
} else {
@@ -497,7 +496,7 @@ namespace ICSharpCode.Decompiler.ILAst
// handle direct return (e.g. in release builds)
int val = (int)expr.Arguments[0].Operand;
if (val == 0) {
- newBody.Add(MakeGoTo(returnFalseLabel));
+ newBody.Add(new ILExpression(ILCode.YieldBreak, null));
} else if (val == 1) {
newBody.Add(MakeGoTo(labels, currentState));
} else {
@@ -507,21 +506,21 @@ namespace ICSharpCode.Decompiler.ILAst
MethodDefinition method = GetMethodDefinition(expr.Operand as MethodReference);
if (method == null)
throw new SymbolicAnalysisFailedException();
- Interval interval;
+ StateRange stateRange;
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 SymbolicAnalysisFailedException();
- newBody.Add(MakeGoTo(returnFalseLabel));
- } else if (finallyMethodToStateInterval.TryGetValue(method, out interval)) {
+ newBody.Add(new ILExpression(ILCode.YieldBreak, null));
+ } else if (finallyMethodToStateRange.TryGetValue(method, out stateRange)) {
// Call to Finally-method
- int index = stateChanges.FindIndex(ss => ss.NewState >= interval.Start && ss.NewState <= interval.End);
+ int index = stateChanges.FindIndex(ss => stateRange.Contains(ss.NewState));
if (index < 0)
throw new SymbolicAnalysisFailedException();
ILLabel label = new ILLabel();
- label.Name = "JumpOutOfTryFinally" + interval.Start + "_" + interval.End;
+ label.Name = "JumpOutOfTryFinally" + stateChanges[index].NewState;
newBody.Add(new ILExpression(ILCode.Leave, label));
SetState stateChange = stateChanges[index];
@@ -544,6 +543,7 @@ namespace ICSharpCode.Decompiler.ILAst
ILExpression MakeGoTo(ILLabel targetLabel)
{
+ Debug.Assert(targetLabel != null);
if (targetLabel == returnFalseLabel)
return new ILExpression(ILCode.YieldBreak, null);
else
diff --git a/main/contrib/ICSharpCode.Decompiler/Properties/AssemblyInfo.template.cs b/main/contrib/ICSharpCode.Decompiler/Properties/AssemblyInfo.template.cs
new file mode 100644
index 0000000000..3dba481ae1
--- /dev/null
+++ b/main/contrib/ICSharpCode.Decompiler/Properties/AssemblyInfo.template.cs
@@ -0,0 +1,27 @@
+#region Using directives
+
+using System;
+using System.Resources;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+#endregion
+
+[assembly: AssemblyTitle("ICSharpCode.Decompiler")]
+[assembly: AssemblyDescription("IL decompiler engine")]
+[assembly: AssemblyCompany("ic#code")]
+[assembly: AssemblyProduct("ILSpy")]
+[assembly: AssemblyCopyright("Copyright 2011-2014 AlphaSierraPapa for the SharpDevelop Team")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// This sets the default COM visibility of types in the assembly to invisible.
+// If you need to expose a type to COM, use [ComVisible(true)] on that type.
+[assembly: ComVisible(false)]
+
+[assembly: AssemblyVersion("$INSERTVERSION$")]
+[assembly: AssemblyInformationalVersion("$INSERTVERSION$$INSERTBRANCHPOSTFIX$$INSERTVERSIONNAMEPOSTFIX$-$INSERTSHORTCOMMITHASH$")]
+[assembly: NeutralResourcesLanguage("en-US")]
+
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly",
+ Justification = "AssemblyInformationalVersion does not need to be a parsable version")]
diff --git a/main/contrib/ICSharpCode.Decompiler/Tests/Async.cs b/main/contrib/ICSharpCode.Decompiler/Tests/Async.cs
new file mode 100644
index 0000000000..7629dd5e62
--- /dev/null
+++ b/main/contrib/ICSharpCode.Decompiler/Tests/Async.cs
@@ -0,0 +1,155 @@
+// 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.Runtime.CompilerServices;
+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 void AwaitYield()
+ {
+ await Task.Yield();
+ }
+
+ public async void AwaitDefaultYieldAwaitable()
+ {
+ await default(YieldAwaitable);
+ }
+
+ 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);
+ }
+ }
+}
diff --git a/main/contrib/ICSharpCode.Decompiler/Tests/CodeSampleFileParser.cs b/main/contrib/ICSharpCode.Decompiler/Tests/CodeSampleFileParser.cs
index 552d092ee5..5cb49aad73 100644
--- a/main/contrib/ICSharpCode.Decompiler/Tests/CodeSampleFileParser.cs
+++ b/main/contrib/ICSharpCode.Decompiler/Tests/CodeSampleFileParser.cs
@@ -87,7 +87,8 @@ namespace ICSharpCode.Decompiler.Tests
{
if(String.IsNullOrWhiteSpace(s))
return true;
- return s.Trim().StartsWith("//");
+ s = s.Trim();
+ return s.StartsWith("//") || s.StartsWith("#"); // Also ignore #pragmas for warning suppression
}
public static string ConcatLines(IEnumerable<string> lines)
diff --git a/main/contrib/ICSharpCode.Decompiler/Tests/ControlFlow.cs b/main/contrib/ICSharpCode.Decompiler/Tests/ControlFlow.cs
new file mode 100644
index 0000000000..d83f04a2b1
--- /dev/null
+++ b/main/contrib/ICSharpCode.Decompiler/Tests/ControlFlow.cs
@@ -0,0 +1,97 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+
+public static class ControlFlow
+{
+ public static void EmptyIf(string input, List<string> value, Dictionary<int, string> _headers)
+ {
+ if (value.Contains("test"))
+ {
+ }
+ _headers.Add(2, "result");
+ }
+
+ public static void NormalIf(string input, List<string> value, Dictionary<int, string> _headers)
+ {
+ if (value.Contains("test"))
+ {
+ _headers.Add(1, "result");
+ }
+ else
+ {
+ _headers.Add(1, "else");
+ }
+ _headers.Add(2, "end");
+ }
+
+ public static void NormalIf2(string input, List<string> value, Dictionary<int, string> _headers)
+ {
+ if (value.Contains("test"))
+ {
+ _headers.Add(1, "result");
+ }
+ _headers.Add(2, "end");
+ }
+
+ public static void NormalIf3(string input, List<string> value, Dictionary<int, string> _headers)
+ {
+ if (value.Contains("test"))
+ {
+ _headers.Add(1, "result");
+ }
+ else
+ {
+ _headers.Add(1, "else");
+ }
+ }
+
+ public static void Test(string input, List<string> value, Dictionary<int, string> _headers)
+ {
+ foreach (string current in value)
+ {
+ _headers.Add(0, current);
+ }
+ if (value.Contains("test"))
+ {
+ _headers.Add(1, "result");
+ }
+ else
+ {
+ _headers.Add(1, "else");
+ }
+ }
+
+ public static void CascadingIfElse(bool condition, string input, int index)
+ {
+ if (condition)
+ {
+ Console.WriteLine("condition");
+ }
+ else if (input == null)
+ {
+ Console.WriteLine("condition2");
+ }
+ else if (index > 1)
+ {
+ Console.WriteLine("condition3");
+ }
+ }
+}
diff --git a/main/contrib/ICSharpCode.Decompiler/Tests/CustomShortCircuitOperators.cs b/main/contrib/ICSharpCode.Decompiler/Tests/CustomShortCircuitOperators.cs
new file mode 100644
index 0000000000..5bd0ec516b
--- /dev/null
+++ b/main/contrib/ICSharpCode.Decompiler/Tests/CustomShortCircuitOperators.cs
@@ -0,0 +1,88 @@
+// 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.
+
+using System;
+
+public static class CustomShortCircuitOperators
+{
+ // TODO: Restore base class after https://roslyn.codeplex.com/workitem/358 is fixed.
+ private class C
+ {
+ public static bool operator true(CustomShortCircuitOperators.C x)
+ {
+ return true;
+ }
+
+ public static bool operator false(CustomShortCircuitOperators.C x)
+ {
+ return false;
+ }
+
+ public static CustomShortCircuitOperators.C operator &(CustomShortCircuitOperators.C x, CustomShortCircuitOperators.C y)
+ {
+ return null;
+ }
+
+ public static CustomShortCircuitOperators.C operator |(CustomShortCircuitOperators.C x, CustomShortCircuitOperators.C y)
+ {
+ return null;
+ }
+
+ public static bool operator !(CustomShortCircuitOperators.C x)
+ {
+ return false;
+ }
+
+ private static void Main()
+ {
+ CustomShortCircuitOperators.C c = new CustomShortCircuitOperators.C();
+ CustomShortCircuitOperators.C c2 = new CustomShortCircuitOperators.C();
+ CustomShortCircuitOperators.C c3 = c && c2;
+ CustomShortCircuitOperators.C c4 = c || c2;
+ Console.WriteLine(c3.ToString());
+ Console.WriteLine(c4.ToString());
+ }
+
+ private static void Test2()
+ {
+ CustomShortCircuitOperators.C c = new CustomShortCircuitOperators.C();
+ if (c && c)
+ {
+ Console.WriteLine(c.ToString());
+ }
+
+ if (!(c && c))
+ {
+ Console.WriteLine(c.ToString());
+ }
+ }
+
+ private static void Test3()
+ {
+ CustomShortCircuitOperators.C c = new CustomShortCircuitOperators.C();
+ if (c)
+ {
+ Console.WriteLine(c.ToString());
+ }
+ if (!c)
+ {
+ Console.WriteLine(c.ToString());
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/main/contrib/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs b/main/contrib/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs
index 8205042a97..659bb2be68 100644
--- a/main/contrib/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs
+++ b/main/contrib/ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs
@@ -35,10 +35,8 @@ namespace ICSharpCode.Decompiler.Tests
{
protected static void ValidateFileRoundtrip(string samplesFileName)
{
- var lines = File.ReadAllLines(Path.Combine(@"..\..\Tests", samplesFileName));
- var testCode = RemoveIgnorableLines(lines);
- var decompiledTestCode = RoundtripCode(testCode);
- CodeAssert.AreEqual(testCode, decompiledTestCode);
+ var fullPath = Path.Combine(@"..\..\Tests", samplesFileName);
+ AssertRoundtripCode(fullPath);
}
static string RemoveIgnorableLines(IEnumerable<string> lines)
@@ -46,29 +44,27 @@ namespace ICSharpCode.Decompiler.Tests
return CodeSampleFileParser.ConcatLines(lines.Where(l => !CodeSampleFileParser.IsCommentOrBlank(l)));
}
- /// <summary>
- /// Compiles and decompiles a source code.
- /// </summary>
- /// <param name="code">The source code to copile.</param>
- /// <returns>The decompilation result of compiled source code.</returns>
- static string RoundtripCode(string code)
+ protected static void AssertRoundtripCode(string fileName, bool optimize = false, bool useDebug = false, int compilerVersion = 4)
{
- DecompilerSettings settings = new DecompilerSettings();
- settings.FullyQualifyAmbiguousTypeNames = false;
- AssemblyDefinition assembly = Compile(code);
- AstBuilder decompiler = new AstBuilder(new DecompilerContext(assembly.MainModule) { Settings = settings });
+ var code = RemoveIgnorableLines(File.ReadLines(fileName));
+ AssemblyDefinition assembly = CompileLegacy(code, optimize, useDebug, compilerVersion);
+
+ AstBuilder decompiler = new AstBuilder(new DecompilerContext(assembly.MainModule));
decompiler.AddAssembly(assembly);
new Helpers.RemoveCompilerAttribute().Run(decompiler.SyntaxTree);
+
StringWriter output = new StringWriter();
decompiler.GenerateCode(new PlainTextOutput(output));
- return output.ToString();
+ CodeAssert.AreEqual(code, output.ToString());
}
- static AssemblyDefinition Compile(string code)
+ protected static AssemblyDefinition CompileLegacy(string code, bool optimize, bool useDebug, int compilerVersion)
{
- CSharpCodeProvider provider = new CSharpCodeProvider(new Dictionary<string, string> { { "CompilerVersion", "v4.0" } });
+ CSharpCodeProvider provider = new CSharpCodeProvider(new Dictionary<string, string> { { "CompilerVersion", "v" + new Version(compilerVersion, 0) } });
CompilerParameters options = new CompilerParameters();
- options.ReferencedAssemblies.Add("System.Core.dll");
+ options.CompilerOptions = "/unsafe /o" + (optimize ? "+" : "-") + (useDebug ? " /debug" : "");
+ if (compilerVersion >= 4)
+ options.ReferencedAssemblies.Add("System.Core.dll");
CompilerResults results = provider.CompileAssemblyFromSource(options, code);
try
{
diff --git a/main/contrib/ICSharpCode.Decompiler/Tests/DelegateConstruction.cs b/main/contrib/ICSharpCode.Decompiler/Tests/DelegateConstruction.cs
index 5d5071f676..70c00fc655 100644
--- a/main/contrib/ICSharpCode.Decompiler/Tests/DelegateConstruction.cs
+++ b/main/contrib/ICSharpCode.Decompiler/Tests/DelegateConstruction.cs
@@ -62,6 +62,22 @@ public static class DelegateConstruction
}
return null;
}
+
+ public void LambdaInForLoop()
+ {
+ for (int i = 0; i < 100000; i++) {
+ Bar(() => Foo());
+ }
+ }
+
+ public int Foo()
+ {
+ return 0;
+ }
+
+ public void Bar(Func<int> f)
+ {
+ }
}
public static void Test(this string a)
diff --git a/main/contrib/ICSharpCode.Decompiler/Tests/DoubleConstants.cs b/main/contrib/ICSharpCode.Decompiler/Tests/DoubleConstants.cs
new file mode 100644
index 0000000000..2bc20a7730
--- /dev/null
+++ b/main/contrib/ICSharpCode.Decompiler/Tests/DoubleConstants.cs
@@ -0,0 +1,28 @@
+// 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.
+
+using System;
+
+public class DoubleConstants
+{
+ public const double Zero = 0.0;
+ public const double MinusZero = -0.0;
+ public const double NaN = double.NaN;
+ public const double PositiveInfinity = double.PositiveInfinity;
+ public const double NegativeInfinity = double.NegativeInfinity;
+}
diff --git a/main/contrib/ICSharpCode.Decompiler/Tests/ExpressionTrees.cs b/main/contrib/ICSharpCode.Decompiler/Tests/ExpressionTrees.cs
new file mode 100644
index 0000000000..9d325e9e9d
--- /dev/null
+++ b/main/contrib/ICSharpCode.Decompiler/Tests/ExpressionTrees.cs
@@ -0,0 +1,370 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Xml;
+
+public class ExpressionTrees
+{
+ class GenericClass<X>
+ {
+ public static X StaticField;
+ public X InstanceField;
+ public static X StaticProperty { get; set; }
+ public X InstanceProperty { get; set; }
+
+ public static bool GenericMethod<Y>()
+ {
+ return false;
+ }
+ }
+
+ int field;
+
+ static object ToCode<R>(object x, Expression<Func<R>> expr)
+ {
+ return expr;
+ }
+
+ static object ToCode<T, R>(object x, Expression<Func<T, R>> expr)
+ {
+ return expr;
+ }
+
+ static object X()
+ {
+ return null;
+ }
+
+ public void Parameter(bool a)
+ {
+ ToCode(X(), () => a);
+ }
+
+ public void LocalVariable()
+ {
+ bool a = true;
+ ToCode(X(), () => a);
+ }
+
+ public void LambdaParameter()
+ {
+ ToCode(X(), (bool a) => a);
+ }
+
+ public void AddOperator(int x)
+ {
+ ToCode(X(), () => 1 + x + 2);
+ }
+
+ public void AnonymousClasses()
+ {
+ ToCode(X(), () => new { X = 3, A = "a" });
+ }
+
+ public void ArrayIndex()
+ {
+ ToCode(X(), () => new[] { 3, 4, 5 }[0 + (int)(DateTime.Now.Ticks % 3)]);
+ }
+
+ public void ArrayLengthAndDoubles()
+ {
+ ToCode(X(), () => new[] { 1.0, 2.01, 3.5 }.Concat(new[] { 1.0, 2.0 }).ToArray().Length);
+ }
+
+ public void AsOperator()
+ {
+ ToCode(X(), () => new object() as string);
+ }
+
+ public void ComplexGenericName()
+ {
+ ToCode(X(), () => ((Func<int, bool>)(x => x > 0))(0));
+ }
+
+ public void DefaultValue()
+ {
+ ToCode(X(), () => new TimeSpan(1, 2, 3) == default(TimeSpan));
+ }
+
+ public void EnumConstant()
+ {
+ ToCode(X(), () => new object().Equals(MidpointRounding.ToEven));
+ }
+
+ public void IndexerAccess()
+ {
+ var dict = Enumerable.Range(1, 20).ToDictionary(n => n.ToString());
+ ToCode(X(), () => dict["3"] == 3);
+ }
+
+ public void IsOperator()
+ {
+ ToCode(X(), () => new object() is string);
+ }
+
+ public void ListInitializer()
+ {
+ ToCode(X(), () => new Dictionary<int, int> { { 1, 1 }, { 2, 2 }, { 3, 4 } }.Count == 3);
+ }
+
+ public void ListInitializer2()
+ {
+ ToCode(X(), () => new List<int>(50) { 1, 2, 3 }.Count == 3);
+ }
+
+ public void ListInitializer3()
+ {
+ ToCode(X(), () => new List<int> { 1, 2, 3 }.Count == 3);
+ }
+
+ public void LiteralCharAndProperty()
+ {
+ ToCode(X(), () => new string(' ', 3).Length == 1);
+ }
+
+ public void CharNoCast()
+ {
+ ToCode(X(), () => "abc"[1] == 'b');
+ }
+
+ public void StringsImplicitCast()
+ {
+ int i = 1;
+ string x = "X";
+ ToCode(X(), () => (("a\n\\b" ?? x) + x).Length == 2 ? false : true && (1m + -i > 0 || false));
+ }
+
+ public void NotImplicitCast()
+ {
+ byte z = 42;
+ ToCode(X(), () => ~z == 0);
+ }
+
+ public void MembersBuiltin()
+ {
+ ToCode(X(), () => 1.23m.ToString());
+ ToCode(X(), () => AttributeTargets.All.HasFlag((Enum)AttributeTargets.Assembly));
+ ToCode(X(), () => "abc".Length == 3);
+ ToCode(X(), () => 'a'.CompareTo('b') < 0);
+ }
+
+ public void MembersDefault()
+ {
+ ToCode(X(), () => default(DateTime).Ticks == 0);
+ ToCode(X(), () => default(int[]).Length == 0);
+ ToCode(X(), () => default(Type).IsLayoutSequential);
+ ToCode(X(), () => default(List<int>).Count);
+ ToCode(X(), () => default(int[]).Clone() == null);
+ ToCode(X(), () => default(Type).IsInstanceOfType(new object()));
+ ToCode(X(), () => default(List<int>).AsReadOnly());
+ }
+
+ public void DoAssert()
+ {
+ field = 37;
+ ToCode(X(), () => field != C());
+ ToCode(X(), () => !ReferenceEquals(this, new ExpressionTrees()));
+ ToCode(X(), () => MyEquals(this) && !MyEquals(default(ExpressionTrees)));
+ }
+
+ int C()
+ {
+ return field + 5;
+ }
+
+ bool MyEquals(ExpressionTrees other)
+ {
+ return other != null && field == other.field;
+ }
+
+ public void MethodGroupAsExtensionMethod()
+ {
+ ToCode(X(), () => (Func<bool>)new[] { 2000, 2004, 2008, 2012 }.Any);
+ }
+
+ public void MethodGroupConstant()
+ {
+ ToCode(X(), () => Array.TrueForAll(new[] { 2000, 2004, 2008, 2012 }, DateTime.IsLeapYear));
+
+ HashSet<int> set = new HashSet<int>();
+ ToCode(X(), () => new[] { 2000, 2004, 2008, 2012 }.All(set.Add));
+
+ Func<Func<object, object, bool>, bool> sink = f => f(null, null);
+ ToCode(X(), () => sink(int.Equals));
+ }
+
+ public void MultipleCasts()
+ {
+ ToCode(X(), () => 1 == (int)(object)1);
+ }
+
+ public void MultipleDots()
+ {
+ ToCode(X(), () => 3.ToString().ToString().Length > 0);
+ }
+
+ public void NestedLambda()
+ {
+ Func<Func<int>, int> call = f => f();
+ //no params
+ ToCode(X(), () => call(() => 42));
+ //one param
+ ToCode(X(), () => new[] { 37, 42 }.Select(x => x * 2));
+ //two params
+ ToCode(X(), () => new[] { 37, 42 }.Select((x, i) => x * 2));
+ }
+
+ public void CurriedLambda()
+ {
+ ToCode<int, Func<int, Func<int, int>>>(X(), a => b => c => a + b + c);
+ }
+
+ bool Fizz(Func<int, bool> a)
+ {
+ return a(42);
+ }
+
+ bool Buzz(Func<int, bool> a)
+ {
+ return a(42);
+ }
+
+ bool Fizz(Func<string, bool> a)
+ {
+ return a("42");
+ }
+
+ public void NestedLambda2()
+ {
+ ToCode(X(), () => Fizz(x => x == "a"));
+ ToCode(X(), () => Fizz(x => x == 37));
+
+ ToCode(X(), () => Fizz((int x) => true));
+ ToCode(X(), () => Buzz(x => true));
+ }
+
+ public void NewArrayAndExtensionMethod()
+ {
+ ToCode(X(), () => new[] { 1.0, 2.01, 3.5 }.SequenceEqual(new[] { 1.0, 2.01, 3.5 }));
+ }
+
+ public void NewMultiDimArray()
+ {
+ ToCode(X(), () => new int[3, 4].Length == 1);
+ }
+
+ public void NewObject()
+ {
+ ToCode(X(), () => new object() != new object());
+ }
+
+ public void NotOperator()
+ {
+ bool x = true;
+ int y = 3;
+ byte z = 42;
+ ToCode(X(), () => ~(int)z == 0);
+ ToCode(X(), () => ~y == 0);
+ ToCode(X(), () => !x);
+ }
+
+ public void ObjectInitializers()
+ {
+ XmlReaderSettings s = new XmlReaderSettings {
+ CloseInput = false,
+ CheckCharacters = false
+ };
+ ToCode(X(), () => new XmlReaderSettings { CloseInput = s.CloseInput, CheckCharacters = s.CheckCharacters }.Equals(s));
+ }
+
+ public void Quoted()
+ {
+ ToCode(X(), () => (Expression<Func<int, string, string>>)((n, s) => s + n.ToString()) != null);
+ }
+
+ public void Quoted2()
+ {
+ ToCode(X(), () => ToCode(X(), () => true).Equals(null));
+ }
+
+ public void QuotedWithAnonymous()
+ {
+ ToCode(X(), () => new[] { new { X = "a", Y = "b" } }.Select(o => o.X + o.Y).Single());
+ }
+
+ public void StaticCall()
+ {
+ ToCode(X(), () => Equals(3, 0));
+ }
+
+ public void ThisCall()
+ {
+ ToCode(X(), () => !Equals(3));
+ }
+
+ public void ThisExplicit()
+ {
+ ToCode(X(), () => object.Equals(this, 3));
+ }
+
+ public void TypedConstant()
+ {
+ ToCode(X(), () => new[] { typeof(int), typeof(string) });
+ }
+
+ public void StaticCallImplicitCast()
+ {
+ ToCode(X(), () => Equals(3, 0));
+ }
+
+ public void StaticMembers()
+ {
+ ToCode(X(), () => (DateTime.Now > DateTime.Now + TimeSpan.FromMilliseconds(10.001)).ToString() == "False");
+ }
+
+ public void Strings()
+ {
+ int i = 1;
+ string x = "X";
+ ToCode(X(), () => (("a\n\\b" ?? x) + x).Length == 2 ? false : true && (1m + (decimal)-i > 0m || false));
+ }
+
+ public void StringAccessor()
+ {
+ ToCode(X(), () => (int)"abc"[1] == 98);
+ }
+
+ public void GenericClassInstance()
+ {
+ ToCode(X(), () => new GenericClass<int>().InstanceField + new GenericClass<double>().InstanceProperty);
+ }
+
+ public void GenericClassStatic()
+ {
+ ToCode(X(), () => GenericClass<int>.StaticField + GenericClass<double>.StaticProperty);
+ }
+
+ public void InvokeGenericMethod()
+ {
+ ToCode(X(), () => GenericClass<int>.GenericMethod<double>());
+ }
+}
diff --git a/main/contrib/ICSharpCode.Decompiler/Tests/Helpers/CodeAssert.cs b/main/contrib/ICSharpCode.Decompiler/Tests/Helpers/CodeAssert.cs
new file mode 100644
index 0000000000..d06e2db29d
--- /dev/null
+++ b/main/contrib/ICSharpCode.Decompiler/Tests/Helpers/CodeAssert.cs
@@ -0,0 +1,110 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using DiffLib;
+using NUnit.Framework;
+
+namespace ICSharpCode.Decompiler.Tests.Helpers
+{
+ public class CodeAssert
+ {
+ public static void AreEqual(string input1, string input2)
+ {
+ var diff = new StringWriter();
+ if (!Compare(input1, input2, diff)) {
+ Assert.Fail(diff.ToString());
+ }
+ }
+
+ static bool Compare(string input1, string input2, StringWriter diff)
+ {
+ var differ = new AlignedDiff<string>(
+ NormalizeAndSplitCode(input1),
+ NormalizeAndSplitCode(input2),
+ new CodeLineEqualityComparer(),
+ new StringSimilarityComparer(),
+ new StringAlignmentFilter());
+
+ bool result = true, ignoreChange;
+
+ int line1 = 0, line2 = 0;
+
+ foreach (var change in differ.Generate()) {
+ switch (change.Change) {
+ case ChangeType.Same:
+ diff.Write("{0,4} {1,4} ", ++line1, ++line2);
+ diff.Write(" ");
+ diff.WriteLine(change.Element1);
+ break;
+ case ChangeType.Added:
+ diff.Write(" {1,4} ", line1, ++line2);
+ result &= ignoreChange = ShouldIgnoreChange(change.Element2);
+ diff.Write(ignoreChange ? " " : " + ");
+ diff.WriteLine(change.Element2);
+ break;
+ case ChangeType.Deleted:
+ diff.Write("{0,4} ", ++line1, line2);
+ result &= ignoreChange = ShouldIgnoreChange(change.Element1);
+ diff.Write(ignoreChange ? " " : " - ");
+ diff.WriteLine(change.Element1);
+ break;
+ case ChangeType.Changed:
+ diff.Write("{0,4} ", ++line1, line2);
+ result = false;
+ diff.Write("(-) ");
+ diff.WriteLine(change.Element1);
+ diff.Write(" {1,4} ", line1, ++line2);
+ diff.Write("(+) ");
+ diff.WriteLine(change.Element2);
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ class CodeLineEqualityComparer : IEqualityComparer<string>
+ {
+ private IEqualityComparer<string> baseComparer = EqualityComparer<string>.Default;
+
+ public bool Equals(string x, string y)
+ {
+ return baseComparer.Equals(
+ NormalizeLine(x),
+ NormalizeLine(y)
+ );
+ }
+
+ public int GetHashCode(string obj)
+ {
+ return baseComparer.GetHashCode(NormalizeLine(obj));
+ }
+ }
+
+ private static string NormalizeLine(string line)
+ {
+ line = line.Trim();
+ var index = line.IndexOf("//");
+ if (index >= 0) {
+ return line.Substring(0, index);
+ } else if (line.StartsWith("#")) {
+ return string.Empty;
+ } else {
+ return line;
+ }
+ }
+
+ private static bool ShouldIgnoreChange(string line)
+ {
+ // for the result, we should ignore blank lines and added comments
+ return NormalizeLine(line) == string.Empty;
+ }
+
+ private static IEnumerable<string> NormalizeAndSplitCode(string input)
+ {
+ return input.Split(new[] { "\r\n", "\n\r", "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries);
+ }
+ }
+}
diff --git a/main/contrib/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj b/main/contrib/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
index 69598ac73f..8bb4934e78 100644
--- a/main/contrib/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
+++ b/main/contrib/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
@@ -67,6 +67,7 @@
<Compile Include="CallOverloadedMethod.cs" />
<Compile Include="CheckedUnchecked.cs" />
<Compile Include="ControlFlow.cs" />
+ <Compile Include="DoubleConstants.cs" />
<Compile Include="ExpressionTrees.cs" />
<None Include="IL\SequenceOfNestedIfs.Output.cs" />
<Compile Include="IL\ILTests.cs" />
@@ -74,6 +75,7 @@
<Compile Include="CustomShortCircuitOperators.cs" />
<Compile Include="Helpers\CodeAssert.cs" />
<Compile Include="IncrementDecrement.cs" />
+ <Compile Include="Lock.cs" />
<Compile Include="PInvoke.cs" />
<Compile Include="QueryExpressions.cs" />
<Compile Include="Switch.cs" />
@@ -126,11 +128,12 @@
<Name>ICSharpCode.Decompiler</Name>
</ProjectReference>
</ItemGroup>
+ <ItemGroup />
<ItemGroup>
- <Folder Include="IL" />
+ <None Include="BooleanConsumedAsInteger.il" />
</ItemGroup>
<ItemGroup>
- <None Include="BooleanConsumedAsInteger.il" />
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
</Project> \ No newline at end of file
diff --git a/main/contrib/ICSharpCode.Decompiler/Tests/IL/ILTests.cs b/main/contrib/ICSharpCode.Decompiler/Tests/IL/ILTests.cs
new file mode 100644
index 0000000000..f06f3108c5
--- /dev/null
+++ b/main/contrib/ICSharpCode.Decompiler/Tests/IL/ILTests.cs
@@ -0,0 +1,51 @@
+// 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.
+
+using System;
+using System.IO;
+using ICSharpCode.Decompiler.Ast;
+using ICSharpCode.Decompiler.Tests.Helpers;
+using Mono.Cecil;
+using NUnit.Framework;
+
+namespace ICSharpCode.Decompiler.Tests
+{
+ [TestFixture]
+ public class ILTests
+ {
+ const string path = "../../Tests/IL";
+
+ [Test]
+ public void SequenceOfNestedIfs()
+ {
+ Run("SequenceOfNestedIfs.dll", "SequenceOfNestedIfs.Output.cs");
+ }
+
+ void Run(string compiledFile, string expectedOutputFile)
+ {
+ string expectedOutput = File.ReadAllText(Path.Combine(path, expectedOutputFile));
+ var assembly = AssemblyDefinition.ReadAssembly(Path.Combine(path, compiledFile));
+ AstBuilder decompiler = new AstBuilder(new DecompilerContext(assembly.MainModule));
+ decompiler.AddAssembly(assembly);
+ new Helpers.RemoveCompilerAttribute().Run(decompiler.SyntaxTree);
+ StringWriter output = new StringWriter();
+ decompiler.GenerateCode(new PlainTextOutput(output));
+ CodeAssert.AreEqual(expectedOutput, output.ToString());
+ }
+ }
+}
diff --git a/main/contrib/ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.Output.cs b/main/contrib/ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.Output.cs
new file mode 100644
index 0000000000..754d7dafdc
--- /dev/null
+++ b/main/contrib/ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.Output.cs
@@ -0,0 +1,53 @@
+using System;
+[Serializable]
+public class Material
+{
+ public static implicit operator bool(Material m)
+ {
+ return m == null;
+ }
+}
+[Serializable]
+public class SequenceOfNestedIfs
+{
+ public bool _clear;
+ public Material _material;
+ public override bool CheckShader()
+ {
+ return false;
+ }
+ public override void CreateMaterials()
+ {
+ if (!this._clear)
+ {
+ if (!this.CheckShader())
+ {
+ return;
+ }
+ this._material = new Material();
+ }
+ if (!this._material)
+ {
+ if (!this.CheckShader())
+ {
+ return;
+ }
+ this._material = new Material();
+ }
+ if (!this._material)
+ {
+ if (!this.CheckShader())
+ {
+ return;
+ }
+ this._material = new Material();
+ }
+ if (!this._material)
+ {
+ if (this.CheckShader())
+ {
+ this._material = new Material();
+ }
+ }
+ }
+}
diff --git a/main/contrib/ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.dll b/main/contrib/ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.dll
new file mode 100644
index 0000000000..f517d4546d
--- /dev/null
+++ b/main/contrib/ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.dll
Binary files differ
diff --git a/main/contrib/ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.il b/main/contrib/ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.il
new file mode 100644
index 0000000000..9c9b749ce4
--- /dev/null
+++ b/main/contrib/ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.il
@@ -0,0 +1,140 @@
+// Metadata version: v2.0.50727
+.assembly extern mscorlib
+{
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
+ .ver 2:0:0:0
+}
+
+.assembly SequenceOfNestedIfs
+{
+ .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
+ 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module SequenceOfNestedIfs
+// MVID: {DCEC8A87-5679-4EBE-89A3-51274D8B5446}
+.imagebase 0x00400000
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003 // WINDOWS_CUI
+.corflags 0x00000001 // ILONLY
+// Image base: 0x01D60000
+
+
+// =============== CLASS MEMBERS DECLARATION ===================
+
+.class public auto ansi serializable beforefieldinit Material
+ extends [mscorlib]System.Object
+{
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ } // end of method Material::.ctor
+
+ .method public hidebysig specialname static
+ bool op_Implicit(class Material m) cil managed
+ {
+ // Code size 11 (0xb)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: ldnull
+ IL_0008: ceq
+ IL_000a: ret
+ } // end of method Material::op_Implicit
+
+} // end of class Material
+
+.class public auto ansi serializable beforefieldinit SequenceOfNestedIfs
+ extends [mscorlib]System.Object
+{
+ .field public bool _clear
+ .field public class Material _material
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ } // end of method SequenceOfNestedIfs::.ctor
+
+ .method public hidebysig virtual instance bool
+ CheckShader() cil managed
+ {
+ // Code size 2 (0x2)
+ .maxstack 8
+ IL_0000: ldc.i4.0
+ IL_0001: ret
+ } // end of method SequenceOfNestedIfs::CheckShader
+
+ .method public hidebysig virtual instance void
+ CreateMaterials() cil managed
+ {
+ // Code size 168 (0xa8)
+ .maxstack 13
+ IL_0000: ldarg.0
+ IL_0001: ldfld bool SequenceOfNestedIfs::_clear
+ IL_0006: brtrue IL_0026
+
+ IL_000b: ldarg.0
+ IL_000c: callvirt instance bool SequenceOfNestedIfs::CheckShader()
+ IL_0011: brtrue IL_001b
+
+ IL_0016: br IL_00a7
+
+ IL_001b: ldarg.0
+ IL_001c: newobj instance void Material::.ctor()
+ IL_0021: stfld class Material SequenceOfNestedIfs::_material
+ IL_0026: ldarg.0
+ IL_0027: ldfld class Material SequenceOfNestedIfs::_material
+ IL_002c: call bool Material::op_Implicit(class Material)
+ IL_0031: brtrue IL_0051
+
+ IL_0036: ldarg.0
+ IL_0037: callvirt instance bool SequenceOfNestedIfs::CheckShader()
+ IL_003c: brtrue IL_0046
+
+ IL_0041: br IL_00a7
+
+ IL_0046: ldarg.0
+ IL_0047: newobj instance void Material::.ctor()
+ IL_004c: stfld class Material SequenceOfNestedIfs::_material
+ IL_0051: ldarg.0
+ IL_0052: ldfld class Material SequenceOfNestedIfs::_material
+ IL_0057: call bool Material::op_Implicit(class Material)
+ IL_005c: brtrue IL_007c
+
+ IL_0061: ldarg.0
+ IL_0062: callvirt instance bool SequenceOfNestedIfs::CheckShader()
+ IL_0067: brtrue IL_0071
+
+ IL_006c: br IL_00a7
+
+ IL_0071: ldarg.0
+ IL_0072: newobj instance void Material::.ctor()
+ IL_0077: stfld class Material SequenceOfNestedIfs::_material
+ IL_007c: ldarg.0
+ IL_007d: ldfld class Material SequenceOfNestedIfs::_material
+ IL_0082: call bool Material::op_Implicit(class Material)
+ IL_0087: brtrue IL_00a7
+
+ IL_008c: ldarg.0
+ IL_008d: callvirt instance bool SequenceOfNestedIfs::CheckShader()
+ IL_0092: brtrue IL_009c
+
+ IL_0097: br IL_00a7
+
+ IL_009c: ldarg.0
+ IL_009d: newobj instance void Material::.ctor()
+ IL_00a2: stfld class Material SequenceOfNestedIfs::_material
+ IL_00a7: ret
+ } // end of method SequenceOfNestedIfs::CreateMaterials
+
+} // end of class SequenceOfNestedIfs \ No newline at end of file
diff --git a/main/contrib/ICSharpCode.Decompiler/Tests/IL/StackTests.exe b/main/contrib/ICSharpCode.Decompiler/Tests/IL/StackTests.exe
new file mode 100644
index 0000000000..db6194ad68
--- /dev/null
+++ b/main/contrib/ICSharpCode.Decompiler/Tests/IL/StackTests.exe
Binary files differ
diff --git a/main/contrib/ICSharpCode.Decompiler/Tests/IL/StackTests.il b/main/contrib/ICSharpCode.Decompiler/Tests/IL/StackTests.il
new file mode 100644
index 0000000000..51cee37549
--- /dev/null
+++ b/main/contrib/ICSharpCode.Decompiler/Tests/IL/StackTests.il
@@ -0,0 +1,132 @@
+.assembly extern mscorlib
+{
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )
+ .ver 4:0:0:0
+}
+.assembly StackTests
+{
+ .hash algorithm 0x00008004
+ .ver 1:0:4059:39717
+}
+.module StackTests.exe
+.imagebase 0x00400000
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003 // WINDOWS_CUI
+.corflags 0x00000003 // ILONLY 32BITREQUIRED
+
+.class private auto ansi beforefieldinit StackTests.Program extends [mscorlib]System.Object
+{
+ .method public hidebysig static void Main(string[] args) cil managed
+ {
+ .entrypoint
+ .maxstack 8
+
+ ldc.i4.0
+ call string StackTests.Program::Test1(bool cond)
+ call void [mscorlib]System.Console::WriteLine(string) // false
+
+ ldc.i4.1
+ call string StackTests.Program::Test1(bool cond)
+ call void [mscorlib]System.Console::WriteLine(string) // true
+
+ ldc.i4.0
+ ldc.i4.0
+ ldc.i4.0
+ call int32 StackTests.Program::Test2(int32 switch1, int32 br1, int32 br2)
+ call void [mscorlib]System.Console::WriteLine(int32) // 11
+
+ ldc.i4.0
+ ldc.i4.1
+ ldc.i4.0
+ call int32 StackTests.Program::Test2(int32 switch1, int32 br1, int32 br2)
+ call void [mscorlib]System.Console::WriteLine(int32) // 21
+
+ ldc.i4.1
+ ldc.i4.1
+ ldc.i4.1
+ call int32 StackTests.Program::Test2(int32 switch1, int32 br1, int32 br2)
+ call void [mscorlib]System.Console::WriteLine(int32) // 32
+
+ ldc.i4.2
+ ldc.i4.1
+ ldc.i4.0
+ call int32 StackTests.Program::Test2(int32 switch1, int32 br1, int32 br2)
+ call void [mscorlib]System.Console::WriteLine(int32) // 23
+
+ ret
+ }
+
+ .method public hidebysig static string Test1(bool cond) cil managed
+ {
+ ldarg.0
+ brtrue TRUE
+
+ FALSE:
+ ldstr "false"
+ br EXIT
+
+ TRUE:
+ ldstr "true"
+
+ EXIT:
+ ret
+ }
+
+ .method public hidebysig static int32 Test2(int32 switch1, int32 br1, int32 br2) cil managed
+ {
+ ldarg.0
+ switch (ENTRY1, ENTRY2, ENTRY3)
+ ldc.i4.0
+ ret
+
+ ENTRY1:
+ ldc.i4.1
+ br BRANCH1
+
+ ENTRY2:
+ ldc.i4.2
+ br BRANCH1
+
+ ENTRY3:
+ ldc.i4.3
+ br BRANCH2
+
+ BRANCH1:
+ ldarg.1
+ brtrue BRANCH2
+
+ EXIT1:
+ ldc.i4 10
+ add
+ ret
+
+ BRANCH2:
+ ldarg.2
+ brtrue.s EXIT3
+
+ EXIT2:
+ ldc.i4 20
+ add
+ ret
+
+ EXIT3:
+ ldc.i4 30
+ add
+ ret
+ }
+
+ .method public hidebysig specialname rtspecialname
+ instance void .ctor() cil managed
+ {
+ // Code size 7 (0x7)
+ .maxstack 8
+ IL_0000: ldarg.0
+ IL_0001: call instance void [mscorlib]System.Object::.ctor()
+ IL_0006: ret
+ } // end of method Program::.ctor
+
+} // end of class StackTests.Program
+
+
+// =============================================================
diff --git a/main/contrib/ICSharpCode.Decompiler/Tests/LiftedOperators.cs b/main/contrib/ICSharpCode.Decompiler/Tests/LiftedOperators.cs
new file mode 100644
index 0000000000..426276ab0a
--- /dev/null
+++ b/main/contrib/ICSharpCode.Decompiler/Tests/LiftedOperators.cs
@@ -0,0 +1,830 @@
+// 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.
+
+using System;
+using System.Runtime.InteropServices;
+
+public static class LiftedOperators
+{
+ // C# uses 4 different patterns of IL for lifted operators: bool, other primitive types, decimal, other structs.
+ // Different patterns are used depending on whether both of the operands are nullable or only the left/right operand is nullable.
+ // Negation must not be pushed through such comparisons because it would change the semantics.
+ // A comparison used in a condition differs somewhat from a comparison used as a simple value.
+
+ public static void BoolBasic(bool? a, bool? b)
+ {
+ if (a == b)
+ {
+ Console.WriteLine();
+ }
+ if (a != b)
+ {
+ Console.WriteLine();
+ }
+
+ if (!(a == b))
+ {
+ Console.WriteLine();
+ }
+ if (!(a != b))
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void BoolComplex(bool? a, Func<bool> x)
+ {
+ if (a == x())
+ {
+ Console.WriteLine();
+ }
+ if (a != x())
+ {
+ Console.WriteLine();
+ }
+
+ if (x() == a)
+ {
+ Console.WriteLine();
+ }
+ if (x() != a)
+ {
+ Console.WriteLine();
+ }
+
+ if (!(a == x()))
+ {
+ Console.WriteLine();
+ }
+ if (!(a != x()))
+ {
+ Console.WriteLine();
+ }
+ if (!(x() == a))
+ {
+ Console.WriteLine();
+ }
+ if (!(x() != a))
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void BoolConst(bool? a)
+ {
+ if (a == true)
+ {
+ Console.WriteLine();
+ }
+ if (a != true)
+ {
+ Console.WriteLine();
+ }
+ if (a == false)
+ {
+ Console.WriteLine();
+ }
+ if (a != false)
+ {
+ Console.WriteLine();
+ }
+ if (a ?? true)
+ {
+ Console.WriteLine();
+ }
+ if (a ?? false)
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void BoolValueBasic(bool? a, bool? b)
+ {
+ Console.WriteLine(a == b);
+ Console.WriteLine(a != b);
+
+ Console.WriteLine(!(a == b));
+ Console.WriteLine(!(a != b));
+
+ Console.WriteLine(a & b);
+ Console.WriteLine(a | b);
+ Console.WriteLine(a ^ b);
+ Console.WriteLine(a ?? b);
+ Console.WriteLine(!a);
+ a &= b;
+ a |= b;
+ a ^= b;
+ }
+
+ public static void BoolValueComplex(bool? a, Func<bool> x)
+ {
+ Console.WriteLine(a == x());
+ Console.WriteLine(a != x());
+
+ Console.WriteLine(x() == a);
+ Console.WriteLine(x() != a);
+
+ Console.WriteLine(!(a == x()));
+ Console.WriteLine(!(a != x()));
+
+ Console.WriteLine(a & x());
+ Console.WriteLine(a | x());
+ Console.WriteLine(a ^ x());
+ Console.WriteLine(a ?? x());
+ a &= x();
+ a |= x();
+ a ^= x();
+
+ Console.WriteLine(x() ^ a);
+ (new bool?[0])[0] ^= x();
+ }
+
+ public static void BoolValueConst(bool? a)
+ {
+ Console.WriteLine(a == true);
+ Console.WriteLine(a != true);
+ Console.WriteLine(a == false);
+ Console.WriteLine(a != false);
+ Console.WriteLine(a ?? true);
+ Console.WriteLine(a ?? false);
+ }
+
+ public static void IntBasic(int? a, int? b)
+ {
+ if (a == b)
+ {
+ Console.WriteLine();
+ }
+ if (a != b)
+ {
+ Console.WriteLine();
+ }
+ if (a > b)
+ {
+ Console.WriteLine();
+ }
+ if (a < b)
+ {
+ Console.WriteLine();
+ }
+ if (a >= b)
+ {
+ Console.WriteLine();
+ }
+ if (a <= b)
+ {
+ Console.WriteLine();
+ }
+
+ if (!(a == b))
+ {
+ Console.WriteLine();
+ }
+ if (!(a != b))
+ {
+ Console.WriteLine();
+ }
+ if (!(a > b))
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void IntComplex(int? a, Func<int> x)
+ {
+ if (a == x())
+ {
+ Console.WriteLine();
+ }
+ if (a != x())
+ {
+ Console.WriteLine();
+ }
+ if (a > x())
+ {
+ Console.WriteLine();
+ }
+
+ if (x() == a)
+ {
+ Console.WriteLine();
+ }
+ if (x() != a)
+ {
+ Console.WriteLine();
+ }
+ if (x() > a)
+ {
+ Console.WriteLine();
+ }
+
+ if (!(a == x()))
+ {
+ Console.WriteLine();
+ }
+ if (!(a != x()))
+ {
+ Console.WriteLine();
+ }
+ if (!(a > x()))
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void IntConst(int? a)
+ {
+ if (a == 2)
+ {
+ Console.WriteLine();
+ }
+ if (a != 2)
+ {
+ Console.WriteLine();
+ }
+ if (a > 2)
+ {
+ Console.WriteLine();
+ }
+
+ if (2 == a)
+ {
+ Console.WriteLine();
+ }
+ if (2 != a)
+ {
+ Console.WriteLine();
+ }
+ if (2 > a)
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void IntValueBasic(int? a, int? b)
+ {
+ Console.WriteLine(a == b);
+ Console.WriteLine(a != b);
+ Console.WriteLine(a > b);
+
+ Console.WriteLine(!(a == b));
+ Console.WriteLine(!(a != b));
+ Console.WriteLine(!(a > b));
+
+ Console.WriteLine(a + b);
+ Console.WriteLine(a - b);
+ Console.WriteLine(a * b);
+ Console.WriteLine(a / b);
+ Console.WriteLine(a % b);
+ Console.WriteLine(a & b);
+ Console.WriteLine(a | b);
+ Console.WriteLine(a ^ b);
+ Console.WriteLine(a << b);
+ Console.WriteLine(a >> b);
+ Console.WriteLine(a ?? b);
+ Console.WriteLine(-a);
+ Console.WriteLine(~a);
+ // TODO:
+ //Console.WriteLine(a++);
+ //Console.WriteLine(a--);
+ Console.WriteLine(++a);
+ Console.WriteLine(--a);
+ a += b;
+ a -= b;
+ a *= b;
+ a /= b;
+ a %= b;
+ a &= b;
+ a |= b;
+ a ^= b;
+ a <<= b;
+ a >>= b;
+ }
+
+ public static void IntValueComplex(int? a, Func<int> x)
+ {
+ Console.WriteLine(a == x());
+ Console.WriteLine(a != x());
+ Console.WriteLine(a > x());
+
+ Console.WriteLine(x() == a);
+ Console.WriteLine(x() != a);
+ Console.WriteLine(x() > a);
+
+ Console.WriteLine(a + x());
+ Console.WriteLine(a - x());
+ Console.WriteLine(a * x());
+ Console.WriteLine(a / x());
+ Console.WriteLine(a % x());
+ Console.WriteLine(a & x());
+ Console.WriteLine(a | x());
+ Console.WriteLine(a ^ x());
+ Console.WriteLine(a << x());
+ Console.WriteLine(a >> x());
+ Console.WriteLine(a ?? x());
+ a += x();
+ a -= x();
+ a *= x();
+ a /= x();
+ a %= x();
+ a &= x();
+ a |= x();
+ a ^= x();
+ a <<= x();
+ a >>= x();
+
+ Console.WriteLine(x() + a);
+ (new int?[0])[0] += x();
+ }
+
+ public static void IntValueConst(int? a)
+ {
+ Console.WriteLine(a == 2);
+ Console.WriteLine(a != 2);
+ Console.WriteLine(a > 2);
+
+ Console.WriteLine(2 == a);
+ Console.WriteLine(2 != a);
+ Console.WriteLine(2 > a);
+
+ Console.WriteLine(a + 2);
+ Console.WriteLine(a - 2);
+ Console.WriteLine(a * 2);
+ Console.WriteLine(a / 2);
+ Console.WriteLine(a % 2);
+ Console.WriteLine(a & 2);
+ Console.WriteLine(a | 2);
+ Console.WriteLine(a ^ 2);
+ Console.WriteLine(a << 2);
+ Console.WriteLine(a >> 2);
+ Console.WriteLine(a ?? 2);
+ a += 2;
+ a -= 2;
+ a *= 2;
+ a /= 2;
+ a %= 2;
+ a &= 2;
+ a |= 2;
+ a ^= 2;
+ a <<= 2;
+ a >>= 2;
+
+ Console.WriteLine(2 + a);
+ }
+
+ public static void NumberBasic(decimal? a, decimal? b)
+ {
+ if (a == b)
+ {
+ Console.WriteLine();
+ }
+ if (a != b)
+ {
+ Console.WriteLine();
+ }
+ if (a > b)
+ {
+ Console.WriteLine();
+ }
+ if (a < b)
+ {
+ Console.WriteLine();
+ }
+ if (a >= b)
+ {
+ Console.WriteLine();
+ }
+ if (a <= b)
+ {
+ Console.WriteLine();
+ }
+
+ if (!(a == b))
+ {
+ Console.WriteLine();
+ }
+ if (!(a != b))
+ {
+ Console.WriteLine();
+ }
+ if (!(a > b))
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void NumberComplex(decimal? a, Func<decimal> x)
+ {
+ if (a == x())
+ {
+ Console.WriteLine();
+ }
+ if (a != x())
+ {
+ Console.WriteLine();
+ }
+ if (a > x())
+ {
+ Console.WriteLine();
+ }
+
+ if (x() == a)
+ {
+ Console.WriteLine();
+ }
+ if (x() != a)
+ {
+ Console.WriteLine();
+ }
+ if (x() > a)
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void NumberConst(decimal? a)
+ {
+ if (a == 2m)
+ {
+ Console.WriteLine();
+ }
+ if (a != 2m)
+ {
+ Console.WriteLine();
+ }
+ if (a > 2m)
+ {
+ Console.WriteLine();
+ }
+
+ if (2m == a)
+ {
+ Console.WriteLine();
+ }
+ if (2m != a)
+ {
+ Console.WriteLine();
+ }
+ if (2m > a)
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void NumberValueBasic(decimal? a, decimal? b)
+ {
+ Console.WriteLine(a == b);
+ Console.WriteLine(a != b);
+ Console.WriteLine(a > b);
+
+ Console.WriteLine(!(a == b));
+ Console.WriteLine(!(a != b));
+ Console.WriteLine(!(a > b));
+
+ Console.WriteLine(a + b);
+ Console.WriteLine(a - b);
+ Console.WriteLine(a * b);
+ Console.WriteLine(a / b);
+ Console.WriteLine(a % b);
+ Console.WriteLine(a ?? b);
+ Console.WriteLine(-a);
+ // TODO:
+ //Console.WriteLine(a++);
+ //Console.WriteLine(a--);
+ //Console.WriteLine(++a);
+ //Console.WriteLine(--a);
+ a += b;
+ a -= b;
+ a *= b;
+ a /= b;
+ a %= b;
+ }
+
+ public static void NumberValueComplex(decimal? a, Func<decimal> x)
+ {
+ Console.WriteLine(a == x());
+ Console.WriteLine(a != x());
+ Console.WriteLine(a > x());
+
+ Console.WriteLine(x() == a);
+ Console.WriteLine(x() != a);
+ Console.WriteLine(x() > a);
+
+ Console.WriteLine(a + x());
+ Console.WriteLine(a - x());
+ Console.WriteLine(a * x());
+ Console.WriteLine(a / x());
+ Console.WriteLine(a % x());
+ Console.WriteLine(a ?? x());
+ a += x();
+ a -= x();
+ a *= x();
+ a /= x();
+ a %= x();
+
+ Console.WriteLine(x() + a);
+ (new decimal?[0])[0] += x();
+ }
+
+ public static void NumberValueConst(decimal? a)
+ {
+ Console.WriteLine(a == 2m);
+ Console.WriteLine(a != 2m);
+ Console.WriteLine(a > 2m);
+
+ Console.WriteLine(2m == a);
+ Console.WriteLine(2m != a);
+ Console.WriteLine(2m > a);
+
+ Console.WriteLine(a + 2m);
+ Console.WriteLine(a - 2m);
+ Console.WriteLine(a * 2m);
+ Console.WriteLine(a / 2m);
+ Console.WriteLine(a % 2m);
+ Console.WriteLine(a ?? 2m);
+ a += 2m;
+ a -= 2m;
+ a *= 2m;
+ a /= 2m;
+ a %= 2m;
+
+ Console.WriteLine(2m + a);
+ }
+
+ public static void StructBasic(TS? a, TS? b)
+ {
+ if (a == b)
+ {
+ Console.WriteLine();
+ }
+ if (a != b)
+ {
+ Console.WriteLine();
+ }
+ if (a > b)
+ {
+ Console.WriteLine();
+ }
+ if (a < b)
+ {
+ Console.WriteLine();
+ }
+ if (a >= b)
+ {
+ Console.WriteLine();
+ }
+ if (a <= b)
+ {
+ Console.WriteLine();
+ }
+
+ if (!(a == b))
+ {
+ Console.WriteLine();
+ }
+ if (!(a != b))
+ {
+ Console.WriteLine();
+ }
+ if (!(a > b))
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void StructComplex(TS? a, Func<TS> x)
+ {
+ if (a == x())
+ {
+ Console.WriteLine();
+ }
+ if (a != x())
+ {
+ Console.WriteLine();
+ }
+ if (a > x())
+ {
+ Console.WriteLine();
+ }
+
+ if (x() == a)
+ {
+ Console.WriteLine();
+ }
+ if (x() != a)
+ {
+ Console.WriteLine();
+ }
+ if (x() > a)
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public static void StructValueBasic(TS? a, TS? b, int? i)
+ {
+ Console.WriteLine(a == b);
+ Console.WriteLine(a != b);
+ Console.WriteLine(a > b);
+
+ Console.WriteLine(!(a == b));
+ Console.WriteLine(!(a != b));
+ Console.WriteLine(!(a > b));
+
+ Console.WriteLine(a + b);
+ Console.WriteLine(a - b);
+ Console.WriteLine(a * b);
+ Console.WriteLine(a / b);
+ Console.WriteLine(a % b);
+ Console.WriteLine(a & b);
+ Console.WriteLine(a | b);
+ Console.WriteLine(a ^ b);
+ Console.WriteLine(a << i);
+ Console.WriteLine(a >> i);
+ Console.WriteLine(a ?? b);
+ Console.WriteLine(+a);
+ Console.WriteLine(-a);
+ Console.WriteLine(!a);
+ Console.WriteLine(~a);
+ // TODO:
+ //Console.WriteLine(a++);
+ //Console.WriteLine(a--);
+ //Console.WriteLine(++a);
+ //Console.WriteLine(--a);
+ //Console.WriteLine((int?)a);
+ a += b;
+ a -= b;
+ a *= b;
+ a /= b;
+ a %= b;
+ a &= b;
+ a |= b;
+ a ^= b;
+ a <<= i;
+ a >>= i;
+ }
+
+ public static void StructValueComplex(TS? a, Func<TS> x, Func<int> i)
+ {
+ Console.WriteLine(a == x());
+ Console.WriteLine(a != x());
+ Console.WriteLine(a > x());
+
+ Console.WriteLine(x() == a);
+ Console.WriteLine(x() != a);
+ Console.WriteLine(x() > a);
+
+ Console.WriteLine(a + x());
+ Console.WriteLine(a - x());
+ Console.WriteLine(a * x());
+ Console.WriteLine(a / x());
+ Console.WriteLine(a % x());
+ Console.WriteLine(a & x());
+ Console.WriteLine(a | x());
+ Console.WriteLine(a ^ x());
+ Console.WriteLine(a << i());
+ Console.WriteLine(a >> i());
+ Console.WriteLine(a ?? x());
+ a += x();
+ a -= x();
+ a *= x();
+ a /= x();
+ a %= x();
+ a &= x();
+ a |= x();
+ a ^= x();
+ a <<= i();
+ a >>= i();
+
+ Console.WriteLine(x() + a);
+ (new TS?[0])[0] += x();
+ }
+}
+
+// dummy structure for testing custom operators
+[StructLayout(LayoutKind.Sequential, Size = 1)]
+public struct TS
+{
+ // unary
+ public static TS operator +(TS a)
+ {
+ throw null;
+ }
+ public static TS operator -(TS a)
+ {
+ throw null;
+ }
+ public static TS operator !(TS a)
+ {
+ throw null;
+ }
+ public static TS operator ~(TS a)
+ {
+ throw null;
+ }
+ public static TS operator ++(TS a)
+ {
+ throw null;
+ }
+ public static TS operator --(TS a)
+ {
+ throw null;
+ }
+
+ public static explicit operator int(TS a)
+ {
+ throw null;
+ }
+
+ // binary
+ public static TS operator +(TS a, TS b)
+ {
+ throw null;
+ }
+ public static TS operator -(TS a, TS b)
+ {
+ throw null;
+ }
+ public static TS operator *(TS a, TS b)
+ {
+ throw null;
+ }
+ public static TS operator /(TS a, TS b)
+ {
+ throw null;
+ }
+ public static TS operator %(TS a, TS b)
+ {
+ throw null;
+ }
+ public static TS operator &(TS a, TS b)
+ {
+ throw null;
+ }
+ public static TS operator |(TS a, TS b)
+ {
+ throw null;
+ }
+ public static TS operator ^(TS a, TS b)
+ {
+ throw null;
+ }
+ public static TS operator <<(TS a, int b)
+ {
+ throw null;
+ }
+ public static TS operator >>(TS a, int b)
+ {
+ throw null;
+ }
+
+ // comparisons
+ public static bool operator ==(TS a, TS b)
+ {
+ throw null;
+ }
+ public static bool operator !=(TS a, TS b)
+ {
+ throw null;
+ }
+ public static bool operator <(TS a, TS b)
+ {
+ throw null;
+ }
+ public static bool operator <=(TS a, TS b)
+ {
+ throw null;
+ }
+ public static bool operator >(TS a, TS b)
+ {
+ throw null;
+ }
+ public static bool operator >=(TS a, TS b)
+ {
+ throw null;
+ }
+
+ public override bool Equals(object obj)
+ {
+ throw null;
+ }
+ public override int GetHashCode()
+ {
+ throw null;
+ }
+}
diff --git a/main/contrib/ICSharpCode.Decompiler/Tests/Lock.cs b/main/contrib/ICSharpCode.Decompiler/Tests/Lock.cs
new file mode 100644
index 0000000000..da5a59c74f
--- /dev/null
+++ b/main/contrib/ICSharpCode.Decompiler/Tests/Lock.cs
@@ -0,0 +1,38 @@
+// 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.
+
+using System;
+
+public class Lock
+{
+ public void LockThis()
+ {
+ lock (this)
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public void LockOnType()
+ {
+ lock (typeof(Lock))
+ {
+ Console.WriteLine();
+ }
+ }
+}
diff --git a/main/contrib/ICSharpCode.Decompiler/Tests/PInvoke.cs b/main/contrib/ICSharpCode.Decompiler/Tests/PInvoke.cs
new file mode 100644
index 0000000000..0c828ac696
--- /dev/null
+++ b/main/contrib/ICSharpCode.Decompiler/Tests/PInvoke.cs
@@ -0,0 +1,96 @@
+// 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.Runtime.InteropServices;
+
+// P/Invoke and marshalling attribute tests
+public class PInvoke
+{
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 2)]
+ public struct MarshalAsTest
+ {
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+ public uint[] FixedArray;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.Bool)]
+ public int[] FixedBoolArray;
+
+ [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
+ public string[] SafeBStrArray;
+
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
+ public string FixedString;
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ public struct Rect
+ {
+ [FieldOffset(0)]
+ public int left;
+ [FieldOffset(4)]
+ public int top;
+ [FieldOffset(8)]
+ public int right;
+ [FieldOffset(12)]
+ public int bottom;
+ }
+
+ public static decimal MarshalAttributesOnPropertyAccessors
+ {
+ [return: MarshalAs(UnmanagedType.Currency)]
+ get
+ {
+ return 0m;
+ }
+ [param: MarshalAs(UnmanagedType.Currency)]
+ set
+ {
+ }
+ }
+
+ [DllImport("xyz.dll", CharSet = CharSet.Auto)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool Method([MarshalAs(UnmanagedType.LPStr)] string input);
+
+ [DllImport("xyz.dll")]
+ private static extern void New1(int ElemCnt, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] int[] ar);
+
+ [DllImport("xyz.dll")]
+ private static extern void New2([MarshalAs(UnmanagedType.LPArray, SizeConst = 128)] int[] ar);
+
+ [DllImport("xyz.dll")]
+ private static extern void New3([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Bool, SizeConst = 64, SizeParamIndex = 1)] int[] ar);
+
+ public void CustomMarshal1([MarshalAs(UnmanagedType.CustomMarshaler, MarshalType = "MyCompany.MyMarshaler")] object o)
+ {
+ }
+
+ public void CustomMarshal2([MarshalAs(UnmanagedType.CustomMarshaler, MarshalType = "MyCompany.MyMarshaler", MarshalCookie = "Cookie")] object o)
+ {
+ }
+
+ [DllImport("ws2_32.dll", SetLastError = true)]
+ internal static extern IntPtr ioctlsocket([In] IntPtr socketHandle, [In] int cmd, [In] [Out] ref int argp);
+
+ public void CallMethodWithInOutParameter()
+ {
+ int num = 0;
+ PInvoke.ioctlsocket(IntPtr.Zero, 0, ref num);
+ }
+}
diff --git a/main/contrib/ICSharpCode.Decompiler/Tests/QueryExpressions.cs b/main/contrib/ICSharpCode.Decompiler/Tests/QueryExpressions.cs
new file mode 100644
index 0000000000..d8b6e06234
--- /dev/null
+++ b/main/contrib/ICSharpCode.Decompiler/Tests/QueryExpressions.cs
@@ -0,0 +1,188 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+public class QueryExpressions
+{
+ public class Customer
+ {
+ public int CustomerID;
+ public IEnumerable<QueryExpressions.Order> Orders;
+ public string Name;
+ public string Country;
+ public string City;
+ }
+
+ public class Order
+ {
+ public int OrderID;
+ public DateTime OrderDate;
+ public QueryExpressions.Customer Customer;
+ public int CustomerID;
+ public decimal Total;
+ public IEnumerable<QueryExpressions.OrderDetail> Details;
+ }
+
+ public class OrderDetail
+ {
+ public decimal UnitPrice;
+ public int Quantity;
+ }
+
+ public IEnumerable<QueryExpressions.Customer> customers;
+ public IEnumerable<QueryExpressions.Order> orders;
+
+ public object MultipleWhere()
+ {
+ return from c in this.customers
+ where c.Orders.Count<QueryExpressions.Order>() > 10
+ where c.Country == "DE"
+ select c;
+ }
+
+ public object SelectManyFollowedBySelect()
+ {
+ return from c in this.customers
+ from o in c.Orders
+ select new
+ {
+ c.Name,
+ o.OrderID,
+ o.Total
+ };
+ }
+
+ public object SelectManyFollowedByOrderBy()
+ {
+ return from c in this.customers
+ from o in c.Orders
+ orderby o.Total descending
+ select new
+ {
+ c.Name,
+ o.OrderID,
+ o.Total
+ };
+ }
+
+ public object MultipleSelectManyFollowedBySelect()
+ {
+ return from c in this.customers
+ from o in c.Orders
+ from d in o.Details
+ select new
+ {
+ c.Name,
+ o.OrderID,
+ d.Quantity
+ };
+ }
+
+ public object MultipleSelectManyFollowedByLet()
+ {
+ return from c in this.customers
+ from o in c.Orders
+ from d in o.Details
+ let x = d.Quantity * d.UnitPrice
+ select new
+ {
+ c.Name,
+ o.OrderID,
+ x
+ };
+ }
+
+ public object FromLetWhereSelect()
+ {
+ return from o in this.orders
+ let t = o.Details.Sum((QueryExpressions.OrderDetail d) => d.UnitPrice * d.Quantity)
+ where t >= 1000m
+ select new
+ {
+ OrderID = o.OrderID,
+ Total = t
+ };
+ }
+
+ public object MultipleLet()
+ {
+ return from a in this.customers
+ let b = a.Country
+ let c = a.Name
+ select b + c;
+ }
+
+ public object Join()
+ {
+ return from c in this.customers
+ join o in this.orders on c.CustomerID equals o.CustomerID
+ select new
+ {
+ c.Name,
+ o.OrderDate,
+ o.Total
+ };
+ }
+
+ public object JoinInto()
+ {
+ return from c in this.customers
+ join o in this.orders on c.CustomerID equals o.CustomerID into co
+ let n = co.Count<QueryExpressions.Order>()
+ where n >= 10
+ select new
+ {
+ Name = c.Name,
+ OrderCount = n
+ };
+ }
+
+ public object OrderBy()
+ {
+ return from o in this.orders
+ orderby o.Customer.Name, o.Total descending
+ select o;
+ }
+
+ public object GroupBy()
+ {
+ return from c in this.customers
+ group c.Name by c.Country;
+ }
+
+ public object ExplicitType()
+ {
+ return from QueryExpressions.Customer c in this.customers
+ where c.City == "London"
+ select c;
+ }
+
+ public object QueryContinuation()
+ {
+ return from c in this.customers
+ group c by c.Country into g
+ select new
+ {
+ Country = g.Key,
+ CustCount = g.Count<QueryExpressions.Customer>()
+ };
+ }
+}
diff --git a/main/contrib/ICSharpCode.Decompiler/Tests/TestRunner.cs b/main/contrib/ICSharpCode.Decompiler/Tests/TestRunner.cs
index 009a3c6c17..215725b0a6 100644
--- a/main/contrib/ICSharpCode.Decompiler/Tests/TestRunner.cs
+++ b/main/contrib/ICSharpCode.Decompiler/Tests/TestRunner.cs
@@ -32,7 +32,7 @@ using NUnit.Framework;
namespace ICSharpCode.Decompiler.Tests
{
[TestFixture]
- public class TestRunner
+ public class TestRunner : DecompilerTestBase
{
[Test]
public void Async()
@@ -67,7 +67,8 @@ namespace ICSharpCode.Decompiler.Tests
[Test]
public void ExceptionHandling()
{
- TestFile(@"..\..\Tests\ExceptionHandling.cs", optimize: false);
+ AssertRoundtripCode(@"..\..\Tests\ExceptionHandling.cs", optimize: false);
+ AssertRoundtripCode(@"..\..\Tests\ExceptionHandling.cs", optimize: false);
}
[Test]
@@ -85,7 +86,14 @@ namespace ICSharpCode.Decompiler.Tests
[Test]
public void ControlFlowWithDebug()
{
- TestFile(@"..\..\Tests\ControlFlow.cs", optimize: false, useDebug: true);
+ AssertRoundtripCode(@"..\..\Tests\ControlFlow.cs", optimize: false, useDebug: true);
+ AssertRoundtripCode(@"..\..\Tests\ControlFlow.cs", optimize: false, useDebug: true);
+ }
+
+ [Test]
+ public void DoubleConstants()
+ {
+ TestFile(@"..\..\Tests\DoubleConstants.cs");
}
[Test]
@@ -107,6 +115,13 @@ namespace ICSharpCode.Decompiler.Tests
}
[Test]
+ public void Lock()
+ {
+ //TestFile(@"..\..\Tests\Lock.cs", compilerVersion: 2);
+ TestFile(@"..\..\Tests\Lock.cs", compilerVersion: 4);
+ }
+
+ [Test]
public void Loops()
{
TestFile(@"..\..\Tests\Loops.cs");
@@ -172,44 +187,12 @@ namespace ICSharpCode.Decompiler.Tests
TestFile(@"..\..\Tests\TypeAnalysisTests.cs");
}
- static void TestFile(string fileName, bool useDebug = false)
- {
- TestFile(fileName, false, useDebug);
- TestFile(fileName, true, useDebug);
- }
-
- static void TestFile(string fileName, bool optimize, bool useDebug = false)
+ static void TestFile(string fileName, bool useDebug = false, int compilerVersion = 4)
{
- string code = File.ReadAllText(fileName);
- AssemblyDefinition assembly = Compile(code, optimize, useDebug);
- AstBuilder decompiler = new AstBuilder(new DecompilerContext(assembly.MainModule));
- decompiler.AddAssembly(assembly);
- new Helpers.RemoveCompilerAttribute().Run(decompiler.SyntaxTree);
- StringWriter output = new StringWriter();
- decompiler.GenerateCode(new PlainTextOutput(output));
- CodeAssert.AreEqual(code, output.ToString());
- }
-
- static AssemblyDefinition Compile(string code, bool optimize, bool useDebug)
- {
- CSharpCodeProvider provider = new CSharpCodeProvider(new Dictionary<string, string> { { "CompilerVersion", "v4.0" } });
- CompilerParameters options = new CompilerParameters();
- options.CompilerOptions = "/unsafe /o" + (optimize ? "+" : "-") + (useDebug ? " /debug": "");
- options.ReferencedAssemblies.Add("System.Core.dll");
- CompilerResults results = provider.CompileAssemblyFromSource(options, code);
- try {
- if (results.Errors.Count > 0) {
- StringBuilder b = new StringBuilder("Compiler error:");
- foreach (var error in results.Errors) {
- b.AppendLine(error.ToString());
- }
- throw new Exception(b.ToString());
- }
- return AssemblyDefinition.ReadAssembly(results.PathToAssembly);
- } finally {
- File.Delete(results.PathToAssembly);
- results.TempFiles.Delete();
- }
+ AssertRoundtripCode(fileName, optimize: false, useDebug: useDebug, compilerVersion: compilerVersion);
+ AssertRoundtripCode(fileName, optimize: true, useDebug: useDebug, compilerVersion: compilerVersion);
+ AssertRoundtripCode(fileName, optimize: false, useDebug: useDebug, compilerVersion: compilerVersion);
+ AssertRoundtripCode(fileName, optimize: true, useDebug: useDebug, compilerVersion: compilerVersion);
}
}
}
diff --git a/main/contrib/ICSharpCode.Decompiler/Tests/TypeAnalysisTests.cs b/main/contrib/ICSharpCode.Decompiler/Tests/TypeAnalysisTests.cs
new file mode 100644
index 0000000000..760bb862d3
--- /dev/null
+++ b/main/contrib/ICSharpCode.Decompiler/Tests/TypeAnalysisTests.cs
@@ -0,0 +1,153 @@
+// 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.
+
+using System;
+
+public class TypeAnalysisTests
+{
+ public byte SubtractFrom256(byte b)
+ {
+ return (byte)(256 - (int)b);
+ }
+
+ #region Shift
+ public int LShiftInteger(int num1, int num2)
+ {
+ return num1 << num2;
+ }
+
+ public uint LShiftUnsignedInteger(uint num1, uint num2)
+ {
+ return num1 << (int)num2;
+ }
+
+ public long LShiftLong(long num1, long num2)
+ {
+ return num1 << (int)num2;
+ }
+
+ public ulong LShiftUnsignedLong(ulong num1, ulong num2)
+ {
+ return num1 << (int)num2;
+ }
+
+ public int RShiftInteger(int num1, int num2)
+ {
+ return num1 >> num2;
+ }
+
+ public uint RShiftUnsignedInteger(uint num1, int num2)
+ {
+ return num1 >> num2;
+ }
+
+ public long RShiftLong(long num1, long num2)
+ {
+ return num1 >> (int)num2;
+ }
+
+ public ulong RShiftUnsignedLong(ulong num1, ulong num2)
+ {
+ return num1 >> (int)num2;
+ }
+
+ public int ShiftByte(byte num)
+ {
+ return (int)num << 8;
+ }
+
+ public int RShiftByte(byte num)
+ {
+ return num >> 8;
+ }
+
+ public uint RShiftByteWithZeroExtension(byte num)
+ {
+ return (uint)num >> 8;
+ }
+
+ public int RShiftByteAsSByte(byte num)
+ {
+ return (sbyte)num >> 8;
+ }
+
+ public int RShiftSByte(sbyte num)
+ {
+ return num >> 8;
+ }
+
+ public uint RShiftSByteWithZeroExtension(sbyte num)
+ {
+ return (uint)num >> 8;
+ }
+
+ public int RShiftSByteAsByte(sbyte num)
+ {
+ return (byte)num >> 8;
+ }
+ #endregion
+
+ public int GetHashCode(long num)
+ {
+ return (int)num ^ (int)(num >> 32);
+ }
+
+ public void TernaryOp(Random a, Random b, bool c)
+ {
+ if ((c ? a : b) == null)
+ {
+ Console.WriteLine();
+ }
+ }
+
+ public void OperatorIs(object o)
+ {
+ Console.WriteLine(o is Random);
+ Console.WriteLine(!(o is Random));
+ }
+
+ public byte[] CreateArrayWithInt(int length)
+ {
+ return new byte[length];
+ }
+
+ public byte[] CreateArrayWithLong(long length)
+ {
+ return new byte[length];
+ }
+
+ public byte[] CreateArrayWithUInt(uint length)
+ {
+ return new byte[length];
+ }
+
+ public byte[] CreateArrayWithULong(ulong length)
+ {
+ return new byte[length];
+ }
+
+ public StringComparison EnumDiffNumber(StringComparison data)
+ {
+ return data - 1;
+ }
+
+ public int EnumDiff(StringComparison a, StringComparison b)
+ {
+ return Math.Abs(a - b);
+ }
+}
diff --git a/main/contrib/ICSharpCode.Decompiler/Tests/Types/S_TypeDeclarations.cs b/main/contrib/ICSharpCode.Decompiler/Tests/Types/S_TypeDeclarations.cs
new file mode 100644
index 0000000000..99bf4279e3
--- /dev/null
+++ b/main/contrib/ICSharpCode.Decompiler/Tests/Types/S_TypeDeclarations.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace ClassMultiInterface
+{
+ public interface IA
+ {
+ }
+ public interface IA2 : IA
+ {
+ }
+ public interface IB
+ {
+ }
+ public class C : IA2, IB
+ {
+ }
+}
diff --git a/main/contrib/ICSharpCode.Decompiler/Tests/Types/S_TypeMemberDeclarations.cs b/main/contrib/ICSharpCode.Decompiler/Tests/Types/S_TypeMemberDeclarations.cs
index 72db7aa465..4a85b9f88a 100644
--- a/main/contrib/ICSharpCode.Decompiler/Tests/Types/S_TypeMemberDeclarations.cs
+++ b/main/contrib/ICSharpCode.Decompiler/Tests/Types/S_TypeMemberDeclarations.cs
@@ -679,7 +679,9 @@ namespace HideMembers3
}
public class J2 : J
{
+#pragma warning disable 0108 // Deliberate bad code for test case
public int get_P;
+#pragma warning restore 0108
}
}
//$$ HideMembers4
diff --git a/main/contrib/ICSharpCode.Decompiler/Tests/UndocumentedExpressions.cs b/main/contrib/ICSharpCode.Decompiler/Tests/UndocumentedExpressions.cs
new file mode 100644
index 0000000000..80f5b0371e
--- /dev/null
+++ b/main/contrib/ICSharpCode.Decompiler/Tests/UndocumentedExpressions.cs
@@ -0,0 +1,41 @@
+// 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.
+
+using System;
+
+public class UndocumentedExpressions
+{
+ public static int GetArgCount(__arglist)
+ {
+ ArgIterator argIterator = new ArgIterator(__arglist);
+ return argIterator.GetRemainingCount();
+ }
+
+ public static void MakeTypedRef(object o)
+ {
+ TypedReference tr = __makeref(o);
+ UndocumentedExpressions.AcceptTypedRef(tr);
+ }
+
+ private static void AcceptTypedRef(TypedReference tr)
+ {
+ Console.WriteLine("Value is: " + __refvalue(tr, object).ToString());
+ Console.WriteLine("Type is: " + __reftype(tr).Name);
+ __refvalue(tr, object) = 1;
+ }
+}
diff --git a/main/contrib/ICSharpCode.Decompiler/Tests/UnsafeCode.cs b/main/contrib/ICSharpCode.Decompiler/Tests/UnsafeCode.cs
index 66fb29529b..cce6d525c7 100644
--- a/main/contrib/ICSharpCode.Decompiler/Tests/UnsafeCode.cs
+++ b/main/contrib/ICSharpCode.Decompiler/Tests/UnsafeCode.cs
@@ -122,7 +122,47 @@ public class UnsafeCode
}
return this.PointerReferenceExpression((double*)ptr);
}
-
+
+ public unsafe int* PointerArithmetic(int* p)
+ {
+ return p + 2;
+ }
+
+ public unsafe byte* PointerArithmetic2(long* p, int y, int x)
+ {
+ return (byte*)((short*)p + (y * x));
+ }
+
+ public unsafe long* PointerArithmetic3(long* p)
+ {
+ return (long*)((byte*)p + 3);
+ }
+
+ public unsafe long* PointerArithmetic4(void* p)
+ {
+ return (long*)((byte*)p + 3);
+ }
+
+ public unsafe int PointerArithmetic5(void* p, byte* q, int i)
+ {
+ return (int)(q[i] + *(byte*)p);
+ }
+
+ public unsafe int PointerSubtraction(long* p, long* q)
+ {
+ return (int)((long)(p - q));
+ }
+
+ public unsafe int PointerSubtraction2(long* p, short* q)
+ {
+ return (int)((long)((byte*)p - (byte*)q));
+ }
+
+ public unsafe int PointerSubtraction3(void* p, void* q)
+ {
+ return (int)((long)((byte*)p - (byte*)q));
+ }
+
unsafe ~UnsafeCode()
{
this.PassPointerAsRefParameter(this.NullPointer);
diff --git a/main/contrib/ICSharpCode.Decompiler/Tests/ValueTypes.cs b/main/contrib/ICSharpCode.Decompiler/Tests/ValueTypes.cs
index b3aa644786..1493cff4c9 100644
--- a/main/contrib/ICSharpCode.Decompiler/Tests/ValueTypes.cs
+++ b/main/contrib/ICSharpCode.Decompiler/Tests/ValueTypes.cs
@@ -168,4 +168,21 @@ public static class ValueTypes
Console.WriteLine("true");
}
}
+
+ public static void CompareNotEqual0IsReallyNotEqual(IComparable<int> a)
+ {
+ if (a.CompareTo(0) != 0)
+ {
+ Console.WriteLine("true");
+ }
+ }
+
+ public static void CompareEqual0IsReallyEqual(IComparable<int> a)
+ {
+ if (a.CompareTo(0) == 0)
+ {
+ Console.WriteLine("true");
+ }
+ }
+
}
diff --git a/main/external/debugger-libs b/main/external/debugger-libs
-Subproject 79eb08b19d3abeb32f9a8305ea9f36db19701ca
+Subproject 50a2141178cf001ab6c4bb6de0913d71ab2bcb2
diff --git a/main/external/fsharpbinding b/main/external/fsharpbinding
-Subproject 096c6d5c045c3c4dfcb92aac9751e9c78520e74
+Subproject 87e3e3562d57c97b127e7c6afb7144b1f7873fb
diff --git a/main/external/libgit-binary b/main/external/libgit-binary
-Subproject ba9f025efbcf2ed4afeccf8ae48f1d5b07b8ca3
+Subproject 944fba6f5eb9636542e824b6fd95c294d91e97a
diff --git a/main/external/libgit2 b/main/external/libgit2
-Subproject 3d5286e151cecad8092060cdca0335031f9cda7
+Subproject e8b8948f5a07cd813ccad7b97490b7f040d364c
diff --git a/main/external/libgit2sharp b/main/external/libgit2sharp
-Subproject 2733f93dcd7376f3c83ed7e9cd97a324386be76
+Subproject 06bbc96251eea534ed66a32e8f2e2edaaa90307
diff --git a/main/external/mono-addins b/main/external/mono-addins
-Subproject e22febe3c4b0f448ec0aef90c63d92cdae4dcb4
+Subproject 60d87622dc6fe6b30913a1730f2f0c205363f2b
diff --git a/main/external/monomac b/main/external/monomac
-Subproject 36508cffdd4ce29f6c6e87f7c30d621d3cc512f
+Subproject 1d878426361aea31f9e31b509783703fbd797c8
diff --git a/main/external/nrefactory b/main/external/nrefactory
-Subproject 0d2152fb88aba005f0c9313365a129c2fa6873a
+Subproject ab1ad3cae23c657763c7e047531ee40de56d741
diff --git a/main/external/nuget-binary b/main/external/nuget-binary
-Subproject da1f2102f8172df6f7a1370a4998e3f88b91c04
+Subproject 4612ea9166f27f5193b4abb3c0825e52df08eb8
diff --git a/main/external/xwt b/main/external/xwt
-Subproject a9014f461e23d27e393b9d89180b2ade92e0b16
+Subproject 35e67b8f13309c213edebac9914830284134787
diff --git a/main/src/addins/AspNet/Tests/MonoDevelop.AspNet.Tests.csproj b/main/src/addins/AspNet/Tests/MonoDevelop.AspNet.Tests.csproj
index cdde498cdf..32b81dba69 100644
--- a/main/src/addins/AspNet/Tests/MonoDevelop.AspNet.Tests.csproj
+++ b/main/src/addins/AspNet/Tests/MonoDevelop.AspNet.Tests.csproj
@@ -55,6 +55,7 @@
<Compile Include="Razor\RazorCompletionTests.cs" />
<Compile Include="Html\HtmlParsingTests.cs" />
<Compile Include="Html\HtmlImplicitClosingTests.cs" />
+ <Compile Include="WebForms\WebFormsSyntaxModeTests.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
diff --git a/main/src/addins/AspNet/Tests/WebForms/WebFormsSyntaxModeTests.cs b/main/src/addins/AspNet/Tests/WebForms/WebFormsSyntaxModeTests.cs
new file mode 100644
index 0000000000..3018f97c46
--- /dev/null
+++ b/main/src/addins/AspNet/Tests/WebForms/WebFormsSyntaxModeTests.cs
@@ -0,0 +1,66 @@
+//
+// WebFormsSyntaxModeTests.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2015 Xamarin Inc. (http://xamarin.com)
+//
+// 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.Linq;
+using NUnit.Framework;
+using Mono.TextEditor;
+using Mono.TextEditor.Highlighting;
+using MonoDevelop.AspNet.WebForms;
+
+namespace MonoDevelop.AspNet.Tests.WebForms
+{
+ [TestFixture]
+ class WebFormsSyntaxModeTests
+ {
+ [Test]
+ public void InvalidMimeTypeInScriptTypeAttribute ()
+ {
+ var doc = new TextDocument ();
+ var syntaxMode = new WebFormsSyntaxMode ();
+ syntaxMode.Document = doc;
+ doc.Text =
+@"<%@ Page Language=""C#"" Inherits=""AspnetTest.Default"" %>
+<!DOCTYPE html>
+<html>
+<head runat=""server"">
+ <title>Default</title>
+</head>
+<body>
+ <form id=""form1"" runat=""server"">
+ <asp:Button id=""button1"" runat=""server"" Text=""Click me!"" OnClick=""button1Clicked"" />
+ </form>
+ <script type=""></script>
+</body>
+</html>
+";
+ var style = new ColorScheme ();
+ foreach (DocumentLine line in doc.Lines) {
+ Assert.DoesNotThrow (() => syntaxMode.GetChunks (style, line, line.Offset, line.Length).ToList ());
+ }
+ }
+ }
+}
+
diff --git a/main/src/addins/AspNet/WebForms/WebFormsSyntaxMode.cs b/main/src/addins/AspNet/WebForms/WebFormsSyntaxMode.cs
index fb7261cf2a..44942b8354 100644
--- a/main/src/addins/AspNet/WebForms/WebFormsSyntaxMode.cs
+++ b/main/src/addins/AspNet/WebForms/WebFormsSyntaxMode.cs
@@ -24,9 +24,11 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using MonoDevelop.Core;
using Mono.TextEditor;
using Mono.TextEditor.Highlighting;
using MonoDevelop.AspNet.WebForms.Parser;
@@ -174,8 +176,12 @@ namespace MonoDevelop.AspNet.WebForms
if (mime != null) {
CodeDeclarationSpan span = new CodeDeclarationSpan (mime);
- FoundSpanBegin (span, i, 0);
- return true;
+ try {
+ FoundSpanBegin (span, i, 0);
+ return true;
+ } catch (Exception ex) {
+ LoggingService.LogInternalError (ex);
+ }
}
}
}
diff --git a/main/src/addins/CBinding/CBinding.Autotools/CBinding.Autotools.csproj b/main/src/addins/CBinding/CBinding.Autotools/CBinding.Autotools.csproj
index 9a1b28c5ed..5cb50bacca 100644
--- a/main/src/addins/CBinding/CBinding.Autotools/CBinding.Autotools.csproj
+++ b/main/src/addins/CBinding/CBinding.Autotools/CBinding.Autotools.csproj
@@ -14,7 +14,7 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>True</DebugSymbols>
<DebugType>full</DebugType>
- <Optimize>True</Optimize>
+ <Optimize>false</Optimize>
<OutputPath>..\..\..\..\build\AddIns\BackendBindings\</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
diff --git a/main/src/addins/CBinding/Gui/GeneralOptionsPanel.cs b/main/src/addins/CBinding/Gui/GeneralOptionsPanel.cs
index 1b8fa5ed30..f230d78fb2 100644
--- a/main/src/addins/CBinding/Gui/GeneralOptionsPanel.cs
+++ b/main/src/addins/CBinding/Gui/GeneralOptionsPanel.cs
@@ -36,6 +36,7 @@ using Mono.Addins;
using MonoDevelop.Core;
using MonoDevelop.Ide.Gui.Dialogs;
+using MonoDevelop.Components.Extensions;
namespace CBinding
{
@@ -173,7 +174,7 @@ namespace CBinding
protected virtual void OnCtagsBrowseClicked (object sender, System.EventArgs e)
{
- OpenFileDialog dialog = new OpenFileDialog (GettextCatalog.GetString ("Choose ctags executable"), Gtk.FileChooserAction.Open);
+ OpenFileDialog dialog = new OpenFileDialog (GettextCatalog.GetString ("Choose ctags executable"), SelectFileDialogAction.Open);
if (dialog.Run ())
ctagsEntry.Text = dialog.SelectedFile;
}
diff --git a/main/src/addins/CSharpBinding/AddinInfo.cs b/main/src/addins/CSharpBinding/AddinInfo.cs
index 2b9deee4f4..90e1d63e5c 100644
--- a/main/src/addins/CSharpBinding/AddinInfo.cs
+++ b/main/src/addins/CSharpBinding/AddinInfo.cs
@@ -15,6 +15,7 @@ using Mono.Addins.Description;
[assembly:AddinDependency ("Ide", MonoDevelop.BuildInfo.Version)]
[assembly:AddinDependency ("Refactoring", MonoDevelop.BuildInfo.Version)]
[assembly:AddinDependency ("SourceEditor2", MonoDevelop.BuildInfo.Version)]
+[assembly:AddinDependency ("NUnit", MonoDevelop.BuildInfo.Version)]
// Submodules
[assembly:AddinModule ("MonoDevelop.CSharpBinding.Autotools.dll")]
diff --git a/main/src/addins/CSharpBinding/Autotools/Autotools.csproj b/main/src/addins/CSharpBinding/Autotools/Autotools.csproj
index 5bcda79d90..c6e075378a 100644
--- a/main/src/addins/CSharpBinding/Autotools/Autotools.csproj
+++ b/main/src/addins/CSharpBinding/Autotools/Autotools.csproj
@@ -37,8 +37,8 @@
<Execution clr-version="Net_2_0" />
</Execution>
<DebugSymbols>true</DebugSymbols>
- <DefineConstants>1591</DefineConstants>
<DocumentationFile>..\..\..\..\build\AddIns\BackendBindings\MonoDevelop.CSharpBinding.Autotools.xml</DocumentationFile>
+ <NoWarn>1591;1573</NoWarn>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\MonoDevelop.Autotools\MonoDevelop.Autotools.csproj">
diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/MemberCompletionData.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/MemberCompletionData.cs
index ab85e91705..b5d11b0e20 100644
--- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/MemberCompletionData.cs
+++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Completion/MemberCompletionData.cs
@@ -387,7 +387,7 @@ namespace MonoDevelop.CSharp.Completion
var ctx = editorCompletion.CSharpUnresolvedFile.GetTypeResolveContext (editorCompletion.UnresolvedFileCompilation, editorCompletion.Document.Editor.Caret.Location) as CSharpTypeResolveContext;
var state = new CSharpResolver (ctx);
var builder = new TypeSystemAstBuilder (state);
- builder.AddAnnotations = true;
+ builder.AddTypeReferenceAnnotations = true;
var dt = state.CurrentTypeDefinition;
var declaring = ctx.CurrentTypeDefinition != null ? ctx.CurrentTypeDefinition.DeclaringTypeDefinition : null;
if (declaring != null) {
diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring.CodeActions/MDRefactoringScript.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring.CodeActions/MDRefactoringScript.cs
index aa6e7a7ce4..008f06c026 100644
--- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring.CodeActions/MDRefactoringScript.cs
+++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Refactoring.CodeActions/MDRefactoringScript.cs
@@ -162,7 +162,7 @@ namespace MonoDevelop.CSharp.Refactoring.CodeActions
var tcs = new TaskCompletionSource<Script>();
if (parentType == null)
return tcs.Task;
- var part = parentType.Parts.FirstOrDefault ();
+ var part = MonoDevelop.Ide.TypeSystem.CodeGenerationService.FindCurrentPart(parentType);
if (part == null)
return tcs.Task;
diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Resolver/TextEditorResolverProvider.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Resolver/TextEditorResolverProvider.cs
index c17bb0fd7b..1f73971a9f 100644
--- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Resolver/TextEditorResolverProvider.cs
+++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.Resolver/TextEditorResolverProvider.cs
@@ -193,7 +193,7 @@ namespace MonoDevelop.CSharp.Resolver
var ctx = doc.ParsedDocument.ParsedFile as CSharpUnresolvedFile;
var state = ctx.GetResolver (doc.Compilation, doc.Editor.OffsetToLocation (offset));
var builder = new TypeSystemAstBuilder (state);
- builder.AddAnnotations = true;
+ builder.AddTypeReferenceAnnotations = true;
var dt = state.CurrentTypeDefinition;
var declaring = dt != null ? dt.DeclaringTypeDefinition : null;
if (declaring != null) {
diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp/PathedDocumentTextEditorExtension.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp/PathedDocumentTextEditorExtension.cs
index d24dc6fb75..02065b26d9 100644
--- a/main/src/addins/CSharpBinding/MonoDevelop.CSharp/PathedDocumentTextEditorExtension.cs
+++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp/PathedDocumentTextEditorExtension.cs
@@ -44,10 +44,13 @@ namespace MonoDevelop.CSharp
{
public override void Dispose ()
{
+ UntrackStartupProjectChanges ();
+
IdeApp.Workspace.FileAddedToProject -= HandleProjectChanged;
IdeApp.Workspace.FileRemovedFromProject -= HandleProjectChanged;
IdeApp.Workspace.WorkspaceItemUnloaded -= HandleWorkspaceItemUnloaded;
- IdeApp.Workspace.WorkspaceItemLoaded -= HandleWorkspaceItemLoaded;;
+ IdeApp.Workspace.WorkspaceItemLoaded -= HandleWorkspaceItemLoaded;
+ IdeApp.Workspace.ActiveConfigurationChanged -= HandleActiveConfigurationChanged;
if (caret != null) {
caret.PositionChanged -= UpdatePath;
@@ -86,7 +89,19 @@ namespace MonoDevelop.CSharp
IdeApp.Workspace.FileAddedToProject += HandleProjectChanged;
IdeApp.Workspace.FileRemovedFromProject += HandleProjectChanged;
IdeApp.Workspace.WorkspaceItemUnloaded += HandleWorkspaceItemUnloaded;
- IdeApp.Workspace.WorkspaceItemLoaded += HandleWorkspaceItemLoaded;;
+ IdeApp.Workspace.WorkspaceItemLoaded += HandleWorkspaceItemLoaded;
+ IdeApp.Workspace.ActiveConfigurationChanged += HandleActiveConfigurationChanged;
+ }
+
+ void HandleActiveConfigurationChanged (object sender, EventArgs e)
+ {
+ // If the current configuration changes and the project to which this document is bound is disabled in the
+ // new configuration, try to find another project
+ if (Document.Project != null && Document.Project.ParentSolution == IdeApp.ProjectOperations.CurrentSelectedSolution) {
+ var conf = Document.Project.ParentSolution.GetConfiguration (IdeApp.Workspace.ActiveConfiguration);
+ if (conf != null && !conf.BuildEnabledForItem (Document.Project))
+ ResetOwnerProject ();
+ }
}
void HandleWorkspaceItemLoaded (object sender, WorkspaceItemEventArgs e)
@@ -101,7 +116,7 @@ namespace MonoDevelop.CSharp
if (ownerProjects == null)
return;
foreach (var p in e.Item.GetAllProjects ().OfType<DotNetProject> ()) {
- ownerProjects.Remove (p);
+ RemoveOwnerProject (p);
}
if (ownerProjects.Count == 0) {
ownerProjects = null;
@@ -124,12 +139,12 @@ namespace MonoDevelop.CSharp
{
var projects = new HashSet<DotNetProject> (allProjects.Where (p => p.IsFileInProject (Document.FileName)));
if (ownerProjects == null || !projects.SetEquals (ownerProjects)) {
- ownerProjects = projects.OrderBy (p => p.Name).ToList ();
+ SetOwnerProjects (projects.OrderBy (p => p.Name).ToList ());
var dnp = Document.Project as DotNetProject;
if (ownerProjects.Count > 0 && (dnp == null || !ownerProjects.Contains (dnp))) {
// If the project for the document is not a DotNetProject but there is a project containing this file
// in the current solution, then use that project
- var pp = Document.Project != null ? ownerProjects.FirstOrDefault (p => p.ParentSolution == Document.Project.ParentSolution) : null;
+ var pp = Document.Project != null ? FindBestDefaultProject (Document.Project.ParentSolution) : null;
if (pp != null)
Document.AttachToProject (pp);
}
@@ -139,8 +154,76 @@ namespace MonoDevelop.CSharp
void UpdateOwnerProjects ()
{
UpdateOwnerProjects (IdeApp.Workspace.GetAllSolutionItems<DotNetProject> ());
- if (Document.Project == null && ownerProjects.Count > 0)
- Document.AttachToProject (ownerProjects[0]);
+ if (Document.Project == null)
+ ResetOwnerProject ();
+ }
+
+ void ResetOwnerProject ()
+ {
+ if (ownerProjects.Count > 0)
+ Document.AttachToProject (FindBestDefaultProject ());
+ }
+
+ DotNetProject FindBestDefaultProject (Solution solution = null)
+ {
+ // The best candidate to be selected as default project for this document is the startup project.
+ // If the startup project is not an owner, pick any project that is not disabled in the current configuration.
+ DotNetProject best = null;
+ if (solution == null)
+ solution = IdeApp.ProjectOperations.CurrentSelectedSolution;
+ foreach (var p in ownerProjects) {
+ if (p.ParentSolution != solution)
+ continue;
+ var solConf = p.ParentSolution.GetConfiguration (IdeApp.Workspace.ActiveConfiguration);
+ if (solConf == null || !solConf.BuildEnabledForItem (p))
+ continue;
+ if (p == p.ParentSolution.StartupItem)
+ return p;
+ if (best == null)
+ best = p;
+ }
+ return best ?? ownerProjects.FirstOrDefault (pr => pr.ParentSolution == solution) ?? ownerProjects.FirstOrDefault ();
+ }
+
+ void SetOwnerProjects (List<DotNetProject> projects)
+ {
+ UntrackStartupProjectChanges ();
+ ownerProjects = projects;
+ TrackStartupProjectChanges ();
+ }
+
+ void RemoveOwnerProject (DotNetProject project)
+ {
+ UntrackStartupProjectChanges ();
+ ownerProjects.Remove (project);
+ TrackStartupProjectChanges ();
+ }
+
+ void TrackStartupProjectChanges ()
+ {
+ if (ownerProjects != null) {
+ foreach (var sol in ownerProjects.Select (p => p.ParentSolution).Distinct ())
+ sol.StartupItemChanged += HandleStartupProjectChanged;
+ }
+ }
+
+ void UntrackStartupProjectChanges ()
+ {
+ if (ownerProjects != null) {
+ foreach (var sol in ownerProjects.Select (p => p.ParentSolution).Distinct ())
+ sol.StartupItemChanged -= HandleStartupProjectChanged;
+ }
+ }
+
+ void HandleStartupProjectChanged (object sender, EventArgs e)
+ {
+ // If the startup project changes, and the new startup project is an owner of this document,
+ // then attach the document to that project
+
+ var sol = (Solution) sender;
+ var p = sol.StartupItem as DotNetProject;
+ if (p != null && ownerProjects.Contains (p))
+ Document.AttachToProject (p);
}
#region IPathedDocument implementation
diff --git a/main/src/addins/CSharpBinding/templates/PortableLibrary.xpt.xml b/main/src/addins/CSharpBinding/templates/PortableLibrary.xpt.xml
index 96adc9255d..f09a65c7f1 100644
--- a/main/src/addins/CSharpBinding/templates/PortableLibrary.xpt.xml
+++ b/main/src/addins/CSharpBinding/templates/PortableLibrary.xpt.xml
@@ -6,7 +6,7 @@
<!-- Template Header -->
<TemplateConfiguration>
<_Name>Portable Library</_Name>
- <Category>other/net/general</Category>
+ <Category>multiplat/library/general</Category>
<Icon>md-project-library</Icon>
<Image id="md-pcl-project" />
<LanguageName>C#</LanguageName>
diff --git a/main/src/addins/CSharpBinding/templates/SharedAssetsProject.xpt.xml b/main/src/addins/CSharpBinding/templates/SharedAssetsProject.xpt.xml
index 18ccc3e169..6f2f0a7584 100644
--- a/main/src/addins/CSharpBinding/templates/SharedAssetsProject.xpt.xml
+++ b/main/src/addins/CSharpBinding/templates/SharedAssetsProject.xpt.xml
@@ -6,7 +6,7 @@
<!-- Template Header -->
<TemplateConfiguration>
<_Name>Shared Project</_Name>
- <Category>other/net/general</Category>
+ <Category>multiplat/library/general</Category>
<Icon>md-project-shared-assets</Icon>
<Image id="md-shared-project" />
<_Description>Creates a project that allows sharing files between projects</_Description>
diff --git a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.csproj b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.csproj
index 511567e76c..6950d93dc2 100644
--- a/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.csproj
+++ b/main/src/addins/Deployment/MonoDevelop.Deployment/MonoDevelop.Deployment.csproj
@@ -24,6 +24,7 @@
<DefineConstants>DEBUG</DefineConstants>
<NoWarn>1591;1573</NoWarn>
<DocumentationFile>..\..\..\..\build\AddIns\MonoDevelop.Deployment\MonoDevelop.Deployment.xml</DocumentationFile>
+ <DebugType>full</DebugType>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
diff --git a/main/src/addins/MacPlatform/Dialogs/MacAddFileDialogHandler.cs b/main/src/addins/MacPlatform/Dialogs/MacAddFileDialogHandler.cs
index 87c62c87c9..fb0e5fe557 100644
--- a/main/src/addins/MacPlatform/Dialogs/MacAddFileDialogHandler.cs
+++ b/main/src/addins/MacPlatform/Dialogs/MacAddFileDialogHandler.cs
@@ -60,7 +60,8 @@ namespace MonoDevelop.MacIntegration
};
box.Layout ();
panel.AccessoryView = box.View;
- box.Layout (box.View.Superview.Frame.Size);
+ if (box.View.Superview != null)
+ box.Layout (box.View.Superview.Frame.Size);
} else {
dropdownBox.Layout ();
panel.AccessoryView = dropdownBox.View;
diff --git a/main/src/addins/MacPlatform/Dialogs/MacOpenFileDialogHandler.cs b/main/src/addins/MacPlatform/Dialogs/MacOpenFileDialogHandler.cs
index 946780fe08..704cd847fb 100644
--- a/main/src/addins/MacPlatform/Dialogs/MacOpenFileDialogHandler.cs
+++ b/main/src/addins/MacPlatform/Dialogs/MacOpenFileDialogHandler.cs
@@ -25,9 +25,9 @@
// THE SOFTWARE.
using System;
-using System.Collections.Generic;
using System.Linq;
using System.Text;
+using System.Collections.Generic;
using AppKit;
@@ -36,7 +36,7 @@ using MonoDevelop.Ide;
using MonoDevelop.Ide.Extensions;
using MonoDevelop.Ide.Gui;
using MonoDevelop.MacInterop;
-
+using MonoDevelop.Components.Extensions;
namespace MonoDevelop.MacIntegration
{
@@ -47,15 +47,12 @@ namespace MonoDevelop.MacIntegration
NSSavePanel panel = null;
try {
- bool directoryMode = data.Action != Gtk.FileChooserAction.Open
- && data.Action != Gtk.FileChooserAction.Save;
-
- if (data.Action == Gtk.FileChooserAction.Save) {
+ if (data.Action == SelectFileDialogAction.Save) {
panel = new NSSavePanel ();
} else {
panel = new NSOpenPanel {
- CanChooseDirectories = directoryMode,
- CanChooseFiles = !directoryMode,
+ CanChooseDirectories = (data.Action & SelectFileDialogAction.FolderFlags) != 0,
+ CanChooseFiles = (data.Action & SelectFileDialogAction.FileFlags) != 0,
};
}
@@ -70,7 +67,7 @@ namespace MonoDevelop.MacIntegration
List<FileViewer> currentViewers = null;
var labels = new List<MDAlignment> ();
- if (!directoryMode) {
+ if ((data.Action & SelectFileDialogAction.FileFlags) != 0) {
var filterPopup = MacSelectFileDialogHandler.CreateFileFilterPopup (data, panel);
if (filterPopup != null) {
@@ -84,7 +81,7 @@ namespace MonoDevelop.MacIntegration
}
if (data.ShowEncodingSelector) {
- encodingSelector = new SelectEncodingPopUpButton (data.Action != Gtk.FileChooserAction.Save);
+ encodingSelector = new SelectEncodingPopUpButton (data.Action != SelectFileDialogAction.Save);
encodingSelector.SelectedEncodingId = data.Encoding != null ? data.Encoding.CodePage : 0;
var encodingLabel = new MDAlignment (new MDLabel (GettextCatalog.GetString ("Encoding:")), true);
@@ -249,7 +246,11 @@ namespace MonoDevelop.MacIntegration
//re-center the accessory view in its parent, Cocoa does this for us initially and after
//resizing the window, but we need to do it again after altering its layout
- var superFrame = box.View.Superview.Frame;
+ var superView = box.View.Superview;
+ if (superView == null)
+ return;
+
+ var superFrame = superView.Frame;
var frame = box.View.Frame;
//not sure why it's ceiling, but this matches the Cocoa layout
frame.X = (float)Math.Ceiling ((superFrame.Width - frame.Width) / 2);
diff --git a/main/src/addins/MacPlatform/Dialogs/MacSelectFileDialogHandler.cs b/main/src/addins/MacPlatform/Dialogs/MacSelectFileDialogHandler.cs
index 9355e85bda..eba974ee8c 100644
--- a/main/src/addins/MacPlatform/Dialogs/MacSelectFileDialogHandler.cs
+++ b/main/src/addins/MacPlatform/Dialogs/MacSelectFileDialogHandler.cs
@@ -48,21 +48,19 @@ namespace MonoDevelop.MacIntegration
NSSavePanel panel = null;
try {
- bool directoryMode = data.Action != Gtk.FileChooserAction.Open;
-
- if (data.Action == Gtk.FileChooserAction.Save) {
+ if (data.Action == SelectFileDialogAction.Save) {
panel = new NSSavePanel ();
} else {
panel = new NSOpenPanel {
- CanChooseDirectories = directoryMode,
- CanChooseFiles = !directoryMode,
+ CanChooseDirectories = (data.Action & SelectFileDialogAction.FolderFlags) != 0,
+ CanChooseFiles = (data.Action & SelectFileDialogAction.FileFlags) != 0,
ResolvesAliases = false,
};
}
SetCommonPanelProperties (data, panel);
- if (!directoryMode) {
+ if ((data.Action & SelectFileDialogAction.FileFlags) != 0) {
var popup = CreateFileFilterPopup (data, panel);
if (popup != null) {
panel.AccessoryView = popup;
@@ -107,7 +105,7 @@ namespace MonoDevelop.MacIntegration
if (!string.IsNullOrEmpty (data.CurrentFolder))
panel.DirectoryUrl = new NSUrl (data.CurrentFolder, true);
- panel.ParentWindow = NSApplication.SharedApplication.KeyWindow;
+ panel.ParentWindow = NSApplication.SharedApplication.KeyWindow ?? NSApplication.SharedApplication.MainWindow;
var openPanel = panel as NSOpenPanel;
if (openPanel != null) {
diff --git a/main/src/addins/MacPlatform/MacPlatform.cs b/main/src/addins/MacPlatform/MacPlatform.cs
index 5777cdddfa..203f239de5 100644
--- a/main/src/addins/MacPlatform/MacPlatform.cs
+++ b/main/src/addins/MacPlatform/MacPlatform.cs
@@ -791,10 +791,12 @@ namespace MonoDevelop.MacIntegration
// When we're looking for modal windows that don't belong to GTK, exclude
// NSStatusBarWindow (which is visible on Mavericks when we're in fullscreen) and
// NSToolbarFullscreenWindow (which is visible on Yosemite in fullscreen).
+ // _NSFullScreenTileDividerWindow (which is visible on El Capitan when two apps share the same fullscreen).
return toplevels.Any (t => t.Key.IsVisible && (t.Value == null || t.Value.Modal) &&
!(t.Key.DebugDescription.StartsWith("<NSStatusBarWindow", StringComparison.Ordinal) ||
t.Key.DebugDescription.StartsWith ("<NSToolbarFullScreenWindow", StringComparison.Ordinal) ||
- t.Key.DebugDescription.StartsWith ("<NSCarbonMenuWindow", StringComparison.Ordinal)
+ t.Key.DebugDescription.StartsWith ("<NSCarbonMenuWindow", StringComparison.Ordinal) ||
+ t.Key.DebugDescription.StartsWith ("<_NSFullScreenTileDividerWindow", StringComparison.Ordinal)
));
}
diff --git a/main/src/addins/MacPlatform/MainToolbar/MainToolbar.cs b/main/src/addins/MacPlatform/MainToolbar/MainToolbar.cs
index 675007e6ae..cd14af52ea 100644
--- a/main/src/addins/MacPlatform/MainToolbar/MainToolbar.cs
+++ b/main/src/addins/MacPlatform/MainToolbar/MainToolbar.cs
@@ -33,6 +33,7 @@ using AppKit;
using CoreGraphics;
using Foundation;
using MonoDevelop.Ide;
+using Xwt;
namespace MonoDevelop.MacIntegration.MainToolbar
{
@@ -66,6 +67,10 @@ namespace MonoDevelop.MacIntegration.MainToolbar
}
int selectorIdx;
+ SelectorView selector {
+ get { return (SelectorView)widget.Items[selectorIdx].View; }
+ }
+
SelectorView.PathSelectorView selectorView {
get { return (SelectorView.PathSelectorView)widget.Items[selectorIdx].View.Subviews [0]; }
}
@@ -96,6 +101,35 @@ namespace MonoDevelop.MacIntegration.MainToolbar
return item;
}
+ OverflowInfoEventArgs FillOverflowInfo (OverflowInfoEventArgs e)
+ {
+ var visibleItems = widget.VisibleItems;
+ var allItems = widget.Items;
+
+ e.WindowWidth = gtkWindow.Allocation.Width;
+ foreach (var iter in allItems) {
+ e.AllItemsWidth += iter.MinSize.Width;
+ if (!visibleItems.Contains (iter))
+ e.ItemsInOverflowWidth += iter.MinSize.Width;
+ }
+ // Add spacings.
+ nfloat spacing = (allItems.Length - 1) * 16;
+ e.AllItemsWidth += spacing;
+
+ return e;
+ }
+
+ bool IsCorrectNotification (NSView view, NSObject notifObject)
+ {
+ var window = selector.Window;
+
+ // Skip updates with a null Window. Only crashes on Mavericks.
+ // The View gets updated once again when the window resize finishes.
+ // We're getting notified about all windows in the application (for example, NSPopovers) that change size when really we only care about
+ // the window the bar is in.
+ return window != null && notifObject == window;
+ }
+
NSToolbarItem CreateSelectorToolbarItem ()
{
var selector = new SelectorView ();
@@ -109,6 +143,43 @@ namespace MonoDevelop.MacIntegration.MainToolbar
item.MinSize = item.MaxSize = e.Size;
centeringSpace.UpdateWidth ();
};
+ selector.OverflowInfoRequested += (o, e) => {
+ FillOverflowInfo (e);
+ };
+
+ IDisposable resizeTimer = null;
+ NSNotificationCenter.DefaultCenter.AddObserver (NSWindow.WillStartLiveResizeNotification, notif => DispatchService.GuiDispatch (() => {
+ if (!IsCorrectNotification (selector, notif.Object))
+ return;
+
+ if (resizeTimer != null)
+ resizeTimer.Dispose ();
+
+ resizeTimer = Application.TimeoutInvoke (100, () => {
+ if (widget.Items.Length != widget.VisibleItems.Length)
+ selector.RequestResize ();
+ return true;
+ });
+ }));
+
+ NSNotificationCenter.DefaultCenter.AddObserver (NSWindow.DidResizeNotification, notif => DispatchService.GuiDispatch (() => {
+ if (!IsCorrectNotification (selector, notif.Object))
+ return;
+
+ // Don't check difference in overflow menus. This could cause issues since we're doing resizing of widgets and the views might go in front
+ // or behind while we're doing the resize request.
+ selector.RequestResize ();
+ }));
+
+ NSNotificationCenter.DefaultCenter.AddObserver (NSWindow.DidEndLiveResizeNotification, notif => DispatchService.GuiDispatch (() => {
+ if (!IsCorrectNotification (selector, notif.Object))
+ return;
+
+ if (resizeTimer != null)
+ resizeTimer.Dispose ();
+
+ resizeTimer = Application.TimeoutInvoke (300, selector.RequestResize);
+ }));
var pathSelector = (SelectorView.PathSelectorView)selector.Subviews [0];
pathSelector.ConfigurationChanged += (sender, e) => {
@@ -143,6 +214,7 @@ namespace MonoDevelop.MacIntegration.MainToolbar
nfloat resize = 6 + 33 * bar.SegmentCount;
item.MinSize = new CGSize (resize, bar.FittingSize.Height);
item.MaxSize = new CGSize (resize, bar.FittingSize.Height);
+ selector.RequestResize ();
centeringSpace.UpdateWidth ();
};
return item;
@@ -175,16 +247,15 @@ namespace MonoDevelop.MacIntegration.MainToolbar
NSToolbarItem CreateSearchBarToolbarItem ()
{
var bar = new SearchBar ();
+
+ // Remove the focus from the Gtk system when Cocoa has focus
+ // Fixes BXC #29601
+ bar.GainedFocus += (o, e) => IdeApp.Workbench.RootWindow.Focus = null;
+
viewCache.Add (bar);
- var menuBar = new SearchBar {
- Frame = new CGRect (0, 0, 180, bar.FittingSize.Height),
- };
var item = new NSToolbarItem (SearchBarId) {
View = bar,
- MenuFormRepresentation = new NSMenuItem {
- View = menuBar,
- },
- MinSize = new CGSize (180, bar.FittingSize.Height),
+ MinSize = new CGSize (150, bar.FittingSize.Height),
MaxSize = new CGSize (270, bar.FittingSize.Height),
};
AttachToolbarEvents (bar);
@@ -202,18 +273,26 @@ namespace MonoDevelop.MacIntegration.MainToolbar
MaxSize = new CGSize (360, 22),
};
- NSNotificationCenter.DefaultCenter.AddObserver (NSWindow.DidResizeNotification, notif => DispatchService.GuiDispatch (() => {
+ Action<NSNotification> resizeAction = notif => DispatchService.GuiDispatch (() => {
// Skip updates with a null Window. Only crashes on Mavericks.
// The View gets updated once again when the window resize finishes.
if (bar.Window == null)
return;
+ // We're getting notified about all windows in the application (for example, NSPopovers) that change size when really we only care about
+ // the window the bar is in.
+ if (notif.Object != bar.Window)
+ return;
+
double maxSize = Math.Round (bar.Window.Frame.Width * 0.30f);
double minSize = Math.Round (bar.Window.Frame.Width * 0.25f);
- item.MinSize = new CGSize ((nfloat)Math.Max (280, minSize), 22);
+ item.MinSize = new CGSize ((nfloat)Math.Max (220, minSize), 22);
item.MaxSize = new CGSize ((nfloat)Math.Min (700, maxSize), 22);
bar.RepositionStatusLayers ();
- }));
+ });
+
+ NSNotificationCenter.DefaultCenter.AddObserver (NSWindow.DidResizeNotification, resizeAction);
+ NSNotificationCenter.DefaultCenter.AddObserver (NSWindow.DidEndLiveResizeNotification, resizeAction);
return item;
}
@@ -274,30 +353,12 @@ namespace MonoDevelop.MacIntegration.MainToolbar
public event EventHandler SearchEntryResized;
#pragma warning restore 0067
- bool IsSearchEntryInOverflow {
- get { return widget.Items.Length != widget.VisibleItems.Length; }
- }
-
public void FocusSearchBar ()
{
+ searchEntry.Focus ();
+
var entry = searchEntry;
- if (!IsSearchEntryInOverflow)
- entry.SelectText (entry);
- else {
- // NSSearchField -> NSToolbarItemViewer -> _NSToolbarClipView -> NSToolbarView -> NSToolbarClippedItemsIndicator
- var clipItem = (NSButton)searchEntry.Superview.Superview.Superview.Subviews [1];
- var sel = new ObjCRuntime.Selector ("_computeMenuForClippedItemsIfNeeded");
- if (!clipItem.RespondsToSelector (sel))
- throw new Exception ("Cocoa selector changed for clipped items menu.");
-
- clipItem.PerformSelector (sel);
- var menu = clipItem.Menu;
- var searchItem = menu.ItemAt (0);
- var searchView = (SearchBar)searchItem.View;
- AttachToolbarEvents (searchView);
- menu.PopUpMenu (menu.ItemAt (0), new CGPoint (0, -5), clipItem);
- searchView.SelectText (searchView);
- }
+ entry.SelectText (entry);
}
List<IButtonBarButton> barItems = new List<IButtonBarButton> ();
@@ -397,39 +458,10 @@ namespace MonoDevelop.MacIntegration.MainToolbar
public string SearchText {
get {
- if (!IsSearchEntryInOverflow) {
- return searchEntry.StringValue;
- }
-
- // NSSearchField -> NSToolbarItemViewer -> _NSToolbarClipView -> NSToolbarView -> NSToolbarClippedItemsIndicator
- var clipItem = (NSButton)searchEntry.Superview.Superview.Superview.Subviews [1];
- var sel = new ObjCRuntime.Selector ("_computeMenuForClippedItemsIfNeeded");
- if (!clipItem.RespondsToSelector (sel))
- throw new Exception ("Cocoa selector changed for clipped items menu.");
-
- clipItem.PerformSelector (sel);
-
- var menuBar = (SearchBar)clipItem.Menu.ItemAt (0).View;
- AttachToolbarEvents (menuBar);
- return menuBar.StringValue;
+ return searchEntry.StringValue;
}
set {
- if (!IsSearchEntryInOverflow) {
- searchEntry.StringValue = value;
- return;
- }
-
- // NSSearchField -> NSToolbarItemViewer -> _NSToolbarClipView -> NSToolbarView -> NSToolbarClippedItemsIndicator
- var clipItem = (NSButton)searchEntry.Superview.Superview.Superview.Subviews [1];
- var sel = new ObjCRuntime.Selector ("_computeMenuForClippedItemsIfNeeded");
- if (!clipItem.RespondsToSelector (sel))
- throw new Exception ("Cocoa selector changed for clipped items menu.");
-
- clipItem.PerformSelector (sel);
-
- var menuBar = (SearchBar)clipItem.Menu.ItemAt (0).View;
- AttachToolbarEvents (menuBar);
- menuBar.StringValue = value;
+ searchEntry.StringValue = value;
}
}
@@ -452,8 +484,12 @@ namespace MonoDevelop.MacIntegration.MainToolbar
var workbenchNsWindow = nsWindows.FirstOrDefault (nswin =>
GtkMacInterop.GetGtkWindow (nswin) is MonoDevelop.Ide.Gui.DefaultWorkbench);
- widget.Allocation = new Gdk.Rectangle (0, (int)(fullscreenToolbarNsWindow.Frame.Bottom - workbenchNsWindow.Frame.Height),
- (int)fullscreenToolbarNsWindow.Frame.Width, 0);
+ // Gtk and Cocoa coordinates are not the same. Offset by left and top screens to get the correct
+ // coordinate for the popup window based on Cocoa coordinates which offset left/top from current desktop.
+ nfloat xOffset = -NSScreen.Screens.Min (screen => screen.Frame.Left);
+ nfloat yOffset = NSScreen.Screens.Max (screen => screen.Frame.Bottom);
+ widget.Allocation = new Gdk.Rectangle (0, (int)(yOffset - workbenchNsWindow.Frame.Height),
+ (int)(xOffset + fullscreenToolbarNsWindow.Frame.Width), 0);
}
return widget;
}
diff --git a/main/src/addins/MacPlatform/MainToolbar/SearchBar.cs b/main/src/addins/MacPlatform/MainToolbar/SearchBar.cs
index 29bbd71e00..9e3f902190 100644
--- a/main/src/addins/MacPlatform/MainToolbar/SearchBar.cs
+++ b/main/src/addins/MacPlatform/MainToolbar/SearchBar.cs
@@ -40,6 +40,7 @@ namespace MonoDevelop.MacIntegration.MainToolbar
internal event EventHandler<Xwt.KeyEventArgs> KeyPressed;
internal event EventHandler LostFocus;
new internal event EventHandler Activated;
+ public event EventHandler GainedFocus;
/// <summary>
/// This tells whether events have been attached when created from the menu.
@@ -113,6 +114,21 @@ namespace MonoDevelop.MacIntegration.MainToolbar
// Needs to be grabbed after it's parented.
gtkWidget = GtkMacInterop.NSViewToGtkWidget (this);
}
+
+ public override bool BecomeFirstResponder ()
+ {
+ bool firstResponder = base.BecomeFirstResponder ();
+ if (firstResponder)
+ Focus ();
+
+ return firstResponder;
+ }
+
+ public void Focus ()
+ {
+ if (GainedFocus != null)
+ GainedFocus (this, EventArgs.Empty);
+ }
}
}
diff --git a/main/src/addins/MacPlatform/MainToolbar/SelectorView.cs b/main/src/addins/MacPlatform/MainToolbar/SelectorView.cs
index f61007805d..21b7f938d0 100644
--- a/main/src/addins/MacPlatform/MainToolbar/SelectorView.cs
+++ b/main/src/addins/MacPlatform/MainToolbar/SelectorView.cs
@@ -45,10 +45,18 @@ namespace MonoDevelop.MacIntegration.MainToolbar
}
}
+ class OverflowInfoEventArgs : EventArgs
+ {
+ public nfloat WindowWidth { get; set; }
+ public nfloat AllItemsWidth { get; set; }
+ public nfloat ItemsInOverflowWidth { get; set; }
+ }
+
[Register]
class SelectorView : NSButton
{
public event EventHandler<SizeRequestedEventArgs> ResizeRequested;
+ public event EventHandler<OverflowInfoEventArgs> OverflowInfoRequested;
internal const int ConfigurationIdx = 0;
internal const int RuntimeIdx = 1;
@@ -56,31 +64,109 @@ namespace MonoDevelop.MacIntegration.MainToolbar
{
Title = "";
BezelStyle = NSBezelStyle.TexturedRounded;
- AddSubview (new PathSelectorView (new CGRect (6, 0, 1, 1)));
+ var pathSelectorView = new PathSelectorView (new CGRect (6, 0, 1, 1));
+ pathSelectorView.UnregisterDraggedTypes ();
+ AddSubview (pathSelectorView);
+ }
+
+ public bool RequestResize ()
+ {
+ var p = (PathSelectorView)Subviews [0];
+ var overflowInfo = new OverflowInfoEventArgs ();
+ if (OverflowInfoRequested != null)
+ OverflowInfoRequested (this, overflowInfo);
+
+ var size = new CGSize (p.ResizeIfNeeded (overflowInfo), Frame.Height);
+
+ if (size != Frame.Size) {
+ if (ResizeRequested != null)
+ ResizeRequested (this, new SizeRequestedEventArgs (size));
+
+ SetFrameSize (size);
+ p.SetFrameSize (size);
+
+ SetNeedsDisplay ();
+ p.SetNeedsDisplay ();
+ return true;
+ }
+ return false;
}
- public override void DrawRect (CGRect dirtyRect)
+ public override void ViewWillDraw ()
{
- var p = (NSPathControl)Subviews [0];
- var size = new CGSize (10 +
- p.PathComponentCells [ConfigurationIdx].CellSize.Width +
- p.PathComponentCells [RuntimeIdx].CellSize.Width + p.Frame.Left,
- Frame.Size.Height);
- if (ResizeRequested != null)
- ResizeRequested (this, new SizeRequestedEventArgs (size));
-
- SetFrameSize (size);
- p.SetFrameSize (size);
- p.SetNeedsDisplay ();
- base.DrawRect (new CGRect (CGPoint.Empty, size));
+ RequestResize ();
+ base.ViewWillDraw ();
}
#region PathSelectorView
[Register]
public class PathSelectorView : NSPathControl
{
+ [Flags]
+ enum CellState
+ {
+ AllHidden = 0x0,
+ RuntimeShown = 0x1,
+ ConfigurationShown = 0x2,
+ AllShown = 0x3,
+ }
+
static readonly string ConfigurationPlaceholder = GettextCatalog.GetString ("Default");
static readonly string RuntimePlaceholder = GettextCatalog.GetString ("Default");
+ CellState state = CellState.AllShown;
+
+ nfloat UpdatePathCellForSize (int idx, nfloat remaining, CellState newStateIfEnoughSize)
+ {
+ var cell = PathComponentCells [idx];
+ string text;
+ if (idx == ConfigurationIdx) {
+ if (ActiveConfiguration != null)
+ text = ActiveConfiguration.DisplayString;
+ else
+ text = ConfigurationPlaceholder;
+ } else {
+ if (ActiveRuntime != null) {
+ using (var mutableModel = ActiveRuntime.GetMutableModel ())
+ text = mutableModel.FullDisplayString;
+ } else
+ text = RuntimePlaceholder;
+ }
+ var size = new NSAttributedString (text, new NSStringAttributes { Font = cell.Font }).Size.Width + 20;
+ if (size < remaining) {
+ state |= newStateIfEnoughSize;
+ UpdatePathText (idx, text);
+ }
+ return remaining - size;
+ }
+
+ internal nfloat ResizeIfNeeded (OverflowInfoEventArgs args)
+ {
+ var remaining = args.WindowWidth - args.AllItemsWidth;
+ if (remaining < 0 || args.ItemsInOverflowWidth > 0) {
+ var cell = PathComponentCells [RuntimeIdx];
+ var size = new NSAttributedString (cell.Title, new NSStringAttributes { Font = cell.Font }).Size.Width;
+ remaining += size;
+ args.ItemsInOverflowWidth -= size;
+ if ((state & CellState.RuntimeShown) != 0) {
+ state &= ~CellState.RuntimeShown;
+ UpdatePathText (RuntimeIdx, string.Empty);
+ }
+ if ((remaining < 0 || args.ItemsInOverflowWidth > 0) && (state & CellState.ConfigurationShown) != 0) {
+ state &= ~CellState.ConfigurationShown;
+ UpdatePathText (ConfigurationIdx, string.Empty);
+ }
+ } else {
+ remaining = remaining - args.ItemsInOverflowWidth;
+ if ((state & CellState.ConfigurationShown) == 0)
+ remaining = UpdatePathCellForSize (ConfigurationIdx, remaining, CellState.ConfigurationShown);
+ if ((state & CellState.RuntimeShown) == 0)
+ UpdatePathCellForSize (RuntimeIdx, remaining, CellState.RuntimeShown);
+ }
+
+ return 10 +
+ PathComponentCells [ConfigurationIdx].CellSize.Width +
+ PathComponentCells [RuntimeIdx].CellSize.Width + Frame.Left;
+ }
NSMenu CreateSubMenuForRuntime (IRuntimeModel runtime)
{
@@ -99,14 +185,21 @@ namespace MonoDevelop.MacIntegration.MainToolbar
void CreateMenuItem (NSMenu menu, IRuntimeModel runtime)
{
- var menuItem = new NSMenuItem {
- IndentationLevel = runtime.IsIndented ? 2 : 1,
- Enabled = runtime.Enabled,
- Hidden = !runtime.Visible,
- AttributedTitle = new NSAttributedString (runtime.DisplayString, new NSStringAttributes {
- Font = runtime.Notable ? NSFontManager.SharedFontManager.ConvertFont (menu.Font, NSFontTraitMask.Bold) : menu.Font,
- }),
- };
+ NSMenuItem menuItem;
+ string runtimeFullDisplayString;
+
+ using (var mutableModel = runtime.GetMutableModel ()) {
+ runtimeFullDisplayString = mutableModel.FullDisplayString;
+
+ menuItem = new NSMenuItem {
+ IndentationLevel = runtime.IsIndented ? 2 : 1,
+ AttributedTitle = new NSAttributedString (mutableModel.DisplayString, new NSStringAttributes {
+ Font = runtime.Notable ? NSFontManager.SharedFontManager.ConvertFont (menu.Font, NSFontTraitMask.Bold) : menu.Font,
+ }),
+ Enabled = mutableModel.Enabled,
+ Hidden = !mutableModel.Visible,
+ };
+ }
var subMenu = CreateSubMenuForRuntime (runtime);
if (subMenu != null) {
@@ -114,14 +207,27 @@ namespace MonoDevelop.MacIntegration.MainToolbar
menuItem.Enabled = true;
} else {
menuItem.Activated += (o2, e2) => {
- string old = ActiveRuntime.FullDisplayString;
- ActiveRuntime = runtimeModel.First (r => r.FullDisplayString == runtime.FullDisplayString);
+ string old;
+ using (var activeMutableModel = ActiveRuntime.GetMutableModel ())
+ old = activeMutableModel.FullDisplayString;
+
+ IRuntimeModel newRuntime = runtimeModel.FirstOrDefault (r => {
+ using (var newRuntimeMutableModel = r.GetMutableModel ())
+ return newRuntimeMutableModel.FullDisplayString == runtimeFullDisplayString;
+ });
+ if (newRuntime == null)
+ return;
+
+ ActiveRuntime = newRuntime;
var ea = new HandledEventArgs ();
if (RuntimeChanged != null)
RuntimeChanged (o2, ea);
if (ea.Handled)
- ActiveRuntime = runtimeModel.First (r => r.FullDisplayString == old);
+ ActiveRuntime = runtimeModel.First (r => {
+ using (var newRuntimeMutableModel = r.GetMutableModel ())
+ return newRuntimeMutableModel.FullDisplayString == old;
+ });
};
}
menu.AddItem (menuItem);
@@ -162,6 +268,9 @@ namespace MonoDevelop.MacIntegration.MainToolbar
Font = NSFont.MenuFontOfSize (12),
};
if (object.ReferenceEquals (ClickedPathComponentCell, PathComponentCells [ConfigurationIdx])) {
+ if (ActiveConfiguration == null)
+ return;
+
foreach (var configuration in ConfigurationModel) {
if (idx == -1 && configuration.OriginalId == ActiveConfiguration.OriginalId)
idx = i;
@@ -179,18 +288,25 @@ namespace MonoDevelop.MacIntegration.MainToolbar
++i;
}
} else if (object.ReferenceEquals (ClickedPathComponentCell, PathComponentCells [RuntimeIdx])) {
- foreach (var runtime in RuntimeModel) {
- if (idx == -1 && runtime.DisplayString == ActiveRuntime.DisplayString)
- idx = i;
-
- if (runtime.HasParent)
- continue;
-
- if (runtime.IsSeparator)
- menu.AddItem (NSMenuItem.SeparatorItem);
- else
- CreateMenuItem (menu, runtime);
- ++i;
+ if (ActiveRuntime == null)
+ return;
+
+ using (var activeMutableModel = ActiveRuntime.GetMutableModel ()) {
+ foreach (var runtime in RuntimeModel) {
+ using (var mutableModel = runtime.GetMutableModel ()) {
+ if (idx == -1 && mutableModel.DisplayString == activeMutableModel.DisplayString)
+ idx = i;
+ }
+
+ if (runtime.HasParent)
+ continue;
+
+ if (runtime.IsSeparator)
+ menu.AddItem (NSMenuItem.SeparatorItem);
+ else
+ CreateMenuItem (menu, runtime);
+ ++i;
+ }
}
} else
throw new NotSupportedException ();
@@ -228,7 +344,8 @@ namespace MonoDevelop.MacIntegration.MainToolbar
void UpdatePathText (int idx, string text)
{
- PathComponentCells [idx].Title = text;
+ bool showText = (idx == ConfigurationIdx && (state & CellState.ConfigurationShown) != 0) || (idx == RuntimeIdx && (state & CellState.RuntimeShown) != 0);
+ PathComponentCells [idx].Title = showText ? text : "\u00A0";
PathComponentCells [ConfigurationIdx].Image = ImageService.GetIcon ("project").ToNSImage ();
PathComponentCells [RuntimeIdx].Image = ImageService.GetIcon ("device").ToNSImage ();
@@ -240,7 +357,9 @@ namespace MonoDevelop.MacIntegration.MainToolbar
get { return activeConfiguration; }
set {
activeConfiguration = value;
+ state |= CellState.ConfigurationShown;
UpdatePathText (ConfigurationIdx, value.DisplayString);
+ ((SelectorView)Superview).RequestResize ();
}
}
@@ -249,7 +368,11 @@ namespace MonoDevelop.MacIntegration.MainToolbar
get { return activeRuntime; }
set {
activeRuntime = value;
- UpdatePathText (RuntimeIdx, value.FullDisplayString);
+ using (var mutableModel = value.GetMutableModel ()) {
+ state |= CellState.RuntimeShown;
+ UpdatePathText (RuntimeIdx, mutableModel.FullDisplayString);
+ ((SelectorView)Superview).RequestResize ();
+ }
}
}
@@ -259,8 +382,11 @@ namespace MonoDevelop.MacIntegration.MainToolbar
set {
configurationModel = value;
int count = value.Count ();
- if (count == 0)
+ if (count == 0) {
+ state |= CellState.ConfigurationShown;
UpdatePathText (ConfigurationIdx, ConfigurationPlaceholder);
+ ((SelectorView)Superview).RequestResize ();
+ }
PathComponentCells [ConfigurationIdx].Enabled = count > 1;
}
}
@@ -271,8 +397,11 @@ namespace MonoDevelop.MacIntegration.MainToolbar
set {
runtimeModel = value;
int count = value.Count ();
- if (count == 0)
+ if (count == 0) {
+ state |= CellState.RuntimeShown;
UpdatePathText (RuntimeIdx, RuntimePlaceholder);
+ ((SelectorView)Superview).RequestResize ();
+ }
PathComponentCells [RuntimeIdx].Enabled = count > 1;
}
}
diff --git a/main/src/addins/MacPlatform/MainToolbar/StatusBar.cs b/main/src/addins/MacPlatform/MainToolbar/StatusBar.cs
index f30ba94714..2331b24551 100644
--- a/main/src/addins/MacPlatform/MainToolbar/StatusBar.cs
+++ b/main/src/addins/MacPlatform/MainToolbar/StatusBar.cs
@@ -154,7 +154,7 @@ namespace MonoDevelop.MacIntegration.MainToolbar
BezelStyle = NSTextFieldBezelStyle.Rounded;
WantsLayer = true;
- Layer.CornerRadius = 4;
+ Layer.CornerRadius = MacSystemInformation.OsVersion >= MacSystemInformation.ElCapitan ? 6 : 4;
ctxHandler = new StatusBarContextHandler (this);
updateHandler = delegate {
@@ -201,7 +201,7 @@ namespace MonoDevelop.MacIntegration.MainToolbar
if (Window == null)
return;
- ReconstructString ();
+ ReconstructString (updateTrackingAreas: true);
foreach (var layer in Layer.Sublayers) {
if (layer.Name != null && layer.Name.StartsWith (StatusIconPrefixId, StringComparison.Ordinal))
layer.SetImage (layerToStatus [layer.Name].Image, Window.BackingScaleFactor);
@@ -234,7 +234,7 @@ namespace MonoDevelop.MacIntegration.MainToolbar
}
NSTrackingArea textFieldArea;
- void ReconstructString ()
+ void ReconstructString (bool updateTrackingAreas)
{
if (string.IsNullOrEmpty (text)) {
textField.AttributedStringValue = new NSAttributedString ("");
@@ -247,8 +247,13 @@ namespace MonoDevelop.MacIntegration.MainToolbar
var width = textField.AttributedStringValue.BoundingRectWithSize (new CGSize (nfloat.MaxValue, textField.Frame.Height),
NSStringDrawingOptions.UsesFontLeading | NSStringDrawingOptions.UsesLineFragmentOrigin).Width;
- if (textFieldArea != null)
+ if (!updateTrackingAreas)
+ return;
+
+ if (textFieldArea != null) {
RemoveTrackingArea (textFieldArea);
+ DestroyPopover ();
+ }
if (width > textField.Frame.Width) {
textFieldArea = new NSTrackingArea (textField.Frame, NSTrackingAreaOptions.MouseEnteredAndExited | NSTrackingAreaOptions.ActiveInKeyWindow, this, null);
@@ -296,12 +301,12 @@ namespace MonoDevelop.MacIntegration.MainToolbar
right -= 9;
if (layer != null) {
- layer.Frame = new CGRect (right, 3, 1, 16);
+ layer.Frame = new CGRect (right, MacSystemInformation.OsVersion >= MacSystemInformation.ElCapitan ? 4 : 3, 1, 16);
layer.SetNeedsDisplay ();
} else {
layer = CALayer.Create ();
layer.Name = SeparatorLayerId;
- layer.Frame = new CGRect (right, 3, 1, 16);
+ layer.Frame = new CGRect (right, MacSystemInformation.OsVersion >= MacSystemInformation.ElCapitan ? 4 : 3, 1, 16);
layer.BackgroundColor = NSColor.LightGray.CGColor;
Layer.AddSublayer (layer);
}
@@ -339,12 +344,12 @@ namespace MonoDevelop.MacIntegration.MainToolbar
nfloat right = DrawSeparatorIfNeeded (LeftMostStatusItemX ());
CGSize size = buildResultText.AttributedString.Size;
right = right - 6 - size.Width;
- buildResultText.Frame = new CGRect (right, 5f, size.Width, size.Height);
+ buildResultText.Frame = new CGRect (right, MacSystemInformation.OsVersion >= MacSystemInformation.ElCapitan ? 6 : 5, size.Width, size.Height);
if (buildResultText.SuperLayer == null)
Layer.AddSublayer (buildResultText);
buildResultText.SetNeedsDisplay ();
right -= buildResultIcon.Bounds.Width;
- buildResultIcon.Frame = new CGRect (right, 3, buildResultIcon.Bounds.Width, buildResultIcon.Bounds.Height);
+ buildResultIcon.Frame = new CGRect (right, MacSystemInformation.OsVersion >= MacSystemInformation.ElCapitan ? 4 : 3, buildResultIcon.Bounds.Width, buildResultIcon.Bounds.Height);
if (buildResultIcon.SuperLayer == null)
Layer.AddSublayer (buildResultIcon);
@@ -358,10 +363,11 @@ namespace MonoDevelop.MacIntegration.MainToolbar
foreach (var item in Layer.Sublayers) {
if (item.Name != null && item.Name.StartsWith (StatusIconPrefixId, StringComparison.Ordinal)) {
var icon = layerToStatus [item.Name];
- RemoveTrackingArea (icon.TrackingArea);
+ if (icon.TrackingArea != null)
+ RemoveTrackingArea (icon.TrackingArea);
right -= item.Bounds.Width + 6;
- item.Frame = new CGRect (right, 3, item.Bounds.Width, item.Bounds.Height);
+ item.Frame = new CGRect (right, MacSystemInformation.OsVersion >= MacSystemInformation.ElCapitan ? 4 : 3, item.Bounds.Width, item.Bounds.Height);
var area = new NSTrackingArea (item.Frame, NSTrackingAreaOptions.MouseEnteredAndExited | NSTrackingAreaOptions.ActiveInKeyWindow, this, null);
AddTrackingArea (area);
@@ -381,27 +387,17 @@ namespace MonoDevelop.MacIntegration.MainToolbar
long statusCounter;
public StatusBarIcon ShowStatusIcon (Xwt.Drawing.Image pixbuf)
{
- nfloat right = layerToStatus.Count == 0 ?
- Layer.Frame.Width :
- Layer.Sublayers.Last (i => i.Name != null && i.Name.StartsWith (StatusIconPrefixId, StringComparison.Ordinal)).Frame.Left;
-
- right -= (nfloat)pixbuf.Width + 6;
var layer = CALayer.Create ();
layer.Name = StatusIconPrefixId + (++statusCounter);
layer.Bounds = new CGRect (0, 0, (nfloat)pixbuf.Width, (nfloat)pixbuf.Height);
- layer.Frame = new CGRect (right, 3, (nfloat)pixbuf.Width, (nfloat)pixbuf.Height);
-
- var area = new NSTrackingArea (layer.Frame, NSTrackingAreaOptions.MouseEnteredAndExited | NSTrackingAreaOptions.ActiveInKeyWindow, this, null);
- AddTrackingArea (area);
-
- var statusIcon = new StatusIcon (this, layer, area) {
+ var statusIcon = new StatusIcon (this, layer, null) {
Image = pixbuf,
};
layerToStatus [layer.Name] = statusIcon;
Layer.AddSublayer (layer);
- textField.SetFrameSize (new CGSize (right - 6 - textField.Frame.Left, Frame.Height));
+ RepositionStatusLayers ();
return statusIcon;
}
@@ -456,18 +452,25 @@ namespace MonoDevelop.MacIntegration.MainToolbar
{
DispatchService.AssertGuiThread ();
- LoadText (message, isMarkup, color);
+ bool changed = LoadText (message, isMarkup, color);
LoadPixbuf (image);
- ReconstructString ();
+ if (changed)
+ ReconstructString (updateTrackingAreas: true);
}
- void LoadText (string message, bool isMarkup, NSColor color)
+ bool LoadText (string message, bool isMarkup, NSColor color)
{
message = message ?? "";
+ message = message.Replace (Environment.NewLine, " ").Replace ("\n", " ").Trim ();
+
+ if (message == text)
+ return false;
- text = message.Replace (Environment.NewLine, " ").Replace ("\n", " ").Trim ();
+ text = message;
currentTextIsMarkup = isMarkup;
textColor = color;
+
+ return true;
}
static bool iconLoaded;
@@ -496,7 +499,7 @@ namespace MonoDevelop.MacIntegration.MainToolbar
image = iconAnimation.FirstFrame.ToNSImage ();
xwtAnimation = iconAnimation.StartAnimation (p => {
image = p.ToNSImage ();
- ReconstructString ();
+ ReconstructString (updateTrackingAreas: false);
});
} else {
image = ImageService.GetIcon (iconId).ToNSImage ();
@@ -568,6 +571,7 @@ namespace MonoDevelop.MacIntegration.MainToolbar
}
static CGColor xamBlue = new CGColor (52f / 255, 152f / 255, 219f / 255);
+ static nfloat verticalOffset = MacSystemInformation.OsVersion >= MacSystemInformation.ElCapitan ? 2 : 0;
CALayer CreateProgressBarLayer (double width)
{
CALayer progress = ProgressLayer;
@@ -577,7 +581,7 @@ namespace MonoDevelop.MacIntegration.MainToolbar
progress.BackgroundColor = xamBlue;
progress.BorderColor = xamBlue;
progress.FillMode = CAFillMode.Forwards;
- progress.Frame = new CGRect (0, Frame.Height - barHeight, (nfloat)width, barHeight);
+ progress.Frame = new CGRect (0, Frame.Height - barHeight - verticalOffset, (nfloat)width, barHeight);
}
return progress;
}
@@ -711,13 +715,14 @@ namespace MonoDevelop.MacIntegration.MainToolbar
((NSTextField)popover.ContentViewController.View).AttributedStringValue = attrString;
}
- void CreatePopoverForLayer (CALayer layer)
+ bool CreatePopoverForLayer (CALayer layer)
{
string tooltip = layerToStatus [layer.Name].ToolTip;
if (tooltip == null)
- return;
+ return false;
CreatePopoverCommon (230, tooltip);
+ return true;
}
void CreatePopoverForStatusBar ()
@@ -733,7 +738,9 @@ namespace MonoDevelop.MacIntegration.MainToolbar
if (!layerToStatus.ContainsKey (layer.Name))
return;
- CreatePopoverForLayer (layer);
+ if (!CreatePopoverForLayer (layer))
+ return;
+
popover.Show (layer.Frame, this, NSRectEdge.MinYEdge);
}
diff --git a/main/src/addins/MacPlatform/icons/build.png b/main/src/addins/MacPlatform/icons/build.png
index a0c40fc091..60db083214 100644
--- a/main/src/addins/MacPlatform/icons/build.png
+++ b/main/src/addins/MacPlatform/icons/build.png
Binary files differ
diff --git a/main/src/addins/MacPlatform/icons/build@2x.png b/main/src/addins/MacPlatform/icons/build@2x.png
index 240baf14f5..7dfb19221b 100644
--- a/main/src/addins/MacPlatform/icons/build@2x.png
+++ b/main/src/addins/MacPlatform/icons/build@2x.png
Binary files differ
diff --git a/main/src/addins/MacPlatform/icons/continue.png b/main/src/addins/MacPlatform/icons/continue.png
index 393b1621bd..9d8db8c1cb 100644
--- a/main/src/addins/MacPlatform/icons/continue.png
+++ b/main/src/addins/MacPlatform/icons/continue.png
Binary files differ
diff --git a/main/src/addins/MacPlatform/icons/continue@2x.png b/main/src/addins/MacPlatform/icons/continue@2x.png
index 01099f61a6..1a74564c7d 100644
--- a/main/src/addins/MacPlatform/icons/continue@2x.png
+++ b/main/src/addins/MacPlatform/icons/continue@2x.png
Binary files differ
diff --git a/main/src/addins/MacPlatform/icons/device.png b/main/src/addins/MacPlatform/icons/device.png
index 52a605662d..51690547be 100644
--- a/main/src/addins/MacPlatform/icons/device.png
+++ b/main/src/addins/MacPlatform/icons/device.png
Binary files differ
diff --git a/main/src/addins/MacPlatform/icons/device@2x.png b/main/src/addins/MacPlatform/icons/device@2x.png
index ce96416250..a045e0817c 100644
--- a/main/src/addins/MacPlatform/icons/device@2x.png
+++ b/main/src/addins/MacPlatform/icons/device@2x.png
Binary files differ
diff --git a/main/src/addins/MacPlatform/icons/project.png b/main/src/addins/MacPlatform/icons/project.png
index f1246f7cf4..f25fdbfb2e 100644
--- a/main/src/addins/MacPlatform/icons/project.png
+++ b/main/src/addins/MacPlatform/icons/project.png
Binary files differ
diff --git a/main/src/addins/MacPlatform/icons/project@2x.png b/main/src/addins/MacPlatform/icons/project@2x.png
index 04e1fe7d90..e5e08d504f 100644
--- a/main/src/addins/MacPlatform/icons/project@2x.png
+++ b/main/src/addins/MacPlatform/icons/project@2x.png
Binary files differ
diff --git a/main/src/addins/MacPlatform/icons/stop.png b/main/src/addins/MacPlatform/icons/stop.png
index 1c83109ce3..62501d3cab 100644
--- a/main/src/addins/MacPlatform/icons/stop.png
+++ b/main/src/addins/MacPlatform/icons/stop.png
Binary files differ
diff --git a/main/src/addins/MacPlatform/icons/stop@2x.png b/main/src/addins/MacPlatform/icons/stop@2x.png
index 05db67ecd6..3870bc446d 100644
--- a/main/src/addins/MacPlatform/icons/stop@2x.png
+++ b/main/src/addins/MacPlatform/icons/stop@2x.png
Binary files differ
diff --git a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyBrowserWidget.cs b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyBrowserWidget.cs
index 8837388616..c1401c7094 100644
--- a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyBrowserWidget.cs
+++ b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyBrowserWidget.cs
@@ -1189,20 +1189,24 @@ namespace MonoDevelop.AssemblyBrowser
public void Open (string url, AssemblyLoader currentAssembly = null)
{
- ITreeNavigator nav = SearchMember (url);
- if (definitions == null) // we've been disposed
- return;
- if (nav != null)
- return;
- try {
- if (currentAssembly != null) {
- OpenFromAssembly (url, currentAssembly);
- } else {
- OpenFromAssemblyNames (url);
- }
- } catch (Exception e) {
- LoggingService.LogError ("Error while opening the assembly browser with id:" + url, e);
- }
+ Task.WhenAll (this.definitions.Select (d => d.LoadingTask).ToArray ()).ContinueWith (d => {
+ Application.Invoke (delegate {
+ ITreeNavigator nav = SearchMember (url);
+ if (definitions == null) // we've been disposed
+ return;
+ if (nav != null)
+ return;
+ try {
+ if (currentAssembly != null) {
+ OpenFromAssembly (url, currentAssembly);
+ } else {
+ OpenFromAssemblyNames (url);
+ }
+ } catch (Exception e) {
+ LoggingService.LogError ("Error while opening the assembly browser with id:" + url, e);
+ }
+ });
+ });
}
void OpenFromAssembly (string url, AssemblyLoader currentAssembly)
@@ -1456,7 +1460,7 @@ namespace MonoDevelop.AssemblyBrowser
result = new AssemblyLoader (this, fileName);
definitions.Add (result);
- result.LoadingTask.ContinueWith (delegate {
+ result.LoadingTask = result.LoadingTask.ContinueWith (task => {
Application.Invoke (delegate {
if (definitions == null)
return;
@@ -1474,8 +1478,9 @@ namespace MonoDevelop.AssemblyBrowser
LoggingService.LogError ("Error while adding assembly to the assembly list", e);
}
});
+ return task.Result;
}
- );
+ );
return result;
}
diff --git a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyLoader.cs b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyLoader.cs
index 9bf8d8fd83..d5859582ac 100644
--- a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyLoader.cs
+++ b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyLoader.cs
@@ -49,6 +49,9 @@ namespace MonoDevelop.AssemblyBrowser
get {
return assemblyLoaderTask;
}
+ set {
+ assemblyLoaderTask = value;
+ }
}
public AssemblyDefinition Assembly {
diff --git a/main/src/addins/MonoDevelop.Debugger.Soft/MonoDevelop.Debugger.Soft/SoftDebuggerEngine.cs b/main/src/addins/MonoDevelop.Debugger.Soft/MonoDevelop.Debugger.Soft/SoftDebuggerEngine.cs
index 9d9992d9e3..acdfd4e14a 100644
--- a/main/src/addins/MonoDevelop.Debugger.Soft/MonoDevelop.Debugger.Soft/SoftDebuggerEngine.cs
+++ b/main/src/addins/MonoDevelop.Debugger.Soft/MonoDevelop.Debugger.Soft/SoftDebuggerEngine.cs
@@ -138,6 +138,18 @@ namespace MonoDevelop.Debugger.Soft
class MDLogger : ICustomLogger
{
+ public string GetNewDebuggerLogFilename ()
+ {
+ if (PropertyService.Get ("MonoDevelop.Debugger.DebuggingService.DebuggerLogging", false)) {
+ string filename;
+ var logWriter = LoggingService.CreateLogFile ("Debugger", out filename);
+ logWriter.Dispose ();
+ return filename;
+ } else {
+ return null;
+ }
+ }
+
public void LogError (string message, Exception ex)
{
LoggingService.LogError (message, ex);
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests.NonUserCodeTestLib/MonoDevelop.Debugger.Tests.NonUserCodeTestLib.csproj b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests.NonUserCodeTestLib/MonoDevelop.Debugger.Tests.NonUserCodeTestLib.csproj
index 5de4c16d4a..a6ad6eb5a0 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests.NonUserCodeTestLib/MonoDevelop.Debugger.Tests.NonUserCodeTestLib.csproj
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests.NonUserCodeTestLib/MonoDevelop.Debugger.Tests.NonUserCodeTestLib.csproj
@@ -22,12 +22,13 @@
<ConsolePause>false</ConsolePause>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <DebugType>full</DebugType>
+ <DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
+ <DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests.TestApp/TestEvaluation.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests.TestApp/TestEvaluation.cs
index f620d07c58..13b590023a 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests.TestApp/TestEvaluation.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests.TestApp/TestEvaluation.cs
@@ -78,6 +78,28 @@ namespace MonoDevelop.Debugger.Tests.TestApp
{
return 6;
}
+
+ public override int OverridenMethodInt ()
+ {
+ return 6;
+ }
+
+ public override int OverridenPropertyInt {
+ get {
+ return 6;
+ }
+ }
+
+ public override string OverridenMethodString ()
+ {
+ return "6";
+ }
+
+ public override string OverridenPropertyString {
+ get {
+ return "6";
+ }
+ }
}
class TestEvaluation : TestEvaluationParent
@@ -166,6 +188,8 @@ namespace MonoDevelop.Debugger.Tests.TestApp
}
}
+ var testEvaluationChild = new TestEvaluationChild ();
+
Console.WriteLine (n); /*break*/
}
@@ -269,6 +293,28 @@ namespace MonoDevelop.Debugger.Tests.TestApp
{
return 5;
}
+
+ public virtual int OverridenMethodInt ()
+ {
+ return 5;
+ }
+
+ public virtual int OverridenPropertyInt {
+ get {
+ return 5;
+ }
+ }
+
+ public virtual string OverridenMethodString ()
+ {
+ return "5";
+ }
+
+ public virtual string OverridenPropertyString {
+ get {
+ return "5";
+ }
+ }
}
public class SomeClassInNamespace
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/DebugTests.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/DebugTests.cs
index 033e45bb70..6b2e752541 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/DebugTests.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/DebugTests.cs
@@ -224,6 +224,9 @@ namespace MonoDevelop.Debugger.Tests
default:
throw new Exception ("Timeout while waiting for initial breakpoint");
}
+ if (Session is SoftDebuggerSession) {
+ Console.WriteLine ("SDB protocol version:" + ((SoftDebuggerSession)Session).ProtocolVersion);
+ }
}
void GetLineAndColumn (string breakpointMarker, int offset, string statement, out int line, out int col)
@@ -401,6 +404,13 @@ namespace MonoDevelop.Debugger.Tests
static class EvalHelper
{
+ public static bool AtLeast (this Version ver, int major, int minor) {
+ if ((ver.Major > major) || ((ver.Major == major && ver.Minor >= minor)))
+ return true;
+ else
+ return false;
+ }
+
public static ObjectValue Sync (this ObjectValue val)
{
if (!val.IsEvaluating)
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/EvaluationTests.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/EvaluationTests.cs
index 9371dfa6f2..4f06ceae1d 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/EvaluationTests.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/EvaluationTests.cs
@@ -177,6 +177,11 @@ namespace MonoDevelop.Debugger.Tests
public virtual void HiddenMembers ()
{
IgnoreCorDebugger ("TODO");
+ if (Session is SoftDebuggerSession) {
+ if (!((SoftDebuggerSession)Session).ProtocolVersion.AtLeast (2, 40)) {
+ Assert.Ignore ("Need newer Mono with SDB protocol 2.40+");
+ }
+ }
ObjectValue val;
val = Eval ("HiddenField");
Assert.AreEqual ("5", val.Value);
@@ -203,6 +208,122 @@ namespace MonoDevelop.Debugger.Tests
}
Assert.AreEqual ("5", val.Value);
Assert.AreEqual ("int", val.TypeName);
+
+ val = Eval ("OverridenPropertyInt");
+ if (!AllowTargetInvokes) {
+ var options = Session.Options.EvaluationOptions.Clone ();
+ options.AllowTargetInvoke = true;
+
+ val.Refresh (options);
+ val = val.Sync ();
+ }
+ Assert.AreEqual ("6", val.Value);
+ Assert.AreEqual ("int", val.TypeName);
+
+ val = Eval ("OverridenMethodInt()");
+ if (!AllowTargetInvokes) {
+ var options = Session.Options.EvaluationOptions.Clone ();
+ options.AllowTargetInvoke = true;
+
+ val.Refresh (options);
+ val = val.Sync ();
+ }
+ Assert.AreEqual ("6", val.Value);
+ Assert.AreEqual ("int", val.TypeName);
+
+ val = Eval ("OverridenPropertyString");
+ if (!AllowTargetInvokes) {
+ var options = Session.Options.EvaluationOptions.Clone ();
+ options.AllowTargetInvoke = true;
+
+ val.Refresh (options);
+ val = val.Sync ();
+ }
+ Assert.AreEqual ("\"6\"", val.Value);
+ Assert.AreEqual ("string", val.TypeName);
+
+ val = Eval ("OverridenMethodString()");
+ if (!AllowTargetInvokes) {
+ var options = Session.Options.EvaluationOptions.Clone ();
+ options.AllowTargetInvoke = true;
+
+ val.Refresh (options);
+ val = val.Sync ();
+ }
+ Assert.AreEqual ("\"6\"", val.Value);
+ Assert.AreEqual ("string", val.TypeName);
+
+
+
+ val = Eval ("testEvaluationChild.HiddenField");
+ Assert.AreEqual ("6", val.Value);
+ Assert.AreEqual ("int", val.TypeName);
+
+ val = Eval ("testEvaluationChild.HiddenProperty");
+ if (!AllowTargetInvokes) {
+ var options = Session.Options.EvaluationOptions.Clone ();
+ options.AllowTargetInvoke = true;
+
+ val.Refresh (options);
+ val = val.Sync ();
+ }
+ Assert.AreEqual ("6", val.Value);
+ Assert.AreEqual ("int", val.TypeName);
+
+ val = Eval ("testEvaluationChild.HiddenMethod()");
+ if (!AllowTargetInvokes) {
+ var options = Session.Options.EvaluationOptions.Clone ();
+ options.AllowTargetInvoke = true;
+
+ val.Refresh (options);
+ val = val.Sync ();
+ }
+ Assert.AreEqual ("6", val.Value);
+ Assert.AreEqual ("int", val.TypeName);
+
+ val = Eval ("testEvaluationChild.OverridenPropertyInt");
+ if (!AllowTargetInvokes) {
+ var options = Session.Options.EvaluationOptions.Clone ();
+ options.AllowTargetInvoke = true;
+
+ val.Refresh (options);
+ val = val.Sync ();
+ }
+ Assert.AreEqual ("6", val.Value);
+ Assert.AreEqual ("int", val.TypeName);
+
+ val = Eval ("testEvaluationChild.OverridenMethodInt()");
+ if (!AllowTargetInvokes) {
+ var options = Session.Options.EvaluationOptions.Clone ();
+ options.AllowTargetInvoke = true;
+
+ val.Refresh (options);
+ val = val.Sync ();
+ }
+ Assert.AreEqual ("6", val.Value);
+ Assert.AreEqual ("int", val.TypeName);
+
+ val = Eval ("testEvaluationChild.OverridenPropertyString");
+ if (!AllowTargetInvokes) {
+ var options = Session.Options.EvaluationOptions.Clone ();
+ options.AllowTargetInvoke = true;
+
+ val.Refresh (options);
+ val = val.Sync ();
+ }
+ Assert.AreEqual ("\"6\"", val.Value);
+ Assert.AreEqual ("string", val.TypeName);
+
+ val = Eval ("testEvaluationChild.OverridenMethodString()");
+ if (!AllowTargetInvokes) {
+ var options = Session.Options.EvaluationOptions.Clone ();
+ options.AllowTargetInvoke = true;
+
+ val.Refresh (options);
+ val = val.Sync ();
+ }
+ Assert.AreEqual ("\"6\"", val.Value);
+ Assert.AreEqual ("string", val.TypeName);
}
[Test]
@@ -610,7 +731,7 @@ namespace MonoDevelop.Debugger.Tests
Assert.AreEqual ("bool", val.TypeName);
val = Eval ("alist.Count");
- if (!AllowTargetInvokes && soft == null) {
+ if (!AllowTargetInvokes) {
// Note: this is a simple property which gets evaluated client-side by the SDB backend
var options = Session.Options.EvaluationOptions.Clone ();
options.AllowTargetInvoke = true;
@@ -1659,7 +1780,7 @@ namespace MonoDevelop.Debugger.Tests
Assert.Ignore ("A newer version of the Mono runtime is required.");
val = Eval ("a.Prop");
- if (!AllowTargetInvokes && soft == null) {
+ if (!AllowTargetInvokes) {
var options = Session.Options.EvaluationOptions.Clone ();
options.AllowTargetInvoke = true;
@@ -1683,7 +1804,7 @@ namespace MonoDevelop.Debugger.Tests
Assert.AreEqual ("int", val.TypeName);
val = Eval ("a.PropNoVirt2");
- if (!AllowTargetInvokes && soft == null) {
+ if (!AllowTargetInvokes) {
var options = Session.Options.EvaluationOptions.Clone ();
options.AllowTargetInvoke = true;
@@ -1735,7 +1856,7 @@ namespace MonoDevelop.Debugger.Tests
Assert.AreEqual ("int", val.TypeName);
val = Eval ("b.Prop");
- if (!AllowTargetInvokes && soft == null) {
+ if (!AllowTargetInvokes) {
var options = Session.Options.EvaluationOptions.Clone ();
options.AllowTargetInvoke = true;
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.csproj b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.csproj
index 205a6ae228..9b8a936500 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.csproj
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.csproj
@@ -156,7 +156,6 @@
<Compile Include="MonoDevelop.Debugger\BusyEvaluatorDialog.cs" />
<Compile Include="gtk-gui\MonoDevelop.Debugger.BusyEvaluatorDialog.cs" />
<Compile Include="MonoDevelop.Debugger\DebuggerOptionsPanelWidget.cs" />
- <Compile Include="gtk-gui\MonoDevelop.Debugger.DebuggerOptionsPanelWidget.cs" />
<Compile Include="MonoDevelop.Debugger\PinnedWatch.cs" />
<Compile Include="MonoDevelop.Debugger\PinnedWatchStore.cs" />
<Compile Include="MonoDevelop.Debugger\DebuggerEngine.cs" />
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/AttachToProcessDialog.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/AttachToProcessDialog.cs
index 1b7865d396..946fdec8b8 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/AttachToProcessDialog.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/AttachToProcessDialog.cs
@@ -51,6 +51,7 @@ namespace MonoDevelop.Debugger
tree.Model = store;
tree.AppendColumn ("PID", new Gtk.CellRendererText (), "text", 1);
tree.AppendColumn ("Process Name", new Gtk.CellRendererText (), "text", 2);
+ tree.RowActivated += OnRowActivated;
state = new TreeViewState (tree, 1);
@@ -150,7 +151,7 @@ namespace MonoDevelop.Debugger
FillList ();
}
- protected virtual void OnRowActivated (object o, Gtk.RowActivatedArgs args)
+ void OnRowActivated (object o, Gtk.RowActivatedArgs args)
{
Respond (Gtk.ResponseType.Ok);
}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BreakpointPad.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BreakpointPad.cs
index f468753ed1..fe65568897 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BreakpointPad.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BreakpointPad.cs
@@ -397,6 +397,8 @@ namespace MonoDevelop.Debugger
if (breakpoints != null) {
lock (breakpoints) {
foreach (BreakEvent be in breakpoints.GetBreakevents ()) {
+ if (be.NonUserBreakpoint)
+ continue;
string hitCount = be.HitCountMode != HitCountMode.None ? be.CurrentHitCount.ToString () : "";
string traceExp = (be.HitAction & HitAction.PrintExpression) != HitAction.None ? be.TraceExpression : "";
string traceVal = (be.HitAction & HitAction.PrintExpression) != HitAction.None ? be.LastTraceValue : "";
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BusyEvaluatorDialog.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BusyEvaluatorDialog.cs
index e2f8a93769..d82779bcbc 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BusyEvaluatorDialog.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BusyEvaluatorDialog.cs
@@ -34,27 +34,24 @@ namespace MonoDevelop.Debugger
public BusyEvaluatorDialog ()
{
this.Build ();
+ //Prevent closing dialog via X button, user can either wait with
+ //dialog open or press "Stop Debugger" button
+ DeleteEvent += (o, args) => args.RetVal = true;
}
-
+
public void UpdateBusyState (BusyStateEventArgs args)
{
if (!args.IsBusy) {
Hide ();
} else {
- labelMethod.Text = args.Description;
Show ();
}
}
-
+
protected virtual void OnButtonCancelClicked (object sender, System.EventArgs e)
{
Hide ();
DebuggingService.Stop ();
}
-
- protected virtual void OnButtonOkClicked (object sender, System.EventArgs e)
- {
- Hide ();
- }
}
}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggerConsoleView.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggerConsoleView.cs
index d5b4d80774..f67ee7864a 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggerConsoleView.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggerConsoleView.cs
@@ -49,11 +49,21 @@ namespace MonoDevelop.Debugger
SetFont (IdeApp.Preferences.CustomOutputPadFont);
TextView.KeyReleaseEvent += OnEditKeyRelease;
+ TextView.FocusOutEvent += TextView_FocusOutEvent;
IdeApp.Preferences.CustomOutputPadFontChanged += OnCustomOutputPadFontChanged;
CompletionWindowManager.WindowClosed += OnCompletionWindowClosed;
}
+ void TextView_FocusOutEvent(object o, Gtk.FocusOutEventArgs args)
+ {
+ // On Windows code completion popup stays TopMost also when switching to other apps
+ // but on Mac code completion window hides and shows when focus goes out and back in
+ // so no need to hide it on Mac for better UX
+ if (MonoDevelop.Core.Platform.IsWindows)
+ CompletionWindowManager.HideWindow ();
+ }
+
public bool Editable {
get {
return TextView.Editable;
@@ -450,6 +460,7 @@ namespace MonoDevelop.Debugger
IdeApp.Preferences.CustomOutputPadFontChanged -= OnCustomOutputPadFontChanged;
CompletionWindowManager.WindowClosed -= OnCompletionWindowClosed;
CompletionWindowManager.HideWindow ();
+ TextView.FocusOutEvent -= TextView_FocusOutEvent;
base.OnDestroyed ();
}
}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggerOptionsPanelWidget.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggerOptionsPanelWidget.cs
index f4f86afdd1..85c5ef476b 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggerOptionsPanelWidget.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggerOptionsPanelWidget.cs
@@ -1,4 +1,4 @@
-//
+//
// DebuggerOptionsPanelWidget.cs
//
// Author:
@@ -24,30 +24,81 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
+using System;
using Mono.Debugging.Client;
using MonoDevelop.Ide.Gui.Dialogs;
+using Xwt;
+using MonoDevelop.Core;
namespace MonoDevelop.Debugger
{
- public class DebuggerOptionsPanel: OptionsPanel
+ public class DebuggerOptionsPanel : OptionsPanel
{
DebuggerOptionsPanelWidget w;
-
+
public override Gtk.Widget CreatePanelWidget ()
{
- return w = new DebuggerOptionsPanelWidget ();
+ w = new DebuggerOptionsPanelWidget ();
+
+ return (Gtk.Widget)Toolkit.CurrentEngine.GetNativeWidget (w);
}
-
+
public override void ApplyChanges ()
{
w.Store ();
}
}
- [System.ComponentModel.ToolboxItem(true)]
- public partial class DebuggerOptionsPanelWidget : Gtk.Bin
+ public class DebuggerOptionsPanelWidget : VBox
{
DebuggerSessionOptions options;
+ CheckBox checkProjectCodeOnly;
+ CheckBox checkStepOverPropertiesAndOperators;
+ CheckBox checkAllowEval;
+ CheckBox checkAllowToString;
+ CheckBox checkShowBaseGroup;
+ CheckBox checkGroupPrivate;
+ CheckBox checkGroupStatic;
+ SpinButton spinTimeout;
+ CheckBox enableLogging;
+
+ void Build ()
+ {
+ checkProjectCodeOnly = new CheckBox (GettextCatalog.GetString ("Debug project code only; do not step into framework code."));
+ PackStart (checkProjectCodeOnly);
+ checkStepOverPropertiesAndOperators = new CheckBox (GettextCatalog.GetString ("Step over properties and operators"));
+ PackStart (checkStepOverPropertiesAndOperators);
+ checkAllowEval = new CheckBox (GettextCatalog.GetString ("Allow implicit property evaluation and method invocation"));
+ checkAllowEval.Toggled += OnCheckAllowEvalToggled;
+ PackStart (checkAllowEval);
+ checkAllowToString = new CheckBox (GettextCatalog.GetString ("Call string-conversion function on objects in variables windows"));
+ checkAllowToString.MarginLeft = 18;
+ PackStart (checkAllowToString);
+ checkShowBaseGroup = new CheckBox (GettextCatalog.GetString ("Show inherited class members in a base class group"));
+ PackStart (checkShowBaseGroup);
+ checkGroupPrivate = new CheckBox (GettextCatalog.GetString ("Group non-public members"));
+ PackStart (checkGroupPrivate);
+ checkGroupStatic = new CheckBox (GettextCatalog.GetString ("Group static members"));
+ PackStart (checkGroupStatic);
+ var evalBox = new HBox ();
+ evalBox.PackStart (new Label (GettextCatalog.GetString ("Evaluation Timeout:")));
+ spinTimeout = new SpinButton ();
+ spinTimeout.ClimbRate = 100;
+ spinTimeout.Digits = 0;
+ spinTimeout.IncrementValue = 100;
+ spinTimeout.MaximumValue = 1000000;
+ spinTimeout.MinimumValue = 0;
+ spinTimeout.Wrap = false;
+ spinTimeout.WidthRequest = 80;
+ evalBox.PackStart (spinTimeout);
+ evalBox.PackStart (new Label (GettextCatalog.GetString ("ms")));
+ PackStart (evalBox);
+ PackStart (new Label () {
+ Markup = "<b>" + GettextCatalog.GetString ("Advanced options") + "</b>"
+ });
+ enableLogging = new CheckBox (GettextCatalog.GetString ("Enable diagnostic logging", BrandingService.ApplicationName));
+ PackStart (enableLogging);
+ }
public DebuggerOptionsPanelWidget ()
{
@@ -63,6 +114,7 @@ namespace MonoDevelop.Debugger
checkGroupStatic.Active = options.EvaluationOptions.GroupStaticMembers;
checkAllowToString.Sensitive = checkAllowEval.Active;
spinTimeout.Value = options.EvaluationOptions.EvaluationTimeout;
+ enableLogging.Active = PropertyService.Get ("MonoDevelop.Debugger.DebuggingService.DebuggerLogging", false);
}
public void Store ()
@@ -74,13 +126,14 @@ namespace MonoDevelop.Debugger
ops.FlattenHierarchy = !checkShowBaseGroup.Active;
ops.GroupPrivateMembers = checkGroupPrivate.Active;
ops.GroupStaticMembers = checkGroupStatic.Active;
- ops.EvaluationTimeout = (int) spinTimeout.Value;
+ ops.EvaluationTimeout = (int)spinTimeout.Value;
options.StepOverPropertiesAndOperators = checkStepOverPropertiesAndOperators.Active;
options.ProjectAssembliesOnly = checkProjectCodeOnly.Active;
options.EvaluationOptions = ops;
DebuggingService.SetUserOptions (options);
+ PropertyService.Set ("MonoDevelop.Debugger.DebuggingService.DebuggerLogging", enableLogging.Active);
}
protected virtual void OnCheckAllowEvalToggled (object sender, System.EventArgs e)
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs
index abb2d6544f..3422b1cf87 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs
@@ -98,6 +98,7 @@ namespace MonoDevelop.Debugger
IdeApp.Workspace.LoadingUserPreferences += OnLoadUserPrefs;
IdeApp.Workspace.LastWorkspaceItemClosed += OnSolutionClosed;
busyDialog = new BusyEvaluatorDialog ();
+ busyDialog.Modal = true;
busyDialog.TransientFor = MessageService.RootWindow;
busyDialog.DestroyWithParent = true;
};
@@ -706,7 +707,7 @@ namespace MonoDevelop.Debugger
if (busyStatusIcon == null) {
busyStatusIcon = IdeApp.Workbench.StatusBar.ShowStatusIcon (ImageService.GetIcon ("md-execute-debug", Gtk.IconSize.Menu));
busyStatusIcon.SetAlertMode (100);
- busyStatusIcon.ToolTip = GettextCatalog.GetString ("The Debugger is waiting for an expression evaluation to finish.");
+ busyStatusIcon.ToolTip = GettextCatalog.GetString ("The debugger runtime is not responding. You can wait for it to recover, or stop debugging.");
busyStatusIcon.Clicked += delegate {
MessageService.PlaceDialog (busyDialog, MessageService.RootWindow);
};
@@ -744,6 +745,8 @@ namespace MonoDevelop.Debugger
static void OnTargetEvent (object sender, TargetEventArgs args)
{
+ if (args.BreakEvent != null && args.BreakEvent.NonUserBreakpoint)
+ return;
nextStatementLocations.Clear ();
try {
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DisassemblyView.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DisassemblyView.cs
index 90973bb76f..c5d9ba351e 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DisassemblyView.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DisassemblyView.cs
@@ -45,6 +45,7 @@ using MonoDevelop.Ide;
using System.Security.Cryptography;
using Gdk;
using MonoDevelop.Components;
+using MonoDevelop.Components.Extensions;
namespace MonoDevelop.Debugger
{
@@ -127,7 +128,7 @@ namespace MonoDevelop.Debugger
messageOverlayWindow.SizeFunc = () => openButton.SizeRequest ().Width + w + hbox.Spacing * 5 + containerPadding * 2;
openButton.Clicked += delegate {
- var dlg = new OpenFileDialog (GettextCatalog.GetString ("File to Open"), Gtk.FileChooserAction.Open) {
+ var dlg = new OpenFileDialog (GettextCatalog.GetString ("File to Open"), SelectFileDialogAction.Open) {
TransientFor = IdeApp.Workbench.RootWindow,
ShowEncodingSelector = true,
ShowViewerSelector = true
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Extensions.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Extensions.cs
index cea2001d16..8ce3fe3f98 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Extensions.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Extensions.cs
@@ -51,7 +51,6 @@ namespace MonoDevelop.Debugger
ExecutionContext context = new ExecutionContext (DebuggingService.GetExecutionHandler (), IdeApp.Workbench.ProgressMonitors, IdeApp.Workspace.ActiveExecutionTarget);
IAsyncOperation op = opers.Execute (entry, context);
- SwitchToDebugLayout (op);
return op;
}
@@ -72,17 +71,11 @@ namespace MonoDevelop.Debugger
if (opers.CurrentRunOperation != null && !opers.CurrentRunOperation.IsCompleted)
return opers.CurrentRunOperation;
- string oldLayout = IdeApp.Workbench.CurrentLayout;
- IdeApp.Workbench.CurrentLayout = "Debug";
-
var monitor = IdeApp.Workbench.ProgressMonitors.GetRunProgressMonitor ();
var oper = DebuggingService.Run (executableFile, args, workingDir, envVars, (IConsole) monitor);
oper.Completed += delegate {
monitor.Dispose ();
- Gtk.Application.Invoke (delegate {
- IdeApp.Workbench.CurrentLayout = oldLayout;
- });
};
opers.CurrentRunOperation = monitor.AsyncOperation;
@@ -95,7 +88,6 @@ namespace MonoDevelop.Debugger
return opers.CurrentRunOperation;
var oper = DebuggingService.AttachToProcess (debugger, proc);
- SwitchToDebugLayout (oper);
opers.CurrentRunOperation = oper;
return opers.CurrentRunOperation;
@@ -110,17 +102,5 @@ namespace MonoDevelop.Debugger
{
return doc.FileName != FilePath.Null && IdeApp.ProjectOperations.CanDebugFile (doc.FileName);
}
-
- static void SwitchToDebugLayout (IAsyncOperation oper)
- {
- string oldLayout = IdeApp.Workbench.CurrentLayout;
- IdeApp.Workbench.CurrentLayout = "Debug";
-
- oper.Completed += delegate {
- DispatchService.GuiDispatch (delegate {
- IdeApp.Workbench.CurrentLayout = oldLayout;
- });
- };
- }
}
}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/LocalsPad.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/LocalsPad.cs
index f9355b83d6..feb6d9c0c3 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/LocalsPad.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/LocalsPad.cs
@@ -28,103 +28,29 @@
using System;
using Mono.Debugging.Client;
using System.Collections.Generic;
+using System.Linq;
namespace MonoDevelop.Debugger
{
public class LocalsPad : ObjectValuePad
{
- Dictionary<string, ObjectValue> lastLookup = new Dictionary<string, ObjectValue> ();
- StackFrame lastFrame;
-
public LocalsPad ()
{
tree.AllowEditing = true;
tree.AllowAdding = false;
}
- protected override void OnDebuggerStopped (object s, EventArgs a)
- {
- lastLookup = null;
- lastFrame = null;
- base.OnDebuggerStopped (s, a);
- }
-
public override void OnUpdateList ()
{
base.OnUpdateList ();
var frame = DebuggingService.CurrentFrame;
- if (frame == null || !FrameEquals (frame, lastFrame)) {
- tree.ClearExpressions ();
- lastLookup = null;
- }
-
- lastFrame = frame;
-
if (frame == null)
return;
- //add expressions not in tree already, remove expressions that are longer valid
- var frameLocals = frame.GetAllLocals ();
- var lookup = new Dictionary<string, ObjectValue> (frameLocals.Length);
-
- foreach (var local in frameLocals) {
- var variableName = local.Name;
-
- //not sure if there is a use case for duplicate variable names, or blanks
- if (string.IsNullOrWhiteSpace (variableName) || variableName == "?" || lookup.ContainsKey (variableName))
- continue;
-
- lookup.Add (variableName, local);
-
- if (lastLookup != null) {
- ObjectValue priorValue;
- if (lastLookup.TryGetValue (variableName, out priorValue))
- tree.ReplaceValue (priorValue, local);
- else
- tree.AddValue (local);
- }
- }
-
- if (lastLookup != null) {
- //get rid of the values that didnt survive from the last refresh
- foreach (var prior in lastLookup) {
- if (!lookup.ContainsKey (prior.Key))
- tree.RemoveValue (prior.Value);
- }
- } else {
- tree.ClearValues ();
- tree.AddValues (lookup.Values);
- }
-
- lastLookup = lookup;
- }
-
- static bool FrameEquals (StackFrame a, StackFrame z)
- {
- if (null == a || null == z)
- return a == z;
-
- if (a.SourceLocation == null || z.SourceLocation == null)
- return a.SourceLocation == z.SourceLocation;
-
- if (a.SourceLocation.FileName == null) {
- if (z.SourceLocation.FileName != null)
- return false;
- } else {
- if (!a.SourceLocation.FileName.Equals (z.SourceLocation.FileName, StringComparison.Ordinal))
- return false;
- }
-
- if (a.SourceLocation.MethodName == null) {
- if (z.SourceLocation.MethodName != null)
- return false;
-
- return true;
- }
-
- return a.SourceLocation.MethodName.Equals (z.SourceLocation.MethodName, StringComparison.Ordinal);
+ tree.ClearAll ();
+ tree.AddValues (frame.GetAllLocals ().Where (l => !string.IsNullOrWhiteSpace (l.Name) && l.Name != "?").ToArray ());
}
}
}
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValueTreeView.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValueTreeView.cs
index 8529a2ead9..da3940e4b1 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValueTreeView.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ObjectValueTreeView.cs
@@ -1232,7 +1232,7 @@ namespace MonoDevelop.Debugger
if (hasChildren) {
// Add dummy node
- store.AppendValues (it, GettextCatalog.GetString ("Loading..."), "", "", null, true);
+ store.AppendValues (it, GettextCatalog.GetString ("Loading..."), "", "", null, false);
if (!ShowExpanders)
ShowExpanders = true;
valPath += "/";
diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/StackTracePad.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/StackTracePad.cs
index 36f2ec250e..97164a0ca5 100644
--- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/StackTracePad.cs
+++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/StackTracePad.cs
@@ -41,6 +41,7 @@ using MonoDevelop.Ide.Gui.Components;
using MonoDevelop.Components.Commands;
using Stock = MonoDevelop.Ide.Gui.Stock;
using MonoDevelop.Components;
+using System.Linq;
namespace MonoDevelop.Debugger
{
@@ -55,10 +56,7 @@ namespace MonoDevelop.Debugger
const int StyleColumn = 6;
const int FrameColumn = 7;
const int FrameIndexColumn = 8;
- const int CanRefreshColumn = 9;
- readonly CellRendererImage refresh;
- readonly CommandEntrySet menuSet;
readonly PadTreeView tree;
readonly ListStore store;
IPadWindow window;
@@ -70,17 +68,7 @@ namespace MonoDevelop.Debugger
{
this.ShadowType = ShadowType.None;
- var evalCmd = new ActionCommand ("StackTracePad.EvaluateMethodParams", GettextCatalog.GetString ("Evaluate Method Parameters"));
- var gotoCmd = new ActionCommand ("StackTracePad.ActivateFrame", GettextCatalog.GetString ("Activate Stack Frame"));
-
- menuSet = new CommandEntrySet ();
- menuSet.Add (evalCmd);
- menuSet.Add (gotoCmd);
- menuSet.AddSeparator ();
- menuSet.AddItem (EditCommands.SelectAll);
- menuSet.AddItem (EditCommands.Copy);
-
- store = new ListStore (typeof (bool), typeof (string), typeof (string), typeof (string), typeof (string), typeof (string), typeof (Pango.Style), typeof (object), typeof (int), typeof (bool));
+ store = new ListStore (typeof(bool), typeof(string), typeof(string), typeof(string), typeof(string), typeof(string), typeof(Pango.Style), typeof(object), typeof(int), typeof(bool));
tree = new PadTreeView (store);
tree.RulesHint = true;
@@ -89,7 +77,6 @@ namespace MonoDevelop.Debugger
tree.SearchEqualFunc = Search;
tree.EnableSearch = true;
tree.SearchColumn = 1;
- tree.ButtonPressEvent += HandleButtonPressEvent;
tree.DoPopupMenu = ShowPopup;
var col = new TreeViewColumn ();
@@ -101,10 +88,6 @@ namespace MonoDevelop.Debugger
col = new TreeViewColumn ();
col.Title = GettextCatalog.GetString ("Name");
- refresh = new CellRendererImage ();
- refresh.Image = ImageService.GetIcon (Gtk.Stock.Refresh).WithSize (12, 12);
- col.PackStart (refresh, false);
- col.AddAttribute (refresh, "visible", CanRefreshColumn);
col.PackStart (tree.TextRenderer, true);
col.AddAttribute (tree.TextRenderer, "text", MethodColumn);
col.AddAttribute (tree.TextRenderer, "foreground", ForegroundColumn);
@@ -125,6 +108,7 @@ namespace MonoDevelop.Debugger
col.PackStart (tree.TextRenderer, false);
col.AddAttribute (tree.TextRenderer, "text", LangColumn);
col.AddAttribute (tree.TextRenderer, "foreground", ForegroundColumn);
+ col.Visible = false;//By default Language column is hidden
tree.AppendColumn (col);
col = new TreeViewColumn ();
@@ -132,9 +116,14 @@ namespace MonoDevelop.Debugger
col.PackStart (tree.TextRenderer, false);
col.AddAttribute (tree.TextRenderer, "text", AddrColumn);
col.AddAttribute (tree.TextRenderer, "foreground", ForegroundColumn);
+ col.Visible = false;//By default Address column is hidden
tree.AppendColumn (col);
Add (tree);
+
+ LoadColumnsVisibility ();
+ LoadSettings ();
+
ShowAll ();
UpdateDisplay ();
@@ -143,21 +132,63 @@ namespace MonoDevelop.Debugger
DebuggingService.StoppedEvent += OnDebuggingServiceStopped;
tree.RowActivated += OnRowActivated;
+ }
+
+ bool ShowModuleName;
+ bool ShowParameterType;
+ bool ShowParameterName;
+ bool ShowParameterValue;
+ bool ShowLineNumber;
+
+ void LoadSettings ()
+ {
+ ShowModuleName = PropertyService.Get ("Monodevelop.StackTrace.ShowModuleName", false);
+ ShowParameterType = PropertyService.Get ("Monodevelop.StackTrace.ShowParameterType", true);
+ ShowParameterName = PropertyService.Get ("Monodevelop.StackTrace.ShowParameterName", true);
+ ShowParameterValue = PropertyService.Get ("Monodevelop.StackTrace.ShowParameterValue", false);
+ ShowLineNumber = PropertyService.Get ("Monodevelop.StackTrace.ShowLineNumber", true);
+ }
+
+ void StoreSettings ()
+ {
+ PropertyService.Set ("Monodevelop.StackTrace.ShowModuleName", ShowModuleName);
+ PropertyService.Set ("Monodevelop.StackTrace.ShowParameterType", ShowParameterType);
+ PropertyService.Set ("Monodevelop.StackTrace.ShowParameterName", ShowParameterName);
+ PropertyService.Set ("Monodevelop.StackTrace.ShowParameterValue", ShowParameterValue);
+ PropertyService.Set ("Monodevelop.StackTrace.ShowLineNumber", ShowLineNumber);
+ }
+
+ void LoadColumnsVisibility ()
+ {
+ var columns = PropertyService.Get ("Monodevelop.StackTrace.ColumnsVisibility", "");
+ var tokens = columns.Split (new [] { ';' }, StringSplitOptions.RemoveEmptyEntries);
+ if (tree.Columns.Length == tokens.Length) {
+ for (int i = 0; i < tokens.Length; i++) {
+ bool visible;
+ if (bool.TryParse (tokens [i], out visible))
+ tree.Columns [i].Visible = visible;
+ }
+ }
+ }
+
+ void StoreColumnsVisibility ()
+ {
+ PropertyService.Set ("Monodevelop.StackTrace.ColumnsVisibility", string.Join (";", tree.Columns.Select (c => c.Visible ? "TRUE" : "FALSE")));
}
- void OnDebuggingServiceStopped(object sender, EventArgs e)
+ void OnDebuggingServiceStopped (object sender, EventArgs e)
{
- if (store != null)
- store.Clear();
+ if (store != null)
+ store.Clear ();
}
static bool Search (TreeModel model, int column, string key, TreeIter iter)
{
- string value = (string) model.GetValue (iter, column);
+ string value = (string)model.GetValue (iter, column);
return !value.Contains (key);
}
-
+
void IPadContent.Initialize (IPadWindow window)
{
this.window = window;
@@ -175,22 +206,51 @@ namespace MonoDevelop.Debugger
needsUpdate = true;
}
- static string EvaluateMethodName (StackFrame frame, EvaluationOptions options)
+ string EvaluateMethodName (StackFrame frame)
{
- var method = new StringBuilder (frame.SourceLocation.MethodName);
+ var methodNameBuilder = new StringBuilder (frame.SourceLocation.MethodName);
+ var options = DebuggingService.DebuggerSession.Options.EvaluationOptions.Clone ();
+ if (ShowParameterValue) {
+ options.AllowMethodEvaluation = true;
+ options.AllowToStringCalls = true;
+ options.AllowTargetInvoke = true;
+ } else {
+ options.AllowMethodEvaluation = false;
+ options.AllowToStringCalls = false;
+ options.AllowTargetInvoke = false;
+ }
+
var args = frame.GetParameters (options);
- if (args.Length != 0 || !frame.SourceLocation.MethodName.StartsWith ("[", StringComparison.Ordinal)) {
- method.Append (" (");
- for (int n = 0; n < args.Length; n++) {
- if (n > 0)
- method.Append (", ");
- method.Append (args[n].Name).Append ("=").Append (args[n].Value);
+ //MethodName starting with "["... it's something like [ExternalCode]
+ if (!frame.SourceLocation.MethodName.StartsWith ("[", StringComparison.Ordinal)) {
+ if (ShowModuleName && !string.IsNullOrEmpty (frame.FullModuleName)) {
+ methodNameBuilder.Insert (0, System.IO.Path.GetFileName (frame.FullModuleName) + "!");
+ }
+ if (ShowParameterType || ShowParameterName || ShowParameterValue) {
+ methodNameBuilder.Append ("(");
+ for (int n = 0; n < args.Length; n++) {
+ if (n > 0)
+ methodNameBuilder.Append (", ");
+ if (ShowParameterType) {
+ methodNameBuilder.Append (args [n].TypeName);
+ if (ShowParameterName)
+ methodNameBuilder.Append (" ");
+ }
+ if (ShowParameterName)
+ methodNameBuilder.Append (args [n].Name);
+ if (ShowParameterValue) {
+ if (ShowParameterType || ShowParameterName)
+ methodNameBuilder.Append (" = ");
+ var val = args [n].Value ?? "";
+ methodNameBuilder.Append (val.Replace ("\r\n", " ").Replace ("\n", " "));
+ }
+ }
+ methodNameBuilder.Append (")");
}
- method.Append (")");
}
- return method.ToString ();
+ return methodNameBuilder.ToString ();
}
void Update ()
@@ -204,7 +264,6 @@ namespace MonoDevelop.Debugger
if (!DebuggingService.IsPaused)
return;
- var options = DebuggingService.DebuggerSession.Options.EvaluationOptions;
var backtrace = DebuggingService.CurrentCallStack;
for (int i = 0; i < backtrace.FrameCount; i++) {
@@ -214,12 +273,12 @@ namespace MonoDevelop.Debugger
if (frame.IsDebuggerHidden)
continue;
- var method = EvaluateMethodName (frame, options);
+ var method = EvaluateMethodName (frame);
string file;
if (!string.IsNullOrEmpty (frame.SourceLocation.FileName)) {
file = frame.SourceLocation.FileName;
- if (frame.SourceLocation.Line != -1)
+ if (frame.SourceLocation.Line != -1 && ShowLineNumber)
file += ":" + frame.SourceLocation.Line;
} else {
file = string.Empty;
@@ -228,7 +287,7 @@ namespace MonoDevelop.Debugger
var style = frame.IsExternalCode ? Pango.Style.Italic : Pango.Style.Normal;
store.AppendValues (icon, method, file, frame.Language, "0x" + frame.Address.ToString ("x"), null,
- style, frame, i, !options.AllowDisplayStringEvaluation);
+ style, frame, i);
}
}
@@ -253,33 +312,6 @@ namespace MonoDevelop.Debugger
return false;
}
- [GLib.ConnectBefore]
- void HandleButtonPressEvent (object sender, ButtonPressEventArgs args)
- {
- TreeViewColumn col;
- CellRenderer cr;
- TreePath path;
- TreeIter iter;
-
- if (args.Event.Button != 1 || !GetCellAtPos ((int) args.Event.X, (int) args.Event.Y, out path, out col, out cr))
- return;
-
- if (!store.GetIter (out iter, path))
- return;
-
- if (cr == refresh) {
- var options = DebuggingService.DebuggerSession.Options.EvaluationOptions.Clone ();
- options.AllowMethodEvaluation = true;
- options.AllowToStringCalls = true;
-
- var frame = (StackFrame) store.GetValue (iter, FrameColumn);
- var method = EvaluateMethodName (frame, options);
-
- store.SetValue (iter, MethodColumn, method);
- store.SetValue (iter, CanRefreshColumn, false);
- }
- }
-
public void UpdateCurrentFrame ()
{
TreeIter iter;
@@ -288,7 +320,7 @@ namespace MonoDevelop.Debugger
return;
do {
- int frame = (int) store.GetValue (iter, FrameIndexColumn);
+ int frame = (int)store.GetValue (iter, FrameIndexColumn);
if (frame == DebuggingService.CurrentFrameIndex)
store.SetValue (iter, IconColumn, true);
@@ -306,7 +338,7 @@ namespace MonoDevelop.Debugger
{
UpdateDisplay ();
}
-
+
void OnRowActivated (object o, RowActivatedArgs args)
{
ActivateFrame ();
@@ -333,49 +365,114 @@ namespace MonoDevelop.Debugger
void ShowPopup (Gdk.EventButton evt)
{
- IdeApp.CommandService.ShowContextMenu (tree, evt, menuSet, tree);
- }
+ var context_menu = new ContextMenu ();
+ context_menu.Items.Add (new SeparatorContextMenuItem ());
+ var selectAllItem = new ContextMenuItem (GettextCatalog.GetString ("Select All"));
+ selectAllItem.Clicked += delegate {
+ OnSelectAll ();
+ };
+ context_menu.Items.Add (selectAllItem);
+ var copyItem = new ContextMenuItem (GettextCatalog.GetString ("Copy"));
+ copyItem.Clicked += delegate {
+ OnCopy ();
+ };
+ context_menu.Items.Add (copyItem);
- [CommandHandler ("StackTracePad.EvaluateMethodParams")]
- void EvaluateMethodParams ()
- {
- TreeIter iter;
+ context_menu.Items.Add (new SeparatorContextMenuItem ());
- if (!store.GetIterFirst (out iter))
- return;
+ var assemblyCheckbox = new CheckBoxContextMenuItem (GettextCatalog.GetString ("Show Module Name"));
+ assemblyCheckbox.Clicked += delegate {
+ assemblyCheckbox.Checked = ShowModuleName = !ShowModuleName;
+ StoreSettings ();
+ UpdateDisplay ();
+ };
+ assemblyCheckbox.Checked = ShowModuleName;
+ context_menu.Items.Add (assemblyCheckbox);
+ var typeCheckbox = new CheckBoxContextMenuItem (GettextCatalog.GetString ("Show Parameter Type"));
+ typeCheckbox.Clicked += delegate {
+ typeCheckbox.Checked = ShowParameterType = !ShowParameterType;
+ StoreSettings ();
+ UpdateDisplay ();
+ };
+ typeCheckbox.Checked = ShowParameterType;
+ context_menu.Items.Add (typeCheckbox);
+ var nameCheckbox = new CheckBoxContextMenuItem (GettextCatalog.GetString ("Show Parameter Name"));
+ nameCheckbox.Clicked += delegate {
+ nameCheckbox.Checked = ShowParameterName = !ShowParameterName;
+ StoreSettings ();
+ UpdateDisplay ();
+ };
+ nameCheckbox.Checked = ShowParameterName;
+ context_menu.Items.Add (nameCheckbox);
+ var valueCheckbox = new CheckBoxContextMenuItem (GettextCatalog.GetString ("Show Parameter Value"));
+ valueCheckbox.Clicked += delegate {
+ valueCheckbox.Checked = ShowParameterValue = !ShowParameterValue;
+ StoreSettings ();
+ UpdateDisplay ();
+ };
+ valueCheckbox.Checked = ShowParameterValue;
+ context_menu.Items.Add (valueCheckbox);
+ var lineCheckbox = new CheckBoxContextMenuItem (GettextCatalog.GetString ("Show Line Number"));
+ lineCheckbox.Clicked += delegate {
+ lineCheckbox.Checked = ShowLineNumber = !ShowLineNumber;
+ StoreSettings ();
+ UpdateDisplay ();
+ };
+ lineCheckbox.Checked = ShowLineNumber;
+ context_menu.Items.Add (lineCheckbox);
- var options = DebuggingService.DebuggerSession.Options.EvaluationOptions.Clone ();
- options.AllowMethodEvaluation = true;
- options.AllowToStringCalls = true;
- options.AllowTargetInvoke = true;
+ context_menu.Items.Add (new SeparatorContextMenuItem ());
- do {
- if ((bool) store.GetValue (iter, CanRefreshColumn)) {
- var frame = (StackFrame) store.GetValue (iter, FrameColumn);
- var method = EvaluateMethodName (frame, options);
+ var columnsVisibilitySubMenu = new ContextMenu ();
+ var nameColumnVisibilityCheckbox = new CheckBoxContextMenuItem (GettextCatalog.GetString ("Name"));
+ nameColumnVisibilityCheckbox.Clicked += delegate {
+ nameColumnVisibilityCheckbox.Checked = tree.Columns [MethodColumn].Visible = !tree.Columns [MethodColumn].Visible;
+ StoreColumnsVisibility ();
+ };
+ nameColumnVisibilityCheckbox.Checked = tree.Columns [MethodColumn].Visible;
+ columnsVisibilitySubMenu.Items.Add (nameColumnVisibilityCheckbox);
+ var fileColumnVisibilityCheckbox = new CheckBoxContextMenuItem (GettextCatalog.GetString ("File"));
+ fileColumnVisibilityCheckbox.Clicked += delegate {
+ fileColumnVisibilityCheckbox.Checked = tree.Columns [FileColumn].Visible = !tree.Columns [FileColumn].Visible;
+ StoreColumnsVisibility ();
+ };
+ fileColumnVisibilityCheckbox.Checked = tree.Columns [FileColumn].Visible;
+ columnsVisibilitySubMenu.Items.Add (fileColumnVisibilityCheckbox);
+ var languageColumnVisibilityCheckbox = new CheckBoxContextMenuItem (GettextCatalog.GetString ("Language"));
+ languageColumnVisibilityCheckbox.Clicked += delegate {
+ languageColumnVisibilityCheckbox.Checked = tree.Columns [LangColumn].Visible = !tree.Columns [LangColumn].Visible;
+ StoreColumnsVisibility ();
+ };
+ languageColumnVisibilityCheckbox.Checked = tree.Columns [LangColumn].Visible;
+ columnsVisibilitySubMenu.Items.Add (languageColumnVisibilityCheckbox);
+ var addressColumnVisibilityCheckbox = new CheckBoxContextMenuItem (GettextCatalog.GetString ("Address"));
+ addressColumnVisibilityCheckbox.Clicked += delegate {
+ addressColumnVisibilityCheckbox.Checked = tree.Columns [AddrColumn].Visible = !tree.Columns [AddrColumn].Visible;
+ StoreColumnsVisibility ();
+ };
+ addressColumnVisibilityCheckbox.Checked = tree.Columns [AddrColumn].Visible;
+ columnsVisibilitySubMenu.Items.Add (addressColumnVisibilityCheckbox);
+ context_menu.Items.Add (new ContextMenuItem (GettextCatalog.GetString ("Columns")){ SubMenu = columnsVisibilitySubMenu });
- store.SetValue (iter, MethodColumn, method);
- store.SetValue (iter, CanRefreshColumn, false);
- }
- } while (store.IterNext (ref iter));
+
+ context_menu.Show (this, evt);
}
- [CommandHandler ("StackTracePad.ActivateFrame")]
void ActivateFrame ()
{
var selected = tree.Selection.GetSelectedRows ();
TreeIter iter;
- if (selected.Length > 0 && store.GetIter (out iter, selected[0]))
- DebuggingService.CurrentFrameIndex = (int) store.GetValue (iter, FrameIndexColumn);
+ if (selected.Length > 0 && store.GetIter (out iter, selected [0]))
+ DebuggingService.CurrentFrameIndex = (int)store.GetValue (iter, FrameIndexColumn);
}
-
+
[CommandHandler (EditCommands.SelectAll)]
internal void OnSelectAll ()
{
tree.Selection.SelectAll ();
}
-
+
[CommandHandler (EditCommands.Copy)]
internal void OnCopy ()
{
@@ -387,11 +484,11 @@ namespace MonoDevelop.Debugger
if (!model.GetIter (out iter, path))
continue;
- string method = (string) model.GetValue (iter, MethodColumn);
- string file = (string) model.GetValue (iter, FileColumn);
+ string method = (string)model.GetValue (iter, MethodColumn);
+ string file = (string)model.GetValue (iter, FileColumn);
if (txt.Length > 0)
- txt.Append ('\n');
+ txt.Append (Environment.NewLine);
txt.AppendFormat ("{0} in {1}", method, file);
}
diff --git a/main/src/addins/MonoDevelop.Debugger/gtk-gui/MonoDevelop.Debugger.BusyEvaluatorDialog.cs b/main/src/addins/MonoDevelop.Debugger/gtk-gui/MonoDevelop.Debugger.BusyEvaluatorDialog.cs
index 20c77c6ed8..ea62abdeb4 100644
--- a/main/src/addins/MonoDevelop.Debugger/gtk-gui/MonoDevelop.Debugger.BusyEvaluatorDialog.cs
+++ b/main/src/addins/MonoDevelop.Debugger/gtk-gui/MonoDevelop.Debugger.BusyEvaluatorDialog.cs
@@ -5,113 +5,65 @@ namespace MonoDevelop.Debugger
public partial class BusyEvaluatorDialog
{
private global::Gtk.VBox vbox2;
+
private global::Gtk.Label label1;
- private global::Gtk.HBox hbox1;
- private global::Gtk.Label label2;
- private global::Gtk.Label labelMethod;
+
private global::Gtk.Button buttonCancel;
- private global::Gtk.Button buttonOk;
-
- protected virtual void Build ()
+
+ protected virtual void Build()
{
- global::Stetic.Gui.Initialize (this);
+ global::Stetic.Gui.Initialize(this);
// Widget MonoDevelop.Debugger.BusyEvaluatorDialog
this.Name = "MonoDevelop.Debugger.BusyEvaluatorDialog";
- this.Title = global::Mono.Unix.Catalog.GetString ("The Debugger is Busy");
+ this.Title = global::Mono.Unix.Catalog.GetString("The Debugger is Busy");
this.WindowPosition = ((global::Gtk.WindowPosition)(4));
// Internal child MonoDevelop.Debugger.BusyEvaluatorDialog.VBox
global::Gtk.VBox w1 = this.VBox;
w1.Name = "dialog1_VBox";
w1.BorderWidth = ((uint)(2));
// Container child dialog1_VBox.Gtk.Box+BoxChild
- this.vbox2 = new global::Gtk.VBox ();
+ this.vbox2 = new global::Gtk.VBox();
this.vbox2.Name = "vbox2";
this.vbox2.Spacing = 6;
this.vbox2.BorderWidth = ((uint)(9));
// Container child vbox2.Gtk.Box+BoxChild
- this.label1 = new global::Gtk.Label ();
+ this.label1 = new global::Gtk.Label();
this.label1.Name = "label1";
this.label1.Xalign = 0F;
- this.label1.LabelProp = global::Mono.Unix.Catalog.GetString ("The Debugger is waiting for an expression evaluation to finish.");
- this.vbox2.Add (this.label1);
- global::Gtk.Box.BoxChild w2 = ((global::Gtk.Box.BoxChild)(this.vbox2 [this.label1]));
+ this.label1.LabelProp = global::Mono.Unix.Catalog.GetString("The debugger runtime is not responding. You can wait for it to recover, or stop debugging.");
+ this.vbox2.Add(this.label1);
+ global::Gtk.Box.BoxChild w2 = ((global::Gtk.Box.BoxChild)(this.vbox2[this.label1]));
w2.Position = 0;
w2.Expand = false;
w2.Fill = false;
- // Container child vbox2.Gtk.Box+BoxChild
- this.hbox1 = new global::Gtk.HBox ();
- this.hbox1.Name = "hbox1";
- this.hbox1.Spacing = 6;
- // Container child hbox1.Gtk.Box+BoxChild
- this.label2 = new global::Gtk.Label ();
- this.label2.Name = "label2";
- this.label2.Xalign = 0F;
- this.label2.LabelProp = global::Mono.Unix.Catalog.GetString ("Method:");
- this.hbox1.Add (this.label2);
- global::Gtk.Box.BoxChild w3 = ((global::Gtk.Box.BoxChild)(this.hbox1 [this.label2]));
+ w1.Add(this.vbox2);
+ global::Gtk.Box.BoxChild w3 = ((global::Gtk.Box.BoxChild)(w1[this.vbox2]));
w3.Position = 0;
- w3.Expand = false;
- w3.Fill = false;
- // Container child hbox1.Gtk.Box+BoxChild
- this.labelMethod = new global::Gtk.Label ();
- this.labelMethod.Name = "labelMethod";
- this.labelMethod.Xalign = 0F;
- this.labelMethod.LabelProp = "<method>";
- this.labelMethod.Wrap = true;
- this.labelMethod.Selectable = true;
- this.labelMethod.MaxWidthChars = 120;
- this.hbox1.Add (this.labelMethod);
- global::Gtk.Box.BoxChild w4 = ((global::Gtk.Box.BoxChild)(this.hbox1 [this.labelMethod]));
- w4.Position = 1;
- w4.Expand = false;
- w4.Fill = false;
- this.vbox2.Add (this.hbox1);
- global::Gtk.Box.BoxChild w5 = ((global::Gtk.Box.BoxChild)(this.vbox2 [this.hbox1]));
- w5.Position = 1;
- w5.Expand = false;
- w5.Fill = false;
- w1.Add (this.vbox2);
- global::Gtk.Box.BoxChild w6 = ((global::Gtk.Box.BoxChild)(w1 [this.vbox2]));
- w6.Position = 0;
- w6.Expand = false;
- w6.Fill = false;
// Internal child MonoDevelop.Debugger.BusyEvaluatorDialog.ActionArea
- global::Gtk.HButtonBox w7 = this.ActionArea;
- w7.Name = "dialog1_ActionArea";
- w7.Spacing = 10;
- w7.BorderWidth = ((uint)(5));
- w7.LayoutStyle = ((global::Gtk.ButtonBoxStyle)(4));
+ global::Gtk.HButtonBox w4 = this.ActionArea;
+ w4.Name = "dialog1_ActionArea";
+ w4.Spacing = 10;
+ w4.BorderWidth = ((uint)(5));
+ w4.LayoutStyle = ((global::Gtk.ButtonBoxStyle)(4));
// Container child dialog1_ActionArea.Gtk.ButtonBox+ButtonBoxChild
- this.buttonCancel = new global::Gtk.Button ();
+ this.buttonCancel = new global::Gtk.Button();
this.buttonCancel.CanDefault = true;
this.buttonCancel.CanFocus = true;
this.buttonCancel.Name = "buttonCancel";
this.buttonCancel.UseUnderline = true;
- this.buttonCancel.Label = global::Mono.Unix.Catalog.GetString ("Stop Debugger");
- w7.Add (this.buttonCancel);
- global::Gtk.ButtonBox.ButtonBoxChild w8 = ((global::Gtk.ButtonBox.ButtonBoxChild)(w7 [this.buttonCancel]));
- w8.Expand = false;
- w8.Fill = false;
- // Container child dialog1_ActionArea.Gtk.ButtonBox+ButtonBoxChild
- this.buttonOk = new global::Gtk.Button ();
- this.buttonOk.CanDefault = true;
- this.buttonOk.CanFocus = true;
- this.buttonOk.Name = "buttonOk";
- this.buttonOk.UseUnderline = true;
- this.buttonOk.Label = global::Mono.Unix.Catalog.GetString ("Keep Waiting");
- w7.Add (this.buttonOk);
- global::Gtk.ButtonBox.ButtonBoxChild w9 = ((global::Gtk.ButtonBox.ButtonBoxChild)(w7 [this.buttonOk]));
- w9.Position = 1;
- w9.Expand = false;
- w9.Fill = false;
- if ((this.Child != null)) {
- this.Child.ShowAll ();
+ this.buttonCancel.Label = global::Mono.Unix.Catalog.GetString("Stop Debugger");
+ w4.Add(this.buttonCancel);
+ global::Gtk.ButtonBox.ButtonBoxChild w5 = ((global::Gtk.ButtonBox.ButtonBoxChild)(w4[this.buttonCancel]));
+ w5.Expand = false;
+ w5.Fill = false;
+ if ((this.Child != null))
+ {
+ this.Child.ShowAll();
}
- this.DefaultWidth = 381;
- this.DefaultHeight = 126;
- this.Hide ();
- this.buttonCancel.Clicked += new global::System.EventHandler (this.OnButtonCancelClicked);
- this.buttonOk.Clicked += new global::System.EventHandler (this.OnButtonOkClicked);
+ this.DefaultWidth = 548;
+ this.DefaultHeight = 98;
+ this.Hide();
+ this.buttonCancel.Clicked += new global::System.EventHandler(this.OnButtonCancelClicked);
}
}
}
diff --git a/main/src/addins/MonoDevelop.Debugger/gtk-gui/MonoDevelop.Debugger.DebuggerOptionsPanelWidget.cs b/main/src/addins/MonoDevelop.Debugger/gtk-gui/MonoDevelop.Debugger.DebuggerOptionsPanelWidget.cs
deleted file mode 100644
index ddefc1bfbf..0000000000
--- a/main/src/addins/MonoDevelop.Debugger/gtk-gui/MonoDevelop.Debugger.DebuggerOptionsPanelWidget.cs
+++ /dev/null
@@ -1,187 +0,0 @@
-
-// This file has been generated by the GUI designer. Do not modify.
-namespace MonoDevelop.Debugger
-{
- public partial class DebuggerOptionsPanelWidget
- {
- private global::Gtk.VBox vbox3;
-
- private global::Gtk.CheckButton checkProjectCodeOnly;
-
- private global::Gtk.CheckButton checkStepOverPropertiesAndOperators;
-
- private global::Gtk.CheckButton checkAllowEval;
-
- private global::Gtk.Alignment alignmentAllowToString;
-
- private global::Gtk.CheckButton checkAllowToString;
-
- private global::Gtk.CheckButton checkShowBaseGroup;
-
- private global::Gtk.CheckButton checkGroupPrivate;
-
- private global::Gtk.CheckButton checkGroupStatic;
-
- private global::Gtk.Table tableEval;
-
- private global::Gtk.Label label3;
-
- private global::Gtk.Label labelEvalTimeout;
-
- private global::Gtk.SpinButton spinTimeout;
-
- protected virtual void Build ()
- {
- global::Stetic.Gui.Initialize (this);
- // Widget MonoDevelop.Debugger.DebuggerOptionsPanelWidget
- global::Stetic.BinContainer.Attach (this);
- this.Name = "MonoDevelop.Debugger.DebuggerOptionsPanelWidget";
- // Container child MonoDevelop.Debugger.DebuggerOptionsPanelWidget.Gtk.Container+ContainerChild
- this.vbox3 = new global::Gtk.VBox ();
- this.vbox3.Name = "vbox3";
- this.vbox3.Spacing = 6;
- this.vbox3.BorderWidth = ((uint)(9));
- // Container child vbox3.Gtk.Box+BoxChild
- this.checkProjectCodeOnly = new global::Gtk.CheckButton ();
- this.checkProjectCodeOnly.CanFocus = true;
- this.checkProjectCodeOnly.Name = "checkProjectCodeOnly";
- this.checkProjectCodeOnly.Label = global::Mono.Unix.Catalog.GetString ("Debug project code only; do not step into framework code.");
- this.checkProjectCodeOnly.Active = true;
- this.checkProjectCodeOnly.DrawIndicator = true;
- this.checkProjectCodeOnly.UseUnderline = true;
- this.vbox3.Add (this.checkProjectCodeOnly);
- global::Gtk.Box.BoxChild w1 = ((global::Gtk.Box.BoxChild)(this.vbox3 [this.checkProjectCodeOnly]));
- w1.Position = 0;
- w1.Expand = false;
- w1.Fill = false;
- // Container child vbox3.Gtk.Box+BoxChild
- this.checkStepOverPropertiesAndOperators = new global::Gtk.CheckButton ();
- this.checkStepOverPropertiesAndOperators.CanFocus = true;
- this.checkStepOverPropertiesAndOperators.Name = "checkStepOverPropertiesAndOperators";
- this.checkStepOverPropertiesAndOperators.Label = global::Mono.Unix.Catalog.GetString ("Step over properties and operators");
- this.checkStepOverPropertiesAndOperators.Active = true;
- this.checkStepOverPropertiesAndOperators.DrawIndicator = true;
- this.checkStepOverPropertiesAndOperators.UseUnderline = true;
- this.vbox3.Add (this.checkStepOverPropertiesAndOperators);
- global::Gtk.Box.BoxChild w2 = ((global::Gtk.Box.BoxChild)(this.vbox3 [this.checkStepOverPropertiesAndOperators]));
- w2.Position = 1;
- w2.Expand = false;
- w2.Fill = false;
- // Container child vbox3.Gtk.Box+BoxChild
- this.checkAllowEval = new global::Gtk.CheckButton ();
- this.checkAllowEval.CanFocus = true;
- this.checkAllowEval.Name = "checkAllowEval";
- this.checkAllowEval.Label = global::Mono.Unix.Catalog.GetString ("Allow implicit property evaluation and method invocation");
- this.checkAllowEval.Active = true;
- this.checkAllowEval.DrawIndicator = true;
- this.checkAllowEval.UseUnderline = true;
- this.vbox3.Add (this.checkAllowEval);
- global::Gtk.Box.BoxChild w3 = ((global::Gtk.Box.BoxChild)(this.vbox3 [this.checkAllowEval]));
- w3.Position = 2;
- w3.Expand = false;
- w3.Fill = false;
- // Container child vbox3.Gtk.Box+BoxChild
- this.alignmentAllowToString = new global::Gtk.Alignment (0F, 0.5F, 1F, 1F);
- this.alignmentAllowToString.Name = "alignmentAllowToString";
- this.alignmentAllowToString.LeftPadding = ((uint)(18));
- // Container child alignmentAllowToString.Gtk.Container+ContainerChild
- this.checkAllowToString = new global::Gtk.CheckButton ();
- this.checkAllowToString.CanFocus = true;
- this.checkAllowToString.Name = "checkAllowToString";
- this.checkAllowToString.Label = global::Mono.Unix.Catalog.GetString ("Call string-conversion function on objects in variables windows");
- this.checkAllowToString.Active = true;
- this.checkAllowToString.DrawIndicator = true;
- this.checkAllowToString.UseUnderline = true;
- this.alignmentAllowToString.Add (this.checkAllowToString);
- this.vbox3.Add (this.alignmentAllowToString);
- global::Gtk.Box.BoxChild w5 = ((global::Gtk.Box.BoxChild)(this.vbox3 [this.alignmentAllowToString]));
- w5.Position = 3;
- w5.Expand = false;
- w5.Fill = false;
- // Container child vbox3.Gtk.Box+BoxChild
- this.checkShowBaseGroup = new global::Gtk.CheckButton ();
- this.checkShowBaseGroup.CanFocus = true;
- this.checkShowBaseGroup.Name = "checkShowBaseGroup";
- this.checkShowBaseGroup.Label = global::Mono.Unix.Catalog.GetString ("Show inherited class members in a base class group");
- this.checkShowBaseGroup.DrawIndicator = true;
- this.checkShowBaseGroup.UseUnderline = true;
- this.vbox3.Add (this.checkShowBaseGroup);
- global::Gtk.Box.BoxChild w6 = ((global::Gtk.Box.BoxChild)(this.vbox3 [this.checkShowBaseGroup]));
- w6.Position = 4;
- w6.Expand = false;
- w6.Fill = false;
- // Container child vbox3.Gtk.Box+BoxChild
- this.checkGroupPrivate = new global::Gtk.CheckButton ();
- this.checkGroupPrivate.CanFocus = true;
- this.checkGroupPrivate.Name = "checkGroupPrivate";
- this.checkGroupPrivate.Label = global::Mono.Unix.Catalog.GetString ("Group non-public members");
- this.checkGroupPrivate.DrawIndicator = true;
- this.checkGroupPrivate.UseUnderline = true;
- this.vbox3.Add (this.checkGroupPrivate);
- global::Gtk.Box.BoxChild w7 = ((global::Gtk.Box.BoxChild)(this.vbox3 [this.checkGroupPrivate]));
- w7.Position = 5;
- w7.Expand = false;
- w7.Fill = false;
- // Container child vbox3.Gtk.Box+BoxChild
- this.checkGroupStatic = new global::Gtk.CheckButton ();
- this.checkGroupStatic.CanFocus = true;
- this.checkGroupStatic.Name = "checkGroupStatic";
- this.checkGroupStatic.Label = global::Mono.Unix.Catalog.GetString ("Group static members");
- this.checkGroupStatic.DrawIndicator = true;
- this.checkGroupStatic.UseUnderline = true;
- this.vbox3.Add (this.checkGroupStatic);
- global::Gtk.Box.BoxChild w8 = ((global::Gtk.Box.BoxChild)(this.vbox3 [this.checkGroupStatic]));
- w8.Position = 6;
- w8.Expand = false;
- w8.Fill = false;
- // Container child vbox3.Gtk.Box+BoxChild
- this.tableEval = new global::Gtk.Table (((uint)(1)), ((uint)(3)), false);
- this.tableEval.Name = "tableEval";
- this.tableEval.RowSpacing = ((uint)(6));
- this.tableEval.ColumnSpacing = ((uint)(6));
- // Container child tableEval.Gtk.Table+TableChild
- this.label3 = new global::Gtk.Label ();
- this.label3.Name = "label3";
- this.label3.LabelProp = global::Mono.Unix.Catalog.GetString ("ms");
- this.tableEval.Add (this.label3);
- global::Gtk.Table.TableChild w9 = ((global::Gtk.Table.TableChild)(this.tableEval [this.label3]));
- w9.LeftAttach = ((uint)(2));
- w9.RightAttach = ((uint)(3));
- w9.XOptions = ((global::Gtk.AttachOptions)(4));
- w9.YOptions = ((global::Gtk.AttachOptions)(4));
- // Container child tableEval.Gtk.Table+TableChild
- this.labelEvalTimeout = new global::Gtk.Label ();
- this.labelEvalTimeout.Name = "labelEvalTimeout";
- this.labelEvalTimeout.Xalign = 0F;
- this.labelEvalTimeout.LabelProp = global::Mono.Unix.Catalog.GetString ("Evaluation Timeout:");
- this.tableEval.Add (this.labelEvalTimeout);
- global::Gtk.Table.TableChild w10 = ((global::Gtk.Table.TableChild)(this.tableEval [this.labelEvalTimeout]));
- w10.XOptions = ((global::Gtk.AttachOptions)(4));
- w10.YOptions = ((global::Gtk.AttachOptions)(4));
- // Container child tableEval.Gtk.Table+TableChild
- this.spinTimeout = new global::Gtk.SpinButton (0, 1000000, 100);
- this.spinTimeout.CanFocus = true;
- this.spinTimeout.Name = "spinTimeout";
- this.spinTimeout.Adjustment.PageIncrement = 10;
- this.spinTimeout.ClimbRate = 100;
- this.spinTimeout.Numeric = true;
- this.tableEval.Add (this.spinTimeout);
- global::Gtk.Table.TableChild w11 = ((global::Gtk.Table.TableChild)(this.tableEval [this.spinTimeout]));
- w11.LeftAttach = ((uint)(1));
- w11.RightAttach = ((uint)(2));
- w11.XOptions = ((global::Gtk.AttachOptions)(4));
- w11.YOptions = ((global::Gtk.AttachOptions)(4));
- this.vbox3.Add (this.tableEval);
- global::Gtk.Box.BoxChild w12 = ((global::Gtk.Box.BoxChild)(this.vbox3 [this.tableEval]));
- w12.Position = 7;
- w12.Expand = false;
- w12.Fill = false;
- this.Add (this.vbox3);
- if ((this.Child != null)) {
- this.Child.ShowAll ();
- }
- this.Hide ();
- this.checkAllowEval.Toggled += new global::System.EventHandler (this.OnCheckAllowEvalToggled);
- }
- }
-}
diff --git a/main/src/addins/MonoDevelop.Debugger/gtk-gui/generated.cs b/main/src/addins/MonoDevelop.Debugger/gtk-gui/generated.cs
index 3285e87c05..4842e95d78 100644
--- a/main/src/addins/MonoDevelop.Debugger/gtk-gui/generated.cs
+++ b/main/src/addins/MonoDevelop.Debugger/gtk-gui/generated.cs
@@ -6,75 +6,23 @@ namespace Stetic
{
private static bool initialized;
- internal static void Initialize (Gtk.Widget iconRenderer)
+ internal static void Initialize(Gtk.Widget iconRenderer)
{
- if ((Stetic.Gui.initialized == false)) {
+ if ((Stetic.Gui.initialized == false))
+ {
Stetic.Gui.initialized = true;
}
}
}
- internal class BinContainer
- {
- private Gtk.Widget child;
-
- private Gtk.UIManager uimanager;
-
- public static BinContainer Attach (Gtk.Bin bin)
- {
- BinContainer bc = new BinContainer ();
- bin.SizeRequested += new Gtk.SizeRequestedHandler (bc.OnSizeRequested);
- bin.SizeAllocated += new Gtk.SizeAllocatedHandler (bc.OnSizeAllocated);
- bin.Added += new Gtk.AddedHandler (bc.OnAdded);
- return bc;
- }
-
- private void OnSizeRequested (object sender, Gtk.SizeRequestedArgs args)
- {
- if ((this.child != null)) {
- args.Requisition = this.child.SizeRequest ();
- }
- }
-
- private void OnSizeAllocated (object sender, Gtk.SizeAllocatedArgs args)
- {
- if ((this.child != null)) {
- this.child.Allocation = args.Allocation;
- }
- }
-
- private void OnAdded (object sender, Gtk.AddedArgs args)
- {
- this.child = args.Widget;
- }
-
- public void SetUiManager (Gtk.UIManager uim)
- {
- this.uimanager = uim;
- this.child.Realized += new System.EventHandler (this.OnRealized);
- }
-
- private void OnRealized (object sender, System.EventArgs args)
- {
- if ((this.uimanager != null)) {
- Gtk.Widget w;
- w = this.child.Toplevel;
- if (((w != null) && typeof(Gtk.Window).IsInstanceOfType (w))) {
- ((Gtk.Window)(w)).AddAccelGroup (this.uimanager.AccelGroup);
- this.uimanager = null;
- }
- }
- }
- }
-
internal class ActionGroups
{
- public static Gtk.ActionGroup GetActionGroup (System.Type type)
+ public static Gtk.ActionGroup GetActionGroup(System.Type type)
{
- return Stetic.ActionGroups.GetActionGroup (type.FullName);
+ return Stetic.ActionGroups.GetActionGroup(type.FullName);
}
- public static Gtk.ActionGroup GetActionGroup (string name)
+ public static Gtk.ActionGroup GetActionGroup(string name)
{
return null;
}
diff --git a/main/src/addins/MonoDevelop.Debugger/gtk-gui/gui.stetic b/main/src/addins/MonoDevelop.Debugger/gtk-gui/gui.stetic
index a78350eb13..9b600748d0 100644
--- a/main/src/addins/MonoDevelop.Debugger/gtk-gui/gui.stetic
+++ b/main/src/addins/MonoDevelop.Debugger/gtk-gui/gui.stetic
@@ -287,12 +287,12 @@
</widget>
</child>
</widget>
- <widget class="Gtk.Dialog" id="MonoDevelop.Debugger.BusyEvaluatorDialog" design-size="381 126">
+ <widget class="Gtk.Dialog" id="MonoDevelop.Debugger.BusyEvaluatorDialog" design-size="548 98">
<property name="MemberName" />
<property name="Visible">False</property>
<property name="Title" translatable="yes">The Debugger is Busy</property>
<property name="WindowPosition">CenterOnParent</property>
- <property name="Buttons">2</property>
+ <property name="Buttons">1</property>
<property name="HelpButton">False</property>
<child internal-child="VBox">
<widget class="Gtk.VBox" id="dialog1_VBox">
@@ -307,7 +307,7 @@
<widget class="Gtk.Label" id="label1">
<property name="MemberName" />
<property name="Xalign">0</property>
- <property name="LabelProp" translatable="yes">The Debugger is waiting for an expression evaluation to finish.</property>
+ <property name="LabelProp" translatable="yes">The debugger runtime is not responding. You can wait for it to recover, or stop debugging.</property>
</widget>
<packing>
<property name="Position">0</property>
@@ -317,52 +317,12 @@
</packing>
</child>
<child>
- <widget class="Gtk.HBox" id="hbox1">
- <property name="MemberName" />
- <property name="Spacing">6</property>
- <child>
- <widget class="Gtk.Label" id="label2">
- <property name="MemberName" />
- <property name="Xalign">0</property>
- <property name="LabelProp" translatable="yes">Method:</property>
- </widget>
- <packing>
- <property name="Position">0</property>
- <property name="AutoSize">True</property>
- <property name="Expand">False</property>
- <property name="Fill">False</property>
- </packing>
- </child>
- <child>
- <widget class="Gtk.Label" id="labelMethod">
- <property name="MemberName" />
- <property name="Xalign">0</property>
- <property name="LabelProp">&lt;method&gt;</property>
- <property name="Wrap">True</property>
- <property name="Selectable">True</property>
- <property name="MaxWidthChars">120</property>
- </widget>
- <packing>
- <property name="Position">1</property>
- <property name="AutoSize">True</property>
- <property name="Expand">False</property>
- <property name="Fill">False</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="Position">1</property>
- <property name="AutoSize">True</property>
- <property name="Expand">False</property>
- <property name="Fill">False</property>
- </packing>
+ <placeholder />
</child>
</widget>
<packing>
<property name="Position">0</property>
<property name="AutoSize">True</property>
- <property name="Expand">False</property>
- <property name="Fill">False</property>
</packing>
</child>
</widget>
@@ -372,7 +332,7 @@
<property name="MemberName" />
<property name="Spacing">10</property>
<property name="BorderWidth">5</property>
- <property name="Size">2</property>
+ <property name="Size">1</property>
<property name="LayoutStyle">End</property>
<child>
<widget class="Gtk.Button" id="buttonCancel">
@@ -390,233 +350,6 @@
<property name="Fill">False</property>
</packing>
</child>
- <child>
- <widget class="Gtk.Button" id="buttonOk">
- <property name="MemberName" />
- <property name="CanDefault">True</property>
- <property name="CanFocus">True</property>
- <property name="Type">TextOnly</property>
- <property name="Label" translatable="yes">Keep Waiting</property>
- <property name="UseUnderline">True</property>
- <property name="ResponseId">-1</property>
- <signal name="Clicked" handler="OnButtonOkClicked" />
- </widget>
- <packing>
- <property name="Position">1</property>
- <property name="Expand">False</property>
- <property name="Fill">False</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
- <widget class="Gtk.Bin" id="MonoDevelop.Debugger.DebuggerOptionsPanelWidget" design-size="523 241">
- <property name="MemberName" />
- <property name="Visible">False</property>
- <child>
- <widget class="Gtk.VBox" id="vbox3">
- <property name="MemberName" />
- <property name="Spacing">6</property>
- <property name="BorderWidth">9</property>
- <child>
- <widget class="Gtk.CheckButton" id="checkProjectCodeOnly">
- <property name="MemberName" />
- <property name="CanFocus">True</property>
- <property name="Label" translatable="yes">Debug project code only; do not step into framework code.</property>
- <property name="Active">True</property>
- <property name="DrawIndicator">True</property>
- <property name="HasLabel">True</property>
- <property name="UseUnderline">True</property>
- </widget>
- <packing>
- <property name="Position">0</property>
- <property name="AutoSize">True</property>
- <property name="Expand">False</property>
- <property name="Fill">False</property>
- </packing>
- </child>
- <child>
- <widget class="Gtk.CheckButton" id="checkStepOverPropertiesAndOperators">
- <property name="MemberName" />
- <property name="CanFocus">True</property>
- <property name="Label" translatable="yes">Step over properties and operators</property>
- <property name="Active">True</property>
- <property name="DrawIndicator">True</property>
- <property name="HasLabel">True</property>
- <property name="UseUnderline">True</property>
- </widget>
- <packing>
- <property name="Position">1</property>
- <property name="AutoSize">True</property>
- <property name="Expand">False</property>
- <property name="Fill">False</property>
- </packing>
- </child>
- <child>
- <widget class="Gtk.CheckButton" id="checkAllowEval">
- <property name="MemberName" />
- <property name="CanFocus">True</property>
- <property name="Label" translatable="yes">Allow implicit property evaluation and method invocation</property>
- <property name="Active">True</property>
- <property name="DrawIndicator">True</property>
- <property name="HasLabel">True</property>
- <property name="UseUnderline">True</property>
- <signal name="Toggled" handler="OnCheckAllowEvalToggled" />
- </widget>
- <packing>
- <property name="Position">2</property>
- <property name="AutoSize">True</property>
- <property name="Expand">False</property>
- <property name="Fill">False</property>
- </packing>
- </child>
- <child>
- <widget class="Gtk.Alignment" id="alignmentAllowToString">
- <property name="MemberName" />
- <property name="Xalign">0</property>
- <property name="LeftPadding">18</property>
- <child>
- <widget class="Gtk.CheckButton" id="checkAllowToString">
- <property name="MemberName" />
- <property name="CanFocus">True</property>
- <property name="Label" translatable="yes">Call string-conversion function on objects in variables windows</property>
- <property name="Active">True</property>
- <property name="DrawIndicator">True</property>
- <property name="HasLabel">True</property>
- <property name="UseUnderline">True</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="Position">3</property>
- <property name="AutoSize">True</property>
- <property name="Expand">False</property>
- <property name="Fill">False</property>
- </packing>
- </child>
- <child>
- <widget class="Gtk.CheckButton" id="checkShowBaseGroup">
- <property name="MemberName" />
- <property name="CanFocus">True</property>
- <property name="Label" translatable="yes">Show inherited class members in a base class group</property>
- <property name="DrawIndicator">True</property>
- <property name="HasLabel">True</property>
- <property name="UseUnderline">True</property>
- </widget>
- <packing>
- <property name="Position">4</property>
- <property name="AutoSize">True</property>
- <property name="Expand">False</property>
- <property name="Fill">False</property>
- </packing>
- </child>
- <child>
- <widget class="Gtk.CheckButton" id="checkGroupPrivate">
- <property name="MemberName" />
- <property name="CanFocus">True</property>
- <property name="Label" translatable="yes">Group non-public members</property>
- <property name="DrawIndicator">True</property>
- <property name="HasLabel">True</property>
- <property name="UseUnderline">True</property>
- </widget>
- <packing>
- <property name="Position">5</property>
- <property name="AutoSize">True</property>
- <property name="Expand">False</property>
- <property name="Fill">False</property>
- </packing>
- </child>
- <child>
- <widget class="Gtk.CheckButton" id="checkGroupStatic">
- <property name="MemberName" />
- <property name="CanFocus">True</property>
- <property name="Label" translatable="yes">Group static members</property>
- <property name="DrawIndicator">True</property>
- <property name="HasLabel">True</property>
- <property name="UseUnderline">True</property>
- </widget>
- <packing>
- <property name="Position">6</property>
- <property name="AutoSize">True</property>
- <property name="Expand">False</property>
- <property name="Fill">False</property>
- </packing>
- </child>
- <child>
- <widget class="Gtk.Table" id="tableEval">
- <property name="MemberName" />
- <property name="NColumns">3</property>
- <property name="RowSpacing">6</property>
- <property name="ColumnSpacing">6</property>
- <child>
- <widget class="Gtk.Label" id="label3">
- <property name="MemberName" />
- <property name="LabelProp" translatable="yes">ms</property>
- </widget>
- <packing>
- <property name="LeftAttach">2</property>
- <property name="RightAttach">3</property>
- <property name="AutoSize">True</property>
- <property name="XOptions">Fill</property>
- <property name="YOptions">Fill</property>
- <property name="XExpand">False</property>
- <property name="XFill">True</property>
- <property name="XShrink">False</property>
- <property name="YExpand">False</property>
- <property name="YFill">True</property>
- <property name="YShrink">False</property>
- </packing>
- </child>
- <child>
- <widget class="Gtk.Label" id="labelEvalTimeout">
- <property name="MemberName" />
- <property name="Xalign">0</property>
- <property name="LabelProp" translatable="yes">Evaluation Timeout:</property>
- </widget>
- <packing>
- <property name="AutoSize">True</property>
- <property name="XOptions">Fill</property>
- <property name="YOptions">Fill</property>
- <property name="XExpand">False</property>
- <property name="XFill">True</property>
- <property name="XShrink">False</property>
- <property name="YExpand">False</property>
- <property name="YFill">True</property>
- <property name="YShrink">False</property>
- </packing>
- </child>
- <child>
- <widget class="Gtk.SpinButton" id="spinTimeout">
- <property name="MemberName" />
- <property name="CanFocus">True</property>
- <property name="Upper">1000000</property>
- <property name="PageIncrement">10</property>
- <property name="StepIncrement">100</property>
- <property name="ClimbRate">100</property>
- <property name="Numeric">True</property>
- </widget>
- <packing>
- <property name="LeftAttach">1</property>
- <property name="RightAttach">2</property>
- <property name="AutoSize">True</property>
- <property name="XOptions">Fill</property>
- <property name="YOptions">Fill</property>
- <property name="XExpand">False</property>
- <property name="XFill">True</property>
- <property name="XShrink">False</property>
- <property name="YExpand">False</property>
- <property name="YFill">True</property>
- <property name="YShrink">False</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="Position">7</property>
- <property name="AutoSize">True</property>
- <property name="Expand">False</property>
- <property name="Fill">False</property>
- </packing>
- </child>
</widget>
</child>
</widget>
diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Projects/ProjectFileDescriptor.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Projects/ProjectFileDescriptor.cs
index 0a95a9c589..50cb4254fe 100644
--- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Projects/ProjectFileDescriptor.cs
+++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Projects/ProjectFileDescriptor.cs
@@ -31,16 +31,41 @@ using System.ComponentModel;
using MonoDevelop.Projects;
using MonoDevelop.Core;
using MonoDevelop.Ide;
+using System.Linq;
namespace MonoDevelop.DesignerSupport
{
- class ProjectFileDescriptor: CustomDescriptor
+ class ProjectFileDescriptor: CustomDescriptor, IDisposable
{
ProjectFile file;
-
+ Project project;
+
public ProjectFileDescriptor (ProjectFile file)
{
this.file = file;
+ project = file.Project;
+ if (project != null) {
+ project.FilePropertyChangedInProject += OnFilePropertyChangedInProject;
+ }
+ }
+
+ void OnFilePropertyChangedInProject (object sender, ProjectFileEventArgs args)
+ {
+ var pad = IdeApp.Workbench.GetPad <PropertyPad> ();
+ if (pad == null)
+ return;
+
+ var grid = ((PropertyPad)pad.Content).PropertyGrid;
+ if (args.Any (arg => arg.ProjectFile == file))
+ grid.Refresh ();
+ }
+
+ void IDisposable.Dispose ()
+ {
+ if (project != null) {
+ project.FilePropertyChangedInProject -= OnFilePropertyChangedInProject;
+ project = null;
+ }
}
[LocalizedCategory ("Misc")]
@@ -71,6 +96,7 @@ namespace MonoDevelop.DesignerSupport
[LocalizedDisplayName ("Build action")]
[LocalizedDescription ("Action to perform when building this file.")]
[TypeConverter (typeof (BuildActionStringsConverter))]
+ [RefreshProperties(RefreshProperties.All)]
public string BuildAction {
get { return file.BuildAction; }
set { file.BuildAction = value; }
diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/ToolboxWidget.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/ToolboxWidget.cs
index 071501d38a..d15045ffbc 100644
--- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/ToolboxWidget.cs
+++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.Toolbox/ToolboxWidget.cs
@@ -243,11 +243,15 @@ namespace MonoDevelop.DesignerSupport.Toolbox
Category lastCategory = null;
int lastCategoryYpos = 0;
+ cr.LineWidth = 1;
+
Iterate (ref xpos, ref ypos, delegate (Category category, Gdk.Size itemDimension) {
const int foldSegmentHeight = 8;
ProcessExpandAnimation (cr, lastCategory, lastCategoryYpos, backColor, area, ref ypos);
+ if (!area.IntersectsWith (new Gdk.Rectangle (new Gdk.Point (xpos, ypos), itemDimension)))
+ return true;
cr.Rectangle (xpos, ypos, itemDimension.Width, itemDimension.Height);
using (var pat = new Cairo.LinearGradient (xpos, ypos, xpos, ypos + itemDimension.Height)) {
pat.AddColorStop (0, CategoryBackgroundGradientStartColor);
@@ -262,7 +266,6 @@ namespace MonoDevelop.DesignerSupport.Toolbox
cr.MoveTo (0, ypos + itemDimension.Height - 0.5);
cr.LineTo (xpos + Allocation.Width, ypos + itemDimension.Height - 0.5);
cr.SetSourceColor (CategoryBorderColor);
- cr.LineWidth = 1;
cr.Stroke ();
headerLayout.SetText (category.Text);
@@ -278,7 +281,11 @@ namespace MonoDevelop.DesignerSupport.Toolbox
lastCategory = category;
lastCategoryYpos = ypos + itemDimension.Height;
+ return true;
}, delegate (Category curCategory, Item item, Gdk.Size itemDimension) {
+ if (!area.IntersectsWith (new Gdk.Rectangle (new Gdk.Point (xpos, ypos), itemDimension)))
+ return true;
+
if (item == SelectedItem) {
cr.SetSourceColor (Style.Base (StateType.Selected).ToCairoColor ());
cr.Rectangle (xpos, ypos, itemDimension.Width, itemDimension.Height);
@@ -301,6 +308,8 @@ namespace MonoDevelop.DesignerSupport.Toolbox
cr.Rectangle (xpos + 0.5, ypos + 0.5, itemDimension.Width - 1, itemDimension.Height - 1);
cr.Stroke ();
}
+
+ return true;
});
ProcessExpandAnimation (cr, lastCategory, lastCategoryYpos, backColor, area, ref ypos);
@@ -540,6 +549,7 @@ namespace MonoDevelop.DesignerSupport.Toolbox
HideTooltipWindow ();
var oldItem = mouseOverItem;
mouseOverItem = null;
+ Gdk.Rectangle newItemExtents = Gdk.Rectangle.Zero;
this.mouseX = (int)e.X + (int)(this.hAdjustement != null ? this.hAdjustement.Value : 0);
this.mouseY = (int)e.Y + (int)(this.vAdjustement != null ? this.vAdjustement.Value : 0);
Iterate (ref xpos, ref ypos, delegate (Category category, Gdk.Size itemDimension) {
@@ -547,22 +557,34 @@ namespace MonoDevelop.DesignerSupport.Toolbox
ypos <= mouseY && mouseY <= ypos + itemDimension.Height) {
mouseOverItem = category;
GdkWindow.Cursor = handCursor;
- ShowTooltip (mouseOverItem, TipTimer, (int)e.X + 2, (int)e.Y + 16);
+ if (!e.State.HasFlag (ModifierType.Button1Mask))
+ ShowTooltip (mouseOverItem, TipTimer, (int)e.X + 2, (int)e.Y + 16);
+ newItemExtents = new Gdk.Rectangle (xpos, ypos, itemDimension.Width, itemDimension.Height);
+ return false;
}
+ return true;
}, delegate (Category curCategory, Item item, Gdk.Size itemDimension) {
if (xpos <= mouseX && mouseX <= xpos + itemDimension.Width &&
ypos <= mouseY && mouseY <= ypos + itemDimension.Height) {
mouseOverItem = item;
GdkWindow.Cursor = null;
- ShowTooltip (mouseOverItem, TipTimer, (int)e.X + 2, (int)e.Y + 16);
+ if (!e.State.HasFlag (ModifierType.Button1Mask))
+ ShowTooltip (mouseOverItem, TipTimer, (int)e.X + 2, (int)e.Y + 16);
+ newItemExtents = new Gdk.Rectangle (xpos, ypos, itemDimension.Width, itemDimension.Height);
+ return false;
}
+ return true;
});
if (mouseOverItem == null)
GdkWindow.Cursor = null;
- if (oldItem != mouseOverItem)
+ if (oldItem != mouseOverItem) {
this.QueueDraw ();
+ var oldItemExtents = GetItemExtends (oldItem);
+ QueueDrawArea (oldItemExtents.X, oldItemExtents.Y, oldItemExtents.Width, oldItemExtents.Height);
+ QueueDrawArea (newItemExtents.X, newItemExtents.Y, newItemExtents.Width, newItemExtents.Height);
+ }
return base.OnMotionNotifyEvent (e);
}
@@ -612,10 +634,12 @@ namespace MonoDevelop.DesignerSupport.Toolbox
{
Category result = null;
int xpos = 0, ypos = 0;
- Iterate (ref xpos, ref ypos, delegate (Category category, Gdk.Size itemDimension) {
- }, delegate (Category curCategory, Item innerItem, Gdk.Size itemDimension) {
- if (innerItem == item)
+ Iterate (ref xpos, ref ypos, null, delegate (Category curCategory, Item innerItem, Gdk.Size itemDimension) {
+ if (innerItem == item) {
result = curCategory;
+ return false;
+ }
+ return true;
});
return result;
}
@@ -626,11 +650,13 @@ namespace MonoDevelop.DesignerSupport.Toolbox
Category last = null;
int xpos = 0, ypos = 0;
Iterate (ref xpos, ref ypos, delegate (Category curCategory, Gdk.Size itemDimension) {
- if (last == category)
+ if (last == category) {
result = curCategory;
+ return false;
+ }
last = curCategory;
- }, delegate (Category curCategory, Item innerItem, Gdk.Size itemDimension) {
- });
+ return true;
+ }, null);
return result;
}
@@ -639,10 +665,12 @@ namespace MonoDevelop.DesignerSupport.Toolbox
Item result = item;
Gdk.Rectangle rect = GetItemExtends (item);
int xpos = 0, ypos = 0;
- Iterate (ref xpos, ref ypos, delegate (Category category, Gdk.Size itemDimension) {
- }, delegate (Category curCategory, Item curItem, Gdk.Size itemDimension) {
- if (xpos > rect.X && ypos == rect.Y && result == item)
+ Iterate (ref xpos, ref ypos, null, delegate (Category curCategory, Item curItem, Gdk.Size itemDimension) {
+ if (xpos > rect.X && ypos == rect.Y && result == item) {
result = curItem;
+ return false;
+ }
+ return true;
});
return result;
}
@@ -652,10 +680,12 @@ namespace MonoDevelop.DesignerSupport.Toolbox
Item result = item;
Gdk.Rectangle rect = GetItemExtends (item);
int xpos = 0, ypos = 0;
- Iterate (ref xpos, ref ypos, delegate (Category category, Gdk.Size itemDimension) {
- }, delegate (Category curCategory, Item curItem, Gdk.Size itemDimension) {
- if (xpos < rect.X && ypos == rect.Y)
+ Iterate (ref xpos, ref ypos, null, delegate (Category curCategory, Item curItem, Gdk.Size itemDimension) {
+ if (xpos < rect.X && ypos == rect.Y) {
result = curItem;
+ return false;
+ }
+ return true;
});
return result;
}
@@ -667,10 +697,12 @@ namespace MonoDevelop.DesignerSupport.Toolbox
Item result = item;
Gdk.Rectangle rect = GetItemExtends (item);
int xpos = 0, ypos = 0;
- Iterate (ref xpos, ref ypos, delegate (Category category, Gdk.Size itemDimension) {
- }, delegate (Category curCategory, Item curItem, Gdk.Size itemDimension) {
- if (ypos > rect.Y && xpos == rect.X && result == item && curCategory == itemCategory)
+ Iterate (ref xpos, ref ypos, null, delegate (Category curCategory, Item curItem, Gdk.Size itemDimension) {
+ if (ypos > rect.Y && xpos == rect.X && result == item && curCategory == itemCategory) {
result = curItem;
+ return false;
+ }
+ return true;
});
return result;
}
@@ -681,10 +713,12 @@ namespace MonoDevelop.DesignerSupport.Toolbox
Item result = item;
Gdk.Rectangle rect = GetItemExtends (item);
int xpos = 0, ypos = 0;
- Iterate (ref xpos, ref ypos, delegate (Category category, Gdk.Size itemDimension) {
- }, delegate (Category curCategory, Item curItem, Gdk.Size itemDimension) {
- if (ypos < rect.Y && xpos == rect.X && curCategory == itemCategory)
+ Iterate (ref xpos, ref ypos, null, delegate (Category curCategory, Item curItem, Gdk.Size itemDimension) {
+ if (ypos < rect.Y && xpos == rect.X && curCategory == itemCategory) {
result = curItem;
+ return false;
+ }
+ return true;
});
return result;
}
@@ -694,11 +728,17 @@ namespace MonoDevelop.DesignerSupport.Toolbox
Gdk.Rectangle result = new Gdk.Rectangle (0, 0, 0, 0);
int xpos = 0, ypos = 0;
Iterate (ref xpos, ref ypos, delegate (Category category, Gdk.Size itemDimension) {
- if (item == category)
+ if (item == category) {
result = new Gdk.Rectangle (xpos, ypos, itemDimension.Width, itemDimension.Height);
+ return false;
+ }
+ return true;
}, delegate (Category curCategory, Item curItem, Gdk.Size itemDimension) {
- if (item == curItem)
+ if (item == curItem) {
result = new Gdk.Rectangle (xpos, ypos, itemDimension.Width, itemDimension.Height);
+ return false;
+ }
+ return true;
});
return result;
}
@@ -709,13 +749,19 @@ namespace MonoDevelop.DesignerSupport.Toolbox
Item lastItem = null;
int xpos = 0, ypos = 0;
Iterate (ref xpos, ref ypos, delegate (Category category, Gdk.Size itemDimension) {
- if (currentItem == category && lastItem != null)
+ if (currentItem == category && lastItem != null) {
result = lastItem;
+ return false;
+ }
lastItem = category;
+ return true;
}, delegate (Category curCategory, Item item, Gdk.Size itemDimension) {
- if (currentItem == item && lastItem != null)
+ if (currentItem == item && lastItem != null) {
result = lastItem;
+ return false;
+ }
lastItem = item;
+ return true;
});
return result;
@@ -729,13 +775,17 @@ namespace MonoDevelop.DesignerSupport.Toolbox
Iterate (ref xpos, ref ypos, delegate (Category category, Gdk.Size itemDimension) {
if (lastItem == currentItem) {
result = category;
+ return false;
}
lastItem = category;
+ return true;
}, delegate (Category curCategory, Item item, Gdk.Size itemDimension) {
if (lastItem == currentItem) {
result = item;
+ return false;
}
lastItem = item;
+ return true;
});
return result;
}
@@ -774,28 +824,32 @@ namespace MonoDevelop.DesignerSupport.Toolbox
#endregion
#region Item & Category iteration
- delegate void CategoryAction (Category category, Gdk.Size categoryDimension);
- delegate void ItemAction (Category curCategory, Item item, Gdk.Size itemDimension);
- void IterateItems (Category category, ref int xpos, ref int ypos, ItemAction action)
+ delegate bool CategoryAction (Category category, Gdk.Size categoryDimension);
+ delegate bool ItemAction (Category curCategory, Item item, Gdk.Size itemDimension);
+ bool IterateItems (Category category, ref int xpos, ref int ypos, ItemAction action)
{
if (listMode || !category.CanIconizeItems) {
foreach (Item item in category.Items) {
if (!item.IsVisible)
continue;
-
- layout.SetText (item.Text);
- int x, y;
- layout.GetPixelSize (out x, out y);
- y = Math.Max (IconSize.Height, y);
- y += ItemTopBottomPadding * 2;
+
+ int x, y = item.ItemHeight;
+
+ if (y == 0) {
+ layout.SetText (item.Text);
+ layout.GetPixelSize (out x, out y);
+ y = Math.Max (IconSize.Height, y);
+ y += ItemTopBottomPadding * 2;
+ item.ItemHeight = y;
+ }
xpos = 0;
- if (action != null)
- action (category, item, new Gdk.Size (Allocation.Width, y));
+ if (action != null && !action (category, item, new Gdk.Size (Allocation.Width, y)))
+ return false;
ypos += y;
}
- return;
+ return true;
}
foreach (Item item in category.Items) {
if (!item.IsVisible)
@@ -804,11 +858,12 @@ namespace MonoDevelop.DesignerSupport.Toolbox
xpos = 0;
ypos += IconSize.Height;
}
- if (action != null)
- action (category, item, IconSize);
+ if (action != null && !action (category, item, IconSize))
+ return false;
xpos += IconSize.Width;
}
ypos += IconSize.Height;
+ return true;
}
void Iterate (ref int xpos, ref int ypos, CategoryAction catAction, ItemAction action)
@@ -818,18 +873,22 @@ namespace MonoDevelop.DesignerSupport.Toolbox
continue;
xpos = 0;
if (this.showCategories) {
-
- layout.SetText (category.Text);
- int x, y;
- layout.GetPixelSize (out x, out y);
- y += CategoryTopBottomPadding * 2;
+ int x, y = category.ItemHeight;
+
+ if (y == 0) {
+ layout.SetText (category.Text);
+ layout.GetPixelSize (out x, out y);
+ y += CategoryTopBottomPadding * 2;
+ category.ItemHeight = y;
+ }
- if (catAction != null)
- catAction (category, new Size (this.Allocation.Width, y));
+ if (catAction != null && !catAction (category, new Size (this.Allocation.Width, y)))
+ return;
ypos += y;
}
if (category.IsExpanded || category.AnimatingExpand || !this.showCategories) {
- IterateItems (category, ref xpos, ref ypos, action);
+ if (!IterateItems (category, ref xpos, ref ypos, action))
+ return;
}
}
}
@@ -1081,6 +1140,11 @@ namespace MonoDevelop.DesignerSupport.Toolbox
return text;
}
}
+
+ public int ItemHeight {
+ get;
+ set;
+ }
public bool IsVisible {
get {
diff --git a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/CustomDescriptor.cs b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/CustomDescriptor.cs
index 02dd858fc0..702d08915f 100644
--- a/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/CustomDescriptor.cs
+++ b/main/src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/CustomDescriptor.cs
@@ -115,10 +115,9 @@ namespace MonoDevelop.DesignerSupport
protected virtual Attribute[] GetCustomAttributes (string propertyName)
{
- if (IsReadOnly (propertyName))
- return new Attribute[] { ReadOnlyAttribute.Yes };
- else
- return null;
+ return IsReadOnly (propertyName) ? new Attribute[] {
+ ReadOnlyAttribute.Yes
+ } : null;
}
protected virtual bool IsReadOnly (string propertyName)
@@ -129,8 +128,8 @@ namespace MonoDevelop.DesignerSupport
class CustomProperty: PropertyDescriptor
{
- PropertyDescriptor prop;
- Attribute[] customAtts;
+ readonly PropertyDescriptor prop;
+ readonly Attribute[] customAtts;
public CustomProperty (PropertyDescriptor prop, Attribute[] customAtts): base (prop)
{
diff --git a/main/src/addins/MonoDevelop.GtkCore/libstetic/libstetic.csproj b/main/src/addins/MonoDevelop.GtkCore/libstetic/libstetic.csproj
index eb1701a30e..053a866ec1 100644
--- a/main/src/addins/MonoDevelop.GtkCore/libstetic/libstetic.csproj
+++ b/main/src/addins/MonoDevelop.GtkCore/libstetic/libstetic.csproj
@@ -27,7 +27,7 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
- <OutputPath>bin\Release</OutputPath>
+ <OutputPath>..\..\..\..\build\AddIns\MonoDevelop.GtkCore</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Execution>
@@ -35,7 +35,7 @@
</Execution>
<DebugSymbols>true</DebugSymbols>
<NoWarn>1591;1573</NoWarn>
- <DocumentationFile>bin\Release\libstetic.xml</DocumentationFile>
+ <DocumentationFile>..\..\..\..\build\AddIns\MonoDevelop.GtkCore\libstetic.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="Mono.Posix" />
diff --git a/main/src/addins/MonoDevelop.GtkCore/libstetic/wrapper/Misc.cs b/main/src/addins/MonoDevelop.GtkCore/libstetic/wrapper/Misc.cs
index 44624a73d6..757ab62afd 100644
--- a/main/src/addins/MonoDevelop.GtkCore/libstetic/wrapper/Misc.cs
+++ b/main/src/addins/MonoDevelop.GtkCore/libstetic/wrapper/Misc.cs
@@ -31,5 +31,10 @@ namespace Stetic.Wrapper
((Gtk.Misc)Wrapped).Xalign = 0.5f;
}
}
+
+ public static Gtk.Image CreateInstance ()
+ {
+ return new Gtk.Image (Gtk.Stock.MissingImage, Gtk.IconSize.Menu);
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.GtkCore/libsteticui/libsteticui.csproj b/main/src/addins/MonoDevelop.GtkCore/libsteticui/libsteticui.csproj
index fb9b52a59d..07386f8269 100644
--- a/main/src/addins/MonoDevelop.GtkCore/libsteticui/libsteticui.csproj
+++ b/main/src/addins/MonoDevelop.GtkCore/libsteticui/libsteticui.csproj
@@ -29,7 +29,7 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
- <OutputPath>bin\Release</OutputPath>
+ <OutputPath>..\..\..\..\build\AddIns\MonoDevelop.GtkCore</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Execution>
@@ -38,7 +38,7 @@
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<DebugSymbols>true</DebugSymbols>
<NoWarn>1591;1573</NoWarn>
- <DocumentationFile>bin\Release\libsteticui.xml</DocumentationFile>
+ <DocumentationFile>..\..\..\..\build\AddIns\MonoDevelop.GtkCore\libsteticui.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="Mono.Posix" />
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/PackageManagementStartupHandler.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/PackageManagementStartupHandler.cs
index 1177b4d023..4a9a933c57 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/PackageManagementStartupHandler.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/PackageManagementStartupHandler.cs
@@ -113,7 +113,7 @@ namespace MonoDevelop.PackageManagement.Commands
try {
PackageManagementServices.UpdatedPackagesInSolution.CheckForUpdates ();
} catch (Exception ex) {
- LoggingService.LogInternalError ("Check for NuGet package updates error.", ex);
+ LoggingService.LogError ("Check for NuGet package updates error.", ex);
}
}
@@ -125,7 +125,7 @@ namespace MonoDevelop.PackageManagement.Commands
e.Cancel = true;
}
} catch (Exception ex) {
- LoggingService.LogInternalError (ex);
+ LoggingService.LogError ("Error on unloading workspace item.", ex);
}
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackage.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackage.cs
index 1a22b06d86..7ebab31800 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackage.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackage.cs
@@ -231,6 +231,15 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers
public bool DevelopmentDependency { get; set; }
public bool IsValid { get; set; }
+
+ public IFileSystem FileSystemPassedToExtractContents;
+ public string ExtractPathPassedToExtractContents;
+
+ public void ExtractContents (IFileSystem fileSystem, string extractPath)
+ {
+ FileSystemPassedToExtractContents = fileSystem;
+ ExtractPathPassedToExtractContents = extractPath;
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageManagementProject.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageManagementProject.cs
index 8be17a5dfa..b4e225fdcf 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageManagementProject.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakePackageManagementProject.cs
@@ -92,7 +92,10 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers
public List<FakeUpdatePackageAction> FakeUpdatePackageActionsCreated =
new List<FakeUpdatePackageAction> ();
- public string Name { get; set; }
+ public string Name {
+ get { return FakeDotNetProject.Name; }
+ set { FakeDotNetProject.Name = value; }
+ }
public bool IsPackageInstalled (string packageId)
{
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeSettings.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeSettings.cs
index 769caa8028..24b3593320 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeSettings.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeSettings.cs
@@ -83,30 +83,30 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers
PackageSources.Add (valuePair);
}
- public Dictionary<string, KeyValuePair<string, string>> SavedSectionValues =
- new Dictionary<string, KeyValuePair<string, string>> ();
+ public Dictionary<string, SettingValue> SavedSectionValues =
+ new Dictionary<string, SettingValue> ();
public void SetValue (string section, string key, string value)
{
SavedSectionValues.Remove (section);
- SavedSectionValues.Add (section, new KeyValuePair<string, string> (key, value));
+ SavedSectionValues.Add (section, new SettingValue (key, value, false));
}
- public KeyValuePair<string, string> GetValuePassedToSetValueForActivePackageSourceSection ()
+ public SettingValue GetValuePassedToSetValueForActivePackageSourceSection ()
{
return SavedSectionValues [RegisteredPackageSourceSettings.ActivePackageSourceSectionName];
}
- public void SetValues (string section, IList<KeyValuePair<string, string>> values)
+ public void SetValues (string section, IList<SettingValue> values)
{
SavedSectionValueLists.Remove (section);
SavedSectionValueLists.Add (section, values);
}
- public Dictionary<string, IList<KeyValuePair<string, string>>> SavedSectionValueLists
- = new Dictionary<string, IList<KeyValuePair<string, string>>> ();
+ public Dictionary<string, IList<SettingValue>> SavedSectionValueLists
+ = new Dictionary<string, IList<SettingValue>> ();
- public IList<KeyValuePair<string, string>> GetValuesPassedToSetValuesForPackageSourcesSection ()
+ public IList<SettingValue> GetValuesPassedToSetValuesForPackageSourcesSection ()
{
return SavedSectionValueLists [PackageSourcesSectionName];
}
@@ -184,7 +184,7 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers
DisabledPackageSources.Add (setting);
}
- public IList<KeyValuePair<string, string>> GetValuesPassedToSetValuesForDisabledPackageSourcesSection ()
+ public IList<SettingValue> GetValuesPassedToSetValuesForDisabledPackageSourcesSection ()
{
return SavedSectionValueLists [DisabledPackageSourcesSectionName];
}
@@ -202,7 +202,7 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers
Sections.Add ("packageRestore", items);
}
- public KeyValuePair<string, string> GetValuePassedToSetValueForPackageRestoreSection ()
+ public SettingValue GetValuePassedToSetValueForPackageRestoreSection ()
{
return SavedSectionValues ["packageRestore"];
}
@@ -219,6 +219,16 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers
items.Add (new SettingValue ("repositoryPath", fullPath, false));
Sections.Add (ConfigSectionName, items);
}
+
+ public Dictionary<string, IList<SettingValue>> SectionsUpdated =
+ new Dictionary<string, IList<SettingValue>> ();
+
+ public void UpdateSections (string section, IList<SettingValue> values)
+ {
+ SectionsUpdated.Remove (section);
+ SectionsUpdated.Add (section, values);
+ SetValues (section, values);
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/TestableCheckForUpdatesTaskRunner.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableCheckForUpdatesTaskRunner.cs
index 548db011cc..6744012901 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/TestableCheckForUpdatesTaskRunner.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableCheckForUpdatesTaskRunner.cs
@@ -25,36 +25,32 @@
// THE SOFTWARE.
using System;
+using System.Collections.Generic;
using ICSharpCode.PackageManagement;
using MonoDevelop.Ide;
-using MonoDevelop.PackageManagement.Tests.Helpers;
-namespace MonoDevelop.PackageManagement.Tests
+namespace MonoDevelop.PackageManagement.Tests.Helpers
{
public class TestableCheckForUpdatesTaskRunner : CheckForUpdatesTaskRunner
{
- public TestableCheckForUpdatesTaskRunner (
- ITaskFactory taskFactory,
- IPackageManagementProgressMonitorFactory progressMonitorFactory,
- IPackageManagementEvents packageManagementEvents)
- : base (taskFactory, progressMonitorFactory, packageManagementEvents)
- {
- }
+ public List<string> LoggedErrorMessages = new List<string> ();
+ public List<Exception> LoggedExceptions = new List<Exception> ();
- protected override CheckForUpdatesProgressMonitor CreateProgressMonitor (
- IPackageManagementProgressMonitorFactory progressMonitorFactory,
- IPackageManagementEvents packageManagementEvents)
+ public TestableCheckForUpdatesTaskRunner (ITaskFactory taskFactory)
+ : base (taskFactory)
{
- ProgressMonitorCreated = new TestableCheckForUpdatesProgressMonitor (progressMonitorFactory, packageManagementEvents);
- return ProgressMonitorCreated;
}
- public TestableCheckForUpdatesProgressMonitor ProgressMonitorCreated { get; set; }
-
protected override void GuiBackgroundDispatch (MessageHandler handler)
{
handler.Invoke ();
}
+
+ protected override void LogError (string message, Exception ex)
+ {
+ LoggedErrorMessages.Add (message);
+ LoggedExceptions.Add (ex);
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj
index 0e9993c766..71f6d04262 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj
@@ -42,6 +42,7 @@
<OutputPath>..\..\..\..\build\tests</OutputPath>
<DebugSymbols>true</DebugSymbols>
<DebugType>pdbonly</DebugType>
+ <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
@@ -204,12 +205,13 @@
<Compile Include="MonoDevelop.PackageManagement.Tests\MSBuildTargetsRestoredMonitorTests.cs" />
<Compile Include="MonoDevelop.PackageManagement.Tests\EnsureNuGetPackageBuildImportsTargetUpdaterTests.cs" />
<Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\ExceptionThrowingSolutionPackageRepository.cs" />
- <Compile Include="MonoDevelop.PackageManagement.Tests\CheckForUpdatesProgressMonitorTests.cs" />
- <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\TestableCheckForUpdatesProgressMonitor.cs" />
- <Compile Include="MonoDevelop.PackageManagement.Tests\TestableCheckForUpdatesTaskRunner.cs" />
<Compile Include="MonoDevelop.PackageManagement.Tests\OpenPackageReadMeMonitorTests.cs" />
<Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\TestableInstallPackageAction.cs" />
<Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\TestableUpdatePackageAction.cs" />
+ <Compile Include="MonoDevelop.PackageManagement.Tests\FilePathExtensionsTests.cs" />
+ <Compile Include="MonoDevelop.PackageManagement.Tests\DotNetProjectExtensionsTests.cs" />
+ <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\TestableCheckForUpdatesTaskRunner.cs" />
+ <Compile Include="MonoDevelop.PackageManagement.Tests\MinClientVersionTests.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\core\MonoDevelop.Core\MonoDevelop.Core.csproj">
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/BackgroundPackageActionRunnerTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/BackgroundPackageActionRunnerTests.cs
index 1d8f5b7e51..cc692abc1d 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/BackgroundPackageActionRunnerTests.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/BackgroundPackageActionRunnerTests.cs
@@ -282,14 +282,14 @@ namespace MonoDevelop.PackageManagement.Tests
}
[Test]
- public void Run_OneInstallActionWithPowerShellScripts_WarningReportedToProgressMonitor ()
+ public void Run_OneInstallActionWithPowerShellScripts_WarningNotReportedToProgressMonitor ()
{
CreateRunner ();
AddInstallActionWithPowerShellScript ();
Run ();
- Assert.AreEqual ("Warning", progressMonitor.ReportedWarningMessage);
+ Assert.IsNull (progressMonitor.ReportedWarningMessage);
}
[Test]
@@ -300,7 +300,7 @@ namespace MonoDevelop.PackageManagement.Tests
Run ();
- progressMonitor.AssertMessageIsLogged ("Test Package contains PowerShell scripts which will not be run.");
+ progressMonitor.AssertMessageIsLogged ("WARNING: Test Package contains PowerShell scripts which will not be run.");
}
[Test]
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/CheckForUpdatesProgressMonitorTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/CheckForUpdatesProgressMonitorTests.cs
deleted file mode 100644
index 56abc52484..0000000000
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/CheckForUpdatesProgressMonitorTests.cs
+++ /dev/null
@@ -1,148 +0,0 @@
-//
-// CheckForUpdatesProgressMonitorTests.cs
-//
-// Author:
-// Matt Ward <matt.ward@xamarin.com>
-//
-// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
-//
-// 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 NUnit.Framework;
-using MonoDevelop.PackageManagement.Tests.Helpers;
-using MonoDevelop.Core;
-using ICSharpCode.PackageManagement;
-using NuGet;
-
-namespace MonoDevelop.PackageManagement.Tests
-{
- [TestFixture]
- public class CheckForUpdatesProgressMonitorTests
- {
- TestableCheckForUpdatesProgressMonitor progressMonitor;
- FakeProgressMonitorFactory progressMonitorFactory;
- FakeProgressMonitor fakeProgressMonitor;
- PackageManagementEvents packageEvents;
-
- void CreateProgressMonitor ()
- {
- progressMonitorFactory = new FakeProgressMonitorFactory ();
- fakeProgressMonitor = progressMonitorFactory.ProgressMonitor;
- packageEvents = new PackageManagementEvents ();
- progressMonitor = new TestableCheckForUpdatesProgressMonitor (progressMonitorFactory, packageEvents);
- }
-
- [Test]
- public void Constructor_NewInstance_CreatesProgressMonitor ()
- {
- CreateProgressMonitor ();
-
- Assert.AreEqual (GettextCatalog.GetString ("Checking for package updates..."), progressMonitorFactory.StatusText);
- }
-
- [Test]
- public void Dispose_NewInstance_ProgressMonitorIsDisposed ()
- {
- CreateProgressMonitor ();
-
- progressMonitor.Dispose ();
-
- Assert.IsTrue (fakeProgressMonitor.IsDisposed);
- }
-
- [Test]
- public void Constructor_PackageManagementMessageEventFired_MessageLoggedToProgressMonitor ()
- {
- CreateProgressMonitor ();
-
- packageEvents.OnPackageOperationMessageLogged (MessageLevel.Info, "MyMessage");
-
- fakeProgressMonitor.AssertMessageIsLogged ("MyMessage");
- }
-
- [Test]
- public void Dispose_MessageLoggedAfterDispose_MessageNotLoggedToProgressMonitor ()
- {
- CreateProgressMonitor ();
- progressMonitor.Dispose ();
-
- packageEvents.OnPackageOperationMessageLogged (MessageLevel.Info, "MyMessage");
-
- fakeProgressMonitor.AssertMessageIsNotLogged ("MyMessage");
- }
-
- [Test]
- public void ReportError_ReportException_ExceptionReportedToProgressMonitor ()
- {
- CreateProgressMonitor ();
- var exception = new Exception ("Error");
-
- progressMonitor.ReportError (exception);
-
- fakeProgressMonitor.AssertMessageIsLogged ("Error");
- Assert.AreEqual (GettextCatalog.GetString ("Could not check for package updates."), fakeProgressMonitor.ReportedErrorMessage);
- Assert.IsTrue (progressMonitor.IsPackageConsoleShown);
- }
-
- [Test]
- public void ReportError_ReportDispatchServiceException_UnderlyingExceptionReported ()
- {
- CreateProgressMonitor ();
- var exception = new Exception ("Error");
- string message = "An exception was thrown while dispatching a method call in the UI thread.";
- var dispatchServiceException = new Exception (message, exception);
-
- progressMonitor.ReportError (dispatchServiceException);
-
- fakeProgressMonitor.AssertMessageIsLogged ("Error");
- }
-
- [Test]
- public void ReportSuccess_UpdatesAvailable_UpdatesAvailableMessageShownByProgressMonitor ()
- {
- CreateProgressMonitor ();
-
- progressMonitor.ReportSuccess (true);
-
- Assert.AreEqual (GettextCatalog.GetString ("Package updates are available."), fakeProgressMonitor.ReportedSuccessMessage);
- }
-
- [Test]
- public void ReportSuccess_NoUpdatesAvailable_NoUpdatesAvailableMessageShownByProgressMonitor ()
- {
- CreateProgressMonitor ();
-
- progressMonitor.ReportSuccess (false);
-
- Assert.AreEqual (GettextCatalog.GetString ("Packages are up to date."), fakeProgressMonitor.ReportedSuccessMessage);
- }
-
- [Test]
- public void ReportSuccess_NoUpdatesAvailableButWarningLogged_NoUpdatesAvailableWithWarningMessageShownByProgressMonitor ()
- {
- CreateProgressMonitor ();
- packageEvents.OnPackageOperationMessageLogged (MessageLevel.Warning, "WarningMessage");
-
- progressMonitor.ReportSuccess (false);
-
- Assert.AreEqual (GettextCatalog.GetString ("No updates found but warnings were reported."), fakeProgressMonitor.ReportedWarningMessage);
- }
- }
-}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/DotNetProjectExtensionsTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/DotNetProjectExtensionsTests.cs
new file mode 100644
index 0000000000..a0d6d171cc
--- /dev/null
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/DotNetProjectExtensionsTests.cs
@@ -0,0 +1,135 @@
+//
+// DotNetProjectExtensionsTests.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2015 Xamarin Inc. (http://xamarin.com)
+//
+// 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.Collections.Generic;
+using ICSharpCode.PackageManagement;
+using MonoDevelop.PackageManagement.Tests.Helpers;
+using NUnit.Framework;
+
+namespace MonoDevelop.PackageManagement.Tests
+{
+ [TestFixture]
+ public class DotNetProjectExtensionsTests
+ {
+ List<string> existingFiles;
+ FakeDotNetProject project;
+
+ [SetUp]
+ public void Init ()
+ {
+ existingFiles = new List<string> ();
+ DotNetProjectExtensions.FileExists = existingFiles.Contains;
+ }
+
+ void CreateProject (string fileName, string projectName)
+ {
+ project = new FakeDotNetProject (fileName.ToNativePath ()) {
+ Name = projectName
+ };
+ }
+
+ void AddExistingFile (string fileName)
+ {
+ existingFiles.Add (fileName.ToNativePath ());
+ }
+
+ [Test]
+ public void GetPackagesConfigFilePath_ProjectPackagesConfigFileDoesNotExist_ReturnsDefaultPackagesConfigFile ()
+ {
+ CreateProject (@"d:\projects\MyProject.csproj", "MyProject");
+
+ string fileName = project.GetPackagesConfigFilePath ();
+
+ Assert.AreEqual (@"d:\projects\packages.config".ToNativePath (), fileName);
+ }
+
+ [Test]
+ public void GetPackagesConfigFilePath_ProjectPackagesConfigFileExists_ReturnsPackagesConfigFileNamedAfterProject ()
+ {
+ CreateProject (@"d:\projects\MyProject.csproj", "MyProject");
+ AddExistingFile (@"d:\projects\packages.MyProject.config");
+
+ string fileName = project.GetPackagesConfigFilePath ();
+
+ Assert.AreEqual (@"d:\projects\packages.MyProject.config".ToNativePath (), fileName);
+ }
+
+ [Test]
+ public void GetPackagesConfigFilePath_ProjectNameHasSpaceProjectPackagesConfigFileExists_ReturnsPackagesConfigFileNamedAfterProject ()
+ {
+ CreateProject (@"d:\projects\MyProject.csproj", "My Project");
+ AddExistingFile (@"d:\projects\packages.My_Project.config");
+
+ string fileName = project.GetPackagesConfigFilePath ();
+
+ Assert.AreEqual (@"d:\projects\packages.My_Project.config".ToNativePath (), fileName);
+ }
+
+ [Test]
+ public void HasPackages_PackagesConfigFileDoesNotExist_ReturnsFalse ()
+ {
+ CreateProject (@"d:\projects\MyProject.csproj", "MyProject");
+
+ bool result = project.HasPackages ();
+
+ Assert.IsFalse (result);
+ }
+
+ [Test]
+ public void HasPackages_PackagesConfigFileExistsInProjectDirectory_ReturnsTrue ()
+ {
+ CreateProject (@"d:\projects\MyProject.csproj", "MyProject");
+ AddExistingFile (@"d:\projects\packages.config");
+
+ bool result = project.HasPackages ();
+
+ Assert.IsTrue (result);
+ }
+
+ [Test]
+ public void HasPackages_ProjectPackagesConfigFileExistsInProjectDirectory_ReturnsTrue ()
+ {
+ CreateProject (@"d:\projects\MyProject.csproj", "MyProject");
+ AddExistingFile (@"d:\projects\packages.MyProject.config");
+
+ bool result = project.HasPackages ();
+
+ Assert.IsTrue (result);
+ }
+
+ [Test]
+ public void HasPackages_ProjectNameHasSpaceAndProjectPackagesConfigFileExistsInProjectDirectory_ReturnsTrue ()
+ {
+ CreateProject (@"d:\projects\MyProject.csproj", "My Project");
+ AddExistingFile (@"d:\projects\packages.My_Project.config");
+
+ bool result = project.HasPackages ();
+
+ Assert.IsTrue (result);
+ }
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/FilePathExtensionsTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/FilePathExtensionsTests.cs
new file mode 100644
index 0000000000..c3af8c2487
--- /dev/null
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/FilePathExtensionsTests.cs
@@ -0,0 +1,111 @@
+//
+// FilePathExtensionsTests.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2015 Xamarin Inc. (http://xamarin.com)
+//
+// 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 MonoDevelop.Core;
+using MonoDevelop.PackageManagement.Tests.Helpers;
+using NUnit.Framework;
+
+namespace MonoDevelop.PackageManagement.Tests
+{
+ [TestFixture]
+ public class FilePathExtensionsTests
+ {
+ FilePath CreateFilePath (string fileName)
+ {
+ return new FilePath (fileName.ToNativePath ());
+ }
+
+ [Test]
+ public void IsPackagesConfigFileName_Null_ReturnsFalse ()
+ {
+ FilePath nullPath = null;
+ bool result = nullPath.IsPackagesConfigFileName ();
+
+ Assert.IsFalse (result);
+ }
+
+ [Test]
+ public void IsPackagesConfigFileName_TextFile_ReturnsFalse ()
+ {
+ FilePath filePath = CreateFilePath (@"d:\projects\foo.txt");
+
+ bool result = filePath.IsPackagesConfigFileName ();
+
+ Assert.IsFalse (result);
+ }
+
+ [Test]
+ public void IsPackagesConfigFileName_PackagesConfigFile_ReturnsTrue ()
+ {
+ FilePath filePath = CreateFilePath (@"d:\projects\packages.config");
+
+ bool result = filePath.IsPackagesConfigFileName ();
+
+ Assert.IsTrue (result);
+ }
+
+ [Test]
+ public void IsPackagesConfigFileName_PackagesConfigFileInUpperCase_ReturnsTrue ()
+ {
+ FilePath filePath = CreateFilePath (@"d:\projects\PACKAGES.CONFIG");
+
+ bool result = filePath.IsPackagesConfigFileName ();
+
+ Assert.IsTrue (result);
+ }
+
+ [Test]
+ public void IsPackagesConfigFileName_PackagesConfigFileNamedAfterProject_ReturnsTrue ()
+ {
+ FilePath filePath = CreateFilePath (@"d:\projects\packages.MyProject.config");
+
+ bool result = filePath.IsPackagesConfigFileName ();
+
+ Assert.IsTrue (result);
+ }
+
+ [Test]
+ public void IsPackagesConfigFileName_PackagesConfigFileNamedAfterProjectInDifferentCase_ReturnsTrue ()
+ {
+ FilePath filePath = CreateFilePath (@"d:\projects\PACKAGES.MyProject.CONFIG");
+
+ bool result = filePath.IsPackagesConfigFileName ();
+
+ Assert.IsTrue (result);
+ }
+
+ [Test]
+ public void IsPackagesConfigFileName_PackagesConfigFileNamedAfterProjectButStartsWithProjectName_ReturnsFalse ()
+ {
+ FilePath filePath = CreateFilePath (@"d:\projects\MyProject.packages.config");
+
+ bool result = filePath.IsPackagesConfigFileName ();
+
+ Assert.IsFalse (result);
+ }
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/InstallPackageActionTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/InstallPackageActionTests.cs
index b8261410a8..584bf146be 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/InstallPackageActionTests.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/InstallPackageActionTests.cs
@@ -484,7 +484,7 @@ namespace MonoDevelop.PackageManagement.Tests
}
[Test]
- public void Execute_PackageBeingInstalledHasPowerShellScripts_WarningAboutPowerShellScriptsIsLogged ()
+ public void Execute_PackageBeingInstalledHasPowerShellScripts_MessageAboutPowerShellScriptsIsLogged ()
{
CreateAction ();
FakePackage expectedPackage = fakeProject.FakeSourceRepository.AddFakePackageWithVersion ("Test", "1.0");
@@ -493,16 +493,16 @@ namespace MonoDevelop.PackageManagement.Tests
action.PackageId = expectedPackage.Id;
action.PackageVersion = expectedPackage.Version;
fakeProject.FakeInstallOperations.Add (operation);
- string messageLogged = null;
+ var messagesLogged = new List<string> ();
packageManagementEvents.PackageOperationMessageLogged += (sender, e) => {
- if (e.Message.Level == MessageLevel.Warning) {
- messageLogged = e.Message.ToString ();
+ if (e.Message.Level == MessageLevel.Info) {
+ messagesLogged.Add (e.Message.ToString ());
}
};
action.Execute ();
- Assert.AreEqual ("Test Package contains PowerShell scripts which will not be run.", messageLogged);
+ Assert.That (messagesLogged, Contains.Item ("WARNING: Test Package contains PowerShell scripts which will not be run."));
}
[Test]
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/MinClientVersionTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/MinClientVersionTests.cs
new file mode 100644
index 0000000000..4fa2b48c68
--- /dev/null
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/MinClientVersionTests.cs
@@ -0,0 +1,69 @@
+//
+// MinClientVersionTests.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2015 Xamarin Inc. (http://xamarin.com)
+//
+// 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 MonoDevelop.PackageManagement.Tests.Helpers;
+using NuGet;
+using NUnit.Framework;
+
+namespace MonoDevelop.PackageManagement.Tests
+{
+ [TestFixture]
+ public class MinClientVersionTests
+ {
+ FakePackage CreatePackageWithMinClientVersion (string minClientVersion)
+ {
+ return new FakePackage ("Test", "1.0") {
+ MinClientVersion = new Version (minClientVersion)
+ };
+ }
+
+ void WalkPackage (IPackage package)
+ {
+ var localRepository = new FakePackageRepository ();
+ var sourceRepository = new FakePackageRepository ();
+ var walker = new InstallWalker (localRepository, sourceRepository, null, NullLogger.Instance, true, false, DependencyVersion.Lowest);
+ walker.Walk (package);
+ }
+
+ [Test]
+ public void MinClientVersion_MicrosoftApplicationInsights_ShouldBeSupportedByNuGet ()
+ {
+ FakePackage package = CreatePackageWithMinClientVersion ("2.8.50313");
+
+ Assert.DoesNotThrow (() => WalkPackage (package));
+ }
+
+ [Test]
+ public void MinClientVersion_VeryHighNuGetVersion_ShouldNotBeSupportedByNuGet ()
+ {
+ FakePackage package = CreatePackageWithMinClientVersion ("9999.99");
+
+ Assert.Throws<NuGetVersionNotSatisfiedException> (() => WalkPackage (package));
+ }
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/MonoDevelopProjectSystemTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/MonoDevelopProjectSystemTests.cs
index 9d67d3f590..fd3280c147 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/MonoDevelopProjectSystemTests.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/MonoDevelopProjectSystemTests.cs
@@ -1133,17 +1133,24 @@ namespace MonoDevelop.PackageManagement.Tests
}
[Test]
- public void RemoveImport_ImportAlreadyAddedToBottomOfProject_ProjectBuilderIsDisposed ()
+ public void RemoveImport_ImportAlreadyAddedToBottomOfProject_ImportRemovedEventIsFired ()
{
CreateTestProject (@"d:\projects\MyProject\MyProject\MyProject.csproj");
CreateProjectSystem (project);
string targetPath = @"d:\projects\MyProject\packages\Foo.0.1\build\Foo.targets".ToNativePath ();
projectSystem.AddImport (targetPath, ProjectImportLocation.Bottom);
+ const string expectedImportRemoved = @"..\packages\Foo.0.1\build\Foo.targets";
+ DotNetProjectImportEventArgs eventArgs = null;
+ projectSystem.PackageManagementEvents.ImportRemoved += (sender, e) => {
+ eventArgs = e;
+ };
projectSystem.RemoveImport (targetPath);
- AssertImportRemoved (@"..\packages\Foo.0.1\build\Foo.targets");
- Assert.IsTrue (project.IsProjectBuilderDisposed);
+ AssertImportRemoved (expectedImportRemoved);
+ Assert.IsFalse (project.IsProjectBuilderDisposed);
+ Assert.AreEqual (project, eventArgs.Project);
+ Assert.AreEqual (expectedImportRemoved, eventArgs.Import);
}
[Test]
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageFromRepositoryTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageFromRepositoryTests.cs
index b3ad384a74..c83b4aee72 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageFromRepositoryTests.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageFromRepositoryTests.cs
@@ -462,6 +462,19 @@ namespace MonoDevelop.PackageManagement.Tests
Assert.IsTrue (dependency);
}
+
+ [Test]
+ public void ExtractPath_WrappedPackage_WrappedPackageExtractContentsCalled ()
+ {
+ CreatePackage ();
+ var expectedFileSystem = new FakeFileSystem ();
+ string expectedPath = @"d:\projects\test\packages";
+
+ package.ExtractContents (expectedFileSystem, expectedPath);
+
+ Assert.AreEqual (expectedFileSystem, fakePackage.FileSystemPassedToExtractContents);
+ Assert.AreEqual (expectedPath, fakePackage.ExtractPathPassedToExtractContents);
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageManagementOptionsTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageManagementOptionsTests.cs
index f0bf3da6ca..48f81bc6d7 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageManagementOptionsTests.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageManagementOptionsTests.cs
@@ -179,16 +179,16 @@ namespace MonoDevelop.PackageManagement.Tests
registeredPackageSources.Clear ();
registeredPackageSources.Add (packageSource);
- var expectedSavedPackageSourceSettings = new List<KeyValuePair<string, string>> ();
- expectedSavedPackageSourceSettings.Add (new KeyValuePair<string, string> ("Test", "http://codeplex.com"));
+ var expectedSavedPackageSourceSettings = new List<SettingValue> ();
+ expectedSavedPackageSourceSettings.Add (new SettingValue ("Test", "http://codeplex.com", false));
- IList<KeyValuePair<string, string>> actualSavedPackageSourceSettings = fakeSettings.GetValuesPassedToSetValuesForPackageSourcesSection ();
+ IList<SettingValue> actualSavedPackageSourceSettings = fakeSettings.GetValuesPassedToSetValuesForPackageSourcesSection ();
Assert.AreEqual (expectedSavedPackageSourceSettings, actualSavedPackageSourceSettings);
}
[Test]
- public void PackageSources_OnePackageSourceAdded_PackageSourcesSectionDeletedFromSettings ()
+ public void PackageSources_OnePackageSourceAdded_PackageSourcesSectionUpdated ()
{
CreateSettings ();
CreateOptions (fakeSettings);
@@ -198,9 +198,11 @@ namespace MonoDevelop.PackageManagement.Tests
registeredPackageSources.Clear ();
registeredPackageSources.Add (packageSource);
- bool sectionDeleted = fakeSettings.IsPackageSourcesSectionDeleted;
+ IList<SettingValue> settings = fakeSettings.SectionsUpdated [RegisteredPackageSourceSettings.PackageSourcesSectionName];
- Assert.IsTrue (sectionDeleted);
+ Assert.AreEqual (1, settings.Count);
+ Assert.AreEqual ("Test", settings[0].Key);
+ Assert.AreEqual ("http://codeplex.com", settings[0].Value);
}
[Test]
@@ -230,10 +232,10 @@ namespace MonoDevelop.PackageManagement.Tests
options.ActivePackageSource = packageSource;
- var expectedKeyValuePair = new KeyValuePair<string, string> ("Test", "http://sharpdevelop.com");
- KeyValuePair<string, string> actualKeyValuePair = fakeSettings.GetValuePassedToSetValueForActivePackageSourceSection ();
+ var expectedSetting = new SettingValue ("Test", "http://sharpdevelop.com", false);
+ SettingValue actualSetting = fakeSettings.GetValuePassedToSetValueForActivePackageSourceSection ();
- Assert.AreEqual (expectedKeyValuePair, actualKeyValuePair);
+ Assert.AreEqual (expectedSetting, actualSetting);
}
[Test]
@@ -395,9 +397,9 @@ namespace MonoDevelop.PackageManagement.Tests
registeredPackageSources.Clear ();
registeredPackageSources.Add (packageSource);
- bool sectionDeleted = fakeSettings.IsDisabledPackageSourcesSectionDeleted;
+ IList<SettingValue> settings = fakeSettings.SectionsUpdated[RegisteredPackageSourceSettings.DisabledPackageSourceSectionName];
- Assert.IsTrue (sectionDeleted);
+ Assert.AreEqual (0, settings.Count);
}
[Test]
@@ -411,10 +413,10 @@ namespace MonoDevelop.PackageManagement.Tests
registeredPackageSources.Clear ();
registeredPackageSources.Add (packageSource);
- var expectedSavedPackageSourceSettings = new List<KeyValuePair<string, string>> ();
- expectedSavedPackageSourceSettings.Add (new KeyValuePair<string, string> (packageSource.Name, "true"));
+ var expectedSavedPackageSourceSettings = new List<SettingValue> ();
+ expectedSavedPackageSourceSettings.Add (new SettingValue (packageSource.Name, "true", false));
- IList<KeyValuePair<string, string>> actualSavedPackageSourceSettings =
+ IList<SettingValue> actualSavedPackageSourceSettings =
fakeSettings.GetValuesPassedToSetValuesForDisabledPackageSourcesSection ();
Assert.AreEqual (expectedSavedPackageSourceSettings, actualSavedPackageSourceSettings);
}
@@ -430,7 +432,7 @@ namespace MonoDevelop.PackageManagement.Tests
registeredPackageSources.Clear ();
registeredPackageSources.Add (packageSource);
- IList<KeyValuePair<string, string>> actualSavedPackageSourceSettings =
+ IList<SettingValue> actualSavedPackageSourceSettings =
fakeSettings.GetValuesPassedToSetValuesForDisabledPackageSourcesSection ();
Assert.AreEqual (0, actualSavedPackageSourceSettings.Count);
}
@@ -464,10 +466,10 @@ namespace MonoDevelop.PackageManagement.Tests
options.IsPackageRestoreEnabled = true;
- KeyValuePair<string, string> keyPair = fakeSettings.GetValuePassedToSetValueForPackageRestoreSection ();
+ SettingValue setting = fakeSettings.GetValuePassedToSetValueForPackageRestoreSection ();
- Assert.AreEqual ("enabled", keyPair.Key);
- Assert.AreEqual ("True", keyPair.Value);
+ Assert.AreEqual ("enabled", setting.Key);
+ Assert.AreEqual ("True", setting.Value);
}
[Test]
@@ -492,8 +494,8 @@ namespace MonoDevelop.PackageManagement.Tests
options.IsPackageRestoreEnabled = false;
- KeyValuePair<string, string> keyValuePair = fakeSettings.GetValuePassedToSetValueForPackageRestoreSection ();
- Assert.AreEqual ("False", keyValuePair.Value);
+ SettingValue setting = fakeSettings.GetValuePassedToSetValueForPackageRestoreSection ();
+ Assert.AreEqual ("False", setting.Value);
}
[Test]
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/UninstallPackageActionTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/UninstallPackageActionTests.cs
index 885c10c377..948780a2ab 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/UninstallPackageActionTests.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/UninstallPackageActionTests.cs
@@ -24,8 +24,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-using System;
using System.Collections.Generic;
+using System.Linq;
using ICSharpCode.PackageManagement;
using MonoDevelop.PackageManagement.Tests.Helpers;
using NuGet;
@@ -246,22 +246,22 @@ namespace MonoDevelop.PackageManagement.Tests
}
[Test]
- public void Execute_PackageHasPowerShellUninstallScript_PowerShellWarningLogged ()
+ public void Execute_PackageHasPowerShellUninstallScript_PowerShellInfoLogged ()
{
CreateAction ();
FakePackage package = FakePackage.CreatePackageWithVersion ("Test", "1.0");
action.Package = package;
package.AddFile (@"tools\uninstall.ps1");
- string messageLogged = null;
+ var messagesLogged = new List<string> ();
packageManagementEvents.PackageOperationMessageLogged += (sender, e) => {
- if (e.Message.Level == MessageLevel.Warning) {
- messageLogged = e.Message.ToString ();
+ if (e.Message.Level == MessageLevel.Info) {
+ messagesLogged.Add (e.Message.ToString ());
}
};
action.Execute ();
- Assert.AreEqual ("Test Package contains PowerShell scripts which will not be run.", messageLogged);
+ Assert.That (messagesLogged, Contains.Item ("WARNING: Test Package contains PowerShell scripts which will not be run."));
}
[Test]
@@ -271,16 +271,14 @@ namespace MonoDevelop.PackageManagement.Tests
FakePackage package = FakePackage.CreatePackageWithVersion ("Test", "1.0");
action.Package = package;
package.AddFile (@"tools\install.ps1");
- bool messageLogged = false;
+ var messagesLogged = new List<string> ();
packageManagementEvents.PackageOperationMessageLogged += (sender, e) => {
- if (e.Message.Level == MessageLevel.Warning) {
- messageLogged = true;
- }
+ messagesLogged.Add (e.Message.ToString ());
};
action.Execute ();
- Assert.IsFalse (messageLogged);
+ Assert.IsFalse (messagesLogged.Any (message => message.Contains ("PowerShell")));
}
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/UpdatePackageActionTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/UpdatePackageActionTests.cs
index e72db1df04..15c0419c37 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/UpdatePackageActionTests.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/UpdatePackageActionTests.cs
@@ -635,6 +635,22 @@ namespace MonoDevelop.PackageManagement.Tests
Assert.IsFalse (fileService.IsOpenFileCalled);
Assert.IsTrue (monitor.IsDisposed);
}
+
+ [Test]
+ public void Execute_PackagesConfigFileNamedAfterProjectDeletedDuringUpdate_FileServicePackagesConfigFileDeletionIsCancelled ()
+ {
+ CreateSolution ();
+ action.Package = new FakePackage ("Test");
+ string expectedFileName = @"d:\projects\MyProject\packages.MyProject.config".ToNativePath ();
+ bool? fileRemovedResult = null;
+ fakeProject.UpdatePackageAction = (p, a) => {
+ fileRemovedResult = packageManagementEvents.OnFileRemoving (expectedFileName);
+ };
+ action.Execute ();
+
+ Assert.AreEqual (expectedFileName, fileRemover.FileRemoved);
+ Assert.IsFalse (fileRemovedResult.Value);
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/UpdatedPackagesInSolutionTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/UpdatedPackagesInSolutionTests.cs
index 0469b53d99..a67593fd7c 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/UpdatedPackagesInSolutionTests.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/UpdatedPackagesInSolutionTests.cs
@@ -54,10 +54,7 @@ namespace MonoDevelop.PackageManagement.Tests
taskFactory = new FakeTaskFactory ();
taskFactory.RunTasksSynchronously = true;
progressMonitorFactory = new FakeProgressMonitorFactory ();
- checkForUpdatesTaskRunner = new TestableCheckForUpdatesTaskRunner (
- taskFactory,
- progressMonitorFactory,
- packageManagementEvents);
+ checkForUpdatesTaskRunner = new TestableCheckForUpdatesTaskRunner (taskFactory);
updatedPackagesInSolution = new TestableUpdatedPackagesInSolution (
solution,
registeredPackageRepositories,
@@ -387,61 +384,7 @@ namespace MonoDevelop.PackageManagement.Tests
}
[Test]
- public void CheckForUpdates_OnePackageUpdated_ProgressMonitorCreatedAndDisposedAfterCheckForUpdatesReturned ()
- {
- CreateUpdatedPackagesInSolution ();
- taskFactory.RunTasksSynchronously = false;
- FakePackageManagementProject project = AddProjectToSolution ();
- project.AddPackageReference ("MyPackage", "1.0");
- AddUpdatedPackageToAggregateSourceRepository ("MyPackage", "1.1");
- updatedPackagesInSolution.CheckForUpdates ();
- bool progressMonitorCreated = checkForUpdatesTaskRunner.ProgressMonitorCreated != null;
- bool disposedBeforeTaskRun = progressMonitorFactory.ProgressMonitor.IsDisposed;
-
- taskFactory.ExecuteAllTasks<CheckForUpdatesTask> ();
-
- Assert.IsTrue (progressMonitorCreated);
- Assert.IsFalse (disposedBeforeTaskRun);
- Assert.IsTrue (progressMonitorFactory.ProgressMonitor.IsDisposed);
- }
-
- [Test]
- public void CheckForUpdates_OnePackageUpdatedButSolutionClosedBeforeResultsReturned_ProgressMonitorIsDisposed ()
- {
- CreateUpdatedPackagesInSolution ();
- taskFactory.RunTasksSynchronously = false;
- FakePackageManagementProject project = AddProjectToSolution ();
- project.AddPackageReference ("MyPackage", "1.0");
- AddUpdatedPackageToAggregateSourceRepository ("MyPackage", "1.1");
- updatedPackagesInSolution.CheckForUpdates ();
- bool progressMonitorCreated = checkForUpdatesTaskRunner.ProgressMonitorCreated != null;
- bool disposedBeforeTaskRun = progressMonitorFactory.ProgressMonitor.IsDisposed;
- var task = taskFactory.FakeTasksCreated [0] as FakeTask<CheckForUpdatesTask>;
- task.ExecuteTaskButNotContinueWith ();
- updatedPackagesInSolution.Clear ();
-
- task.ExecuteContinueWith ();
-
- Assert.IsTrue (progressMonitorCreated);
- Assert.IsFalse (disposedBeforeTaskRun);
- Assert.IsTrue (progressMonitorFactory.ProgressMonitor.IsDisposed);
- }
-
- [Test]
- public void CheckForUpdates_OnePackageUpdated_SuccessReportedToProgressMonitor ()
- {
- CreateUpdatedPackagesInSolution ();
- FakePackageManagementProject project = AddProjectToSolution ();
- project.AddPackageReference ("MyPackage", "1.0");
- AddUpdatedPackageToAggregateSourceRepository ("MyPackage", "1.1");
-
- updatedPackagesInSolution.CheckForUpdates ();
-
- Assert.AreEqual (GettextCatalog.GetString ("Package updates are available."), progressMonitorFactory.ProgressMonitor.ReportedSuccessMessage);
- }
-
- [Test]
- public void CheckForUpdates_NoPackagesUpdated_SuccessReportedToProgressMonitor ()
+ public void CheckForUpdates_NoPackagesUpdated_NoUpdates ()
{
CreateUpdatedPackagesInSolution ();
FakePackageManagementProject project = AddProjectToSolution ();
@@ -451,11 +394,10 @@ namespace MonoDevelop.PackageManagement.Tests
UpdatedPackagesInProject updatedPackages = updatedPackagesInSolution.GetUpdatedPackages (project.Project);
Assert.IsFalse (updatedPackagesInSolution.AnyUpdates ());
- Assert.AreEqual (GettextCatalog.GetString ("Packages are up to date."), progressMonitorFactory.ProgressMonitor.ReportedSuccessMessage);
}
[Test]
- public void CheckForUpdates_ExceptionThrownWhilstCheckingForUpdates_ErrorReportedToProgressMonitorWhichIsDisposed ()
+ public void CheckForUpdates_ExceptionThrownWhilstCheckingForUpdates_ExceptionLogged ()
{
CreateUpdatedPackagesInSolution ();
taskFactory.RunTasksSynchronously = false;
@@ -471,14 +413,12 @@ namespace MonoDevelop.PackageManagement.Tests
task.Result = null;
task.ExecuteContinueWith ();
- Assert.AreEqual (GettextCatalog.GetString ("Could not check for package updates."), progressMonitorFactory.ProgressMonitor.ReportedErrorMessage);
- Assert.IsTrue (checkForUpdatesTaskRunner.ProgressMonitorCreated.IsPackageConsoleShown);
- progressMonitorFactory.ProgressMonitor.AssertMessageIsLogged ("Inner exception error message");
- Assert.IsTrue (progressMonitorFactory.ProgressMonitor.IsDisposed);
+ Assert.AreEqual ("Current check for updates task error.", checkForUpdatesTaskRunner.LoggedErrorMessages[0]);
+ Assert.AreEqual (task.Exception, checkForUpdatesTaskRunner.LoggedExceptions[0]);
}
[Test]
- public void CheckForUpdates_ExceptionThrownWhilstCheckingForUpdatesButSolutionClosedBeforeCheckForUpdatesReturns_ErrorIsNotReportedButProgressMonitorIsDisposed ()
+ public void CheckForUpdates_ExceptionThrownWhilstCheckingForUpdatesButSolutionClosedBeforeCheckForUpdatesReturns_ErrorIsLogged ()
{
CreateUpdatedPackagesInSolution ();
taskFactory.RunTasksSynchronously = false;
@@ -494,13 +434,12 @@ namespace MonoDevelop.PackageManagement.Tests
task.Result = null;
task.ExecuteContinueWith ();
- Assert.IsNull (progressMonitorFactory.ProgressMonitor.ReportedErrorMessage);
- progressMonitorFactory.ProgressMonitor.AssertMessageIsNotLogged ("Error message");
- Assert.IsTrue (progressMonitorFactory.ProgressMonitor.IsDisposed);
+ Assert.AreEqual ("Check for updates task error.", checkForUpdatesTaskRunner.LoggedErrorMessages[0]);
+ Assert.AreEqual (task.Exception, checkForUpdatesTaskRunner.LoggedExceptions[0]);
}
[Test]
- public void CheckForUpdates_ExceptionThrownWhilstCheckingForUpdatesButSolutionClosedBeforeCheckForUpdatesReturnsAndSecondCheckForUpdatesIsStarted_ErrorIsNotReported ()
+ public void CheckForUpdates_ExceptionThrownWhilstCheckingForUpdatesButSolutionClosedBeforeCheckForUpdatesReturnsAndSecondCheckForUpdatesIsStarted_ErrorIsLogged ()
{
CreateUpdatedPackagesInSolution ();
taskFactory.RunTasksSynchronously = false;
@@ -516,9 +455,8 @@ namespace MonoDevelop.PackageManagement.Tests
task.Result = null;
task.ExecuteContinueWith ();
- Assert.IsNull (progressMonitorFactory.ProgressMonitor.ReportedErrorMessage);
- progressMonitorFactory.ProgressMonitor.AssertMessageIsNotLogged ("Error message");
- Assert.IsTrue (progressMonitorFactory.ProgressMonitor.IsDisposed);
+ Assert.AreEqual ("Check for updates task error.", checkForUpdatesTaskRunner.LoggedErrorMessages[0]);
+ Assert.AreEqual (task.Exception, checkForUpdatesTaskRunner.LoggedExceptions[0]);
}
[Test]
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.csproj b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.csproj
index 28a2416b09..e1673e7ae1 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.csproj
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.csproj
@@ -46,6 +46,7 @@
<OutputPath>..\..\..\build\AddIns\MonoDevelop.PackageManagement</OutputPath>
<DebugSymbols>true</DebugSymbols>
<DebugType>pdbonly</DebugType>
+ <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
</PropertyGroup>
<ItemGroup>
<Reference Include="pango-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
@@ -342,7 +343,6 @@
<Compile Include="MonoDevelop.PackageManagement\IUpdatedPackagesInSolution.cs" />
<Compile Include="MonoDevelop.PackageManagement\FallbackRepository.cs" />
<Compile Include="MonoDevelop.PackageManagement.Commands\PackageManagementStartupHandler.cs" />
- <Compile Include="MonoDevelop.PackageManagement\PackageUpdatesEventMonitor.cs" />
<Compile Include="MonoDevelop.PackageManagement\UpdatedPackagesMonitor.cs" />
<Compile Include="MonoDevelop.PackageManagement\UpdatePackagesProgressMonitorStatusMessage.cs" />
<Compile Include="MonoDevelop.PackageManagement\CheckForUpdatedPackagesAction.cs" />
@@ -364,16 +364,17 @@
<Compile Include="MonoDevelop.PackageManagement\MSBuildTargetsRestoredMonitor.cs" />
<Compile Include="MonoDevelop.PackageManagement\PackageManagementMSBuildExtension.cs" />
<Compile Include="MonoDevelop.PackageManagement\EnsureNuGetPackageBuildImportsTargetUpdater.cs" />
- <Compile Include="MonoDevelop.PackageManagement\CheckForUpdatesProgressMonitor.cs" />
<Compile Include="MonoDevelop.PackageManagement\CheckForUpdatesTaskRunner.cs" />
<Compile Include="MonoDevelop.PackageManagement\CheckForUpdatesTask.cs" />
<Compile Include="MonoDevelop.PackageManagement\ProjectReloadedEventArgs.cs" />
<Compile Include="MonoDevelop.PackageManagement\OpenPackageReadmeMonitor.cs" />
<Compile Include="MonoDevelop.PackageManagement\IOpenPackageReadMeMonitor.cs" />
<Compile Include="MonoDevelop.PackageManagement\NullOpenPackageReadMeMonitor.cs" />
+ <Compile Include="MonoDevelop.PackageManagement\PackageManagementSolutionExtensions.cs" />
<Compile Include="MonoDevelop.PackageManagement\DotNetProjectReferenceEventArgs.cs" />
<Compile Include="MonoDevelop.PackageManagement\LocalCopyReferenceMaintainer.cs" />
<Compile Include="MonoDevelop.PackageManagement\DotNetSolutionEventArgs.cs" />
+ <Compile Include="MonoDevelop.PackageManagement\DotNetProjectImportEventArgs.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="MonoDevelop.PackageManagement.addin.xml" />
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/BackgroundPackageActionRunner.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/BackgroundPackageActionRunner.cs
index fbe1ad52f9..258e102084 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/BackgroundPackageActionRunner.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/BackgroundPackageActionRunner.cs
@@ -210,7 +210,7 @@ namespace MonoDevelop.PackageManagement
public void ShowError (ProgressMonitorStatusMessage progressMessage, Exception exception)
{
- LoggingService.LogInternalError (progressMessage.Status, exception);
+ LoggingService.LogError (progressMessage.Error, exception);
ShowError (progressMessage, exception.Message);
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/CheckForUpdatesProgressMonitor.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/CheckForUpdatesProgressMonitor.cs
deleted file mode 100644
index dbcb6fe501..0000000000
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/CheckForUpdatesProgressMonitor.cs
+++ /dev/null
@@ -1,104 +0,0 @@
-//
-// CheckForUpdatesProgressMonitor.cs
-//
-// Author:
-// Matt Ward <matt.ward@xamarin.com>
-//
-// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
-//
-// 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 ICSharpCode.PackageManagement;
-using MonoDevelop.Core;
-
-namespace MonoDevelop.PackageManagement
-{
- public class CheckForUpdatesProgressMonitor : IDisposable
- {
- ProgressMonitorStatusMessage progressMessage;
- IProgressMonitor progressMonitor;
- PackageUpdatesEventMonitor eventMonitor;
-
- public CheckForUpdatesProgressMonitor ()
- : this (
- PackageManagementServices.ProgressMonitorFactory,
- PackageManagementServices.PackageManagementEvents)
- {
- }
-
- public CheckForUpdatesProgressMonitor (
- IPackageManagementProgressMonitorFactory progressMonitorFactory,
- IPackageManagementEvents packageEvents)
- {
- progressMessage = ProgressMonitorStatusMessageFactory.CreateCheckingForPackageUpdatesMessage ();
- this.progressMonitor = progressMonitorFactory.CreateProgressMonitor (progressMessage.Status);
-
- eventMonitor = new PackageUpdatesEventMonitor (progressMonitor, packageEvents);
- }
-
- public void Dispose ()
- {
- eventMonitor.Dispose ();
- progressMonitor.Dispose ();
- }
-
- public void ReportError (Exception ex)
- {
- LoggingService.LogInternalError (ex);
- if (IsGuiDispatchException (ex)) {
- progressMonitor.Log.WriteLine (ex.InnerException.Message);
- } else if (ex is AggregateException) {
- LogAggregateException ((AggregateException)ex);
- } else {
- progressMonitor.Log.WriteLine (ex.Message);
- }
- progressMonitor.ReportError (progressMessage.Error, null);
- ShowPackageConsole ();
- }
-
- static bool IsGuiDispatchException (Exception ex)
- {
- return (ex.InnerException != null) &&
- (ex.Message == "An exception was thrown while dispatching a method call in the UI thread.");
- }
-
- void LogAggregateException (AggregateException ex)
- {
- progressMonitor.Log.WriteLine (new AggregateExceptionErrorMessage (ex));
- }
-
- protected virtual void ShowPackageConsole ()
- {
- progressMonitor.ShowPackageConsole ();
- }
-
- public void ReportSuccess (bool anyUpdates)
- {
- if (anyUpdates) {
- progressMonitor.ReportSuccess (GettextCatalog.GetString ("Package updates are available."));
- } else if (eventMonitor.WarningReported) {
- progressMonitor.ReportWarning (progressMessage.Warning);
- } else {
- progressMonitor.ReportSuccess (progressMessage.Success);
- }
- }
- }
-}
-
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/CheckForUpdatesTask.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/CheckForUpdatesTask.cs
index 45d7c73716..d59e6517f8 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/CheckForUpdatesTask.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/CheckForUpdatesTask.cs
@@ -65,7 +65,6 @@ namespace MonoDevelop.PackageManagement
public void CheckForUpdatesCompleted ()
{
- ProgressMonitor.ReportSuccess (projectsWithUpdatedPackages.Any ());
updatedPackagesInSolution.CheckForUpdatesCompleted (this);
}
@@ -73,23 +72,12 @@ namespace MonoDevelop.PackageManagement
get { return projectsWithUpdatedPackages; }
}
- public CheckForUpdatesProgressMonitor ProgressMonitor { get; set; }
-
public void Dispose ()
{
if (!disposed) {
disposed = true;
- if (ProgressMonitor != null) {
- ProgressMonitor.Dispose ();
- ProgressMonitor = null;
- }
}
}
-
- public void ReportError (Exception ex)
- {
- ProgressMonitor.ReportError (ex);
- }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/CheckForUpdatesTaskRunner.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/CheckForUpdatesTaskRunner.cs
index 0a01ea6163..c323d30246 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/CheckForUpdatesTaskRunner.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/CheckForUpdatesTaskRunner.cs
@@ -25,7 +25,6 @@
// THE SOFTWARE.
using System;
-using System.Collections.Generic;
using ICSharpCode.PackageManagement;
using MonoDevelop.Core;
using MonoDevelop.Ide;
@@ -35,26 +34,16 @@ namespace MonoDevelop.PackageManagement
public class CheckForUpdatesTaskRunner : IDisposable
{
ITaskFactory taskFactory;
- IPackageManagementProgressMonitorFactory progressMonitorFactory;
- IPackageManagementEvents packageManagementEvents;
CheckForUpdatesTask currentCheckForUpdatesTask;
ITask<CheckForUpdatesTask> task;
- public CheckForUpdatesTaskRunner (
- ITaskFactory taskFactory,
- IPackageManagementProgressMonitorFactory progressMonitorFactory,
- IPackageManagementEvents packageManagementEvents)
+ public CheckForUpdatesTaskRunner (ITaskFactory taskFactory)
{
this.taskFactory = taskFactory;
- this.progressMonitorFactory = progressMonitorFactory;
- this.packageManagementEvents = packageManagementEvents;
}
public CheckForUpdatesTaskRunner ()
- : this (
- new PackageManagementTaskFactory (),
- PackageManagementServices.ProgressMonitorFactory,
- PackageManagementServices.PackageManagementEvents)
+ : this (new PackageManagementTaskFactory ())
{
}
@@ -74,7 +63,6 @@ namespace MonoDevelop.PackageManagement
void CreateCheckForUpdatesTask (CheckForUpdatesTask checkForUpdatesTask)
{
currentCheckForUpdatesTask = checkForUpdatesTask;
- checkForUpdatesTask.ProgressMonitor = CreateProgressMonitor ();
task = taskFactory.CreateTask (
() => CheckForUpdates (checkForUpdatesTask),
@@ -108,9 +96,9 @@ namespace MonoDevelop.PackageManagement
{
if (task.IsFaulted) {
if (IsCurrentTask (task)) {
- ReportError (task.Exception);
+ LogError ("Current check for updates task error.", task.Exception);
} else {
- LoggingService.LogInternalError ("Check for updates task error.", task.Exception);
+ LogError ("Check for updates task error.", task.Exception);
}
} else if (task.IsCancelled) {
// Ignore.
@@ -134,13 +122,9 @@ namespace MonoDevelop.PackageManagement
return currentCheckForUpdatesTask == task;
}
- void ReportError (Exception ex)
+ protected virtual void LogError (string message, Exception ex)
{
- CheckForUpdatesTask task = currentCheckForUpdatesTask;
- task.ReportError (ex);
- GuiBackgroundDispatch (() => {
- task.Dispose ();
- });
+ LoggingService.LogError (message, ex);
}
bool IsCurrentTask (ITask<CheckForUpdatesTask> taskToCompare)
@@ -148,18 +132,6 @@ namespace MonoDevelop.PackageManagement
return taskToCompare == task;
}
- CheckForUpdatesProgressMonitor CreateProgressMonitor ()
- {
- return CreateProgressMonitor (progressMonitorFactory, packageManagementEvents);
- }
-
- protected virtual CheckForUpdatesProgressMonitor CreateProgressMonitor (
- IPackageManagementProgressMonitorFactory progressMonitorFactory,
- IPackageManagementEvents packageManagementEvents)
- {
- return new CheckForUpdatesProgressMonitor (progressMonitorFactory, packageManagementEvents);
- }
-
protected virtual void GuiBackgroundDispatch (MessageHandler handler)
{
DispatchService.BackgroundDispatch (handler);
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/DotNetProjectExtensions.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/DotNetProjectExtensions.cs
index 3d38c585c2..13c5aefb37 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/DotNetProjectExtensions.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/DotNetProjectExtensions.cs
@@ -27,11 +27,11 @@
//
using System;
+using System.Collections.Generic;
+using System.Linq;
using System.IO;
-using MonoDevelop.Core;
using MonoDevelop.PackageManagement;
using MonoDevelop.Projects;
-using MonoDevelop.Projects.Formats.MSBuild;
using NuGet;
namespace ICSharpCode.PackageManagement
@@ -40,7 +40,9 @@ namespace ICSharpCode.PackageManagement
{
public static readonly Guid WebApplication = Guid.Parse("{349C5851-65DF-11DA-9384-00065B846F21}");
public static readonly Guid WebSite = Guid.Parse("{E24C65DC-7377-472B-9ABA-BC803B73C61A}");
-
+
+ public static Func<string, bool> FileExists = File.Exists;
+
public static bool IsWebProject(this IDotNetProject project)
{
return project.HasProjectType(WebApplication) || project.HasProjectType(WebSite);
@@ -82,22 +84,62 @@ namespace ICSharpCode.PackageManagement
public static bool HasPackages (this DotNetProject project)
{
- return File.Exists (project.GetPackagesConfigFilePath ());
+ return HasPackages (project.BaseDirectory, project.Name);
}
public static string GetPackagesConfigFilePath (this DotNetProject project)
{
- return Path.Combine (project.BaseDirectory, Constants.PackageReferenceFile);
+ return GetPackagesConfigFilePath (project.BaseDirectory, project.Name);
}
public static bool HasPackages (this IDotNetProject project)
{
- return File.Exists (project.GetPackagesConfigFilePath ());
+ return AnyFileExists (GetPossiblePackagesConfigFilePaths (project.BaseDirectory, project.Name));
+ }
+
+ static bool HasPackages (string projectDirectory, string projectName)
+ {
+ return AnyFileExists (GetPossiblePackagesConfigFilePaths (projectDirectory, projectName));
+ }
+
+ static bool AnyFileExists (IEnumerable<string> files)
+ {
+ return files.Any (FileExists);
+ }
+
+ static IEnumerable<string> GetPossiblePackagesConfigFilePaths (string projectDirectory, string projectName)
+ {
+ yield return GetNonDefaultProjectPackagesConfigFilePath (projectDirectory, projectName);
+ yield return GetDefaultPackagesConfigFilePath (projectDirectory);
+ }
+
+ static string GetNonDefaultProjectPackagesConfigFilePath (string projectDirectory, string projectName)
+ {
+ return Path.Combine (projectDirectory, GetNonDefaultProjectPackagesConfigFileName (projectName));
+ }
+
+ static string GetNonDefaultProjectPackagesConfigFileName (string projectName)
+ {
+ return "packages." + projectName.Replace (' ', '_') + ".config";
+ }
+
+ static string GetDefaultPackagesConfigFilePath (string projectDirectory)
+ {
+ return Path.Combine (projectDirectory, Constants.PackageReferenceFile);
}
public static string GetPackagesConfigFilePath (this IDotNetProject project)
{
- return Path.Combine (project.BaseDirectory, Constants.PackageReferenceFile);
+ return GetPackagesConfigFilePath (project.BaseDirectory, project.Name);
+ }
+
+ static string GetPackagesConfigFilePath (string projectDirectory, string projectName)
+ {
+ string nonDefaultPackagesConfigFilePath = GetNonDefaultProjectPackagesConfigFilePath (projectDirectory, projectName);
+ if (FileExists (nonDefaultPackagesConfigFilePath)) {
+ return nonDefaultPackagesConfigFilePath;
+ }
+ return GetDefaultPackagesConfigFilePath (projectDirectory);
}
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableCheckForUpdatesProgressMonitor.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/DotNetProjectImportEventArgs.cs
index d35e6aefe5..cf0b696498 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableCheckForUpdatesProgressMonitor.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/DotNetProjectImportEventArgs.cs
@@ -1,10 +1,10 @@
//
-// TestableCheckForUpdatesProgressMonitor.cs
+// DotNetProjectImportEventArgs.cs
//
// Author:
// Matt Ward <matt.ward@xamarin.com>
//
-// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
+// Copyright (c) 2015 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -25,25 +25,19 @@
// THE SOFTWARE.
using System;
-using ICSharpCode.PackageManagement;
-namespace MonoDevelop.PackageManagement.Tests.Helpers
+namespace MonoDevelop.PackageManagement
{
- public class TestableCheckForUpdatesProgressMonitor : CheckForUpdatesProgressMonitor
+ public class DotNetProjectImportEventArgs : EventArgs
{
- public TestableCheckForUpdatesProgressMonitor (
- IPackageManagementProgressMonitorFactory progressMonitorFactory,
- IPackageManagementEvents packageEvents)
- : base (progressMonitorFactory, packageEvents)
+ public DotNetProjectImportEventArgs (IDotNetProject project, string import)
{
+ Project = project;
+ Import = import;
}
- public bool IsPackageConsoleShown;
-
- protected override void ShowPackageConsole ()
- {
- IsPackageConsoleShown = true;
- }
+ public IDotNetProject Project { get; private set; }
+ public string Import { get; private set; }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/FilePathExtensions.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/FilePathExtensions.cs
index 38faa5f7de..7c6cd512b7 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/FilePathExtensions.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/FilePathExtensions.cs
@@ -38,7 +38,14 @@ namespace MonoDevelop.PackageManagement
return false;
}
- return Constants.PackageReferenceFile.Equals (filePath.FileName, StringComparison.OrdinalIgnoreCase);
+ return Constants.PackageReferenceFile.Equals (filePath.FileName, StringComparison.OrdinalIgnoreCase) ||
+ IsProjectSpecificPackagesConfigFile (filePath.FileName);
+ }
+
+ static bool IsProjectSpecificPackagesConfigFile (FilePath filePath)
+ {
+ return filePath.Extension.Equals (".config", StringComparison.OrdinalIgnoreCase) &&
+ filePath.FileNameWithoutExtension.StartsWith ("packages.", StringComparison.OrdinalIgnoreCase);
}
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageManagementEvents.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageManagementEvents.cs
index 5b0bb4fb1f..c830df588d 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageManagementEvents.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/IPackageManagementEvents.cs
@@ -54,6 +54,7 @@ namespace ICSharpCode.PackageManagement
event EventHandler<PackageRestoredEventArgs> PackageRestored;
event EventHandler<DotNetProjectReferenceEventArgs> ReferenceAdding;
event EventHandler<DotNetProjectReferenceEventArgs> ReferenceRemoving;
+ event EventHandler<DotNetProjectImportEventArgs> ImportRemoved;
void OnPackageOperationsStarting();
void OnPackageOperationsFinished();
@@ -72,6 +73,7 @@ namespace ICSharpCode.PackageManagement
void OnPackageRestored (IPackage package);
void OnReferenceAdding (ProjectReference reference);
void OnReferenceRemoving (ProjectReference reference);
+ void OnImportRemoved (IDotNetProject project, string import);
[Obsolete]
void OnParentPackageInstalled (IPackage package, IPackageManagementProject project);
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageFromRepository.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageFromRepository.cs
index 56a5227376..f597c22480 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageFromRepository.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageFromRepository.cs
@@ -231,5 +231,10 @@ namespace ICSharpCode.PackageManagement
return true;
}
}
+
+ public void ExtractContents (IFileSystem fileSystem, string extractPath)
+ {
+ package.ExtractContents (fileSystem, extractPath);
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementEvents.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementEvents.cs
index f6462784f2..fa67203211 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementEvents.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementEvents.cs
@@ -209,5 +209,14 @@ namespace ICSharpCode.PackageManagement
ReferenceAdding (this, new DotNetProjectReferenceEventArgs (reference));
}
}
+
+ public event EventHandler<DotNetProjectImportEventArgs> ImportRemoved;
+
+ public void OnImportRemoved (IDotNetProject project, string import)
+ {
+ if (ImportRemoved != null) {
+ ImportRemoved (this, new DotNetProjectImportEventArgs (project, import));
+ }
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementEventsMonitor.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementEventsMonitor.cs
index 39df61d6e9..a6130d65f7 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementEventsMonitor.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementEventsMonitor.cs
@@ -45,6 +45,7 @@ namespace MonoDevelop.PackageManagement
string currentProgressOperation;
List<FileEventArgs> fileChangedEvents = new List<FileEventArgs> ();
List<IPackageManagementProject> projectsRequiringTypeSystemRefresh = new List<IPackageManagementProject> ();
+ ISolution solutionContainingProjectBuildersToDispose;
public PackageManagementEventsMonitor (
IProgressMonitor progressMonitor,
@@ -60,12 +61,14 @@ namespace MonoDevelop.PackageManagement
packageManagementEvents.AcceptLicenses += AcceptLicenses;
packageManagementEvents.FileChanged += FileChanged;
packageManagementEvents.ParentPackageInstalled += PackageInstalled;
+ packageManagementEvents.ImportRemoved += ImportRemoved;
progressProvider.ProgressAvailable += ProgressAvailable;
}
public void Dispose ()
{
progressProvider.ProgressAvailable -= ProgressAvailable;
+ packageManagementEvents.ImportRemoved -= ImportRemoved;
packageManagementEvents.ParentPackageInstalled -= PackageInstalled;
packageManagementEvents.FileChanged -= FileChanged;
packageManagementEvents.AcceptLicenses -= AcceptLicenses;
@@ -73,6 +76,7 @@ namespace MonoDevelop.PackageManagement
packageManagementEvents.PackageOperationMessageLogged -= PackageOperationMessageLogged;
NotifyFilesChanged ();
+ UnloadMSBuildHost ();
RefreshTypeSystem ();
}
@@ -188,7 +192,7 @@ namespace MonoDevelop.PackageManagement
public void ReportError (ProgressMonitorStatusMessage progressMessage, Exception ex)
{
- LoggingService.LogInternalError (ex);
+ LoggingService.LogError (progressMessage.Error, ex);
progressMonitor.Log.WriteLine (ex.Message);
progressMonitor.ReportError (progressMessage.Error, null);
ShowPackageConsole (progressMonitor);
@@ -232,6 +236,23 @@ namespace MonoDevelop.PackageManagement
return (operation.Action == PackageAction.Install) &&
operation.Package.GetBuildFiles ().Any ();
}
+
+ void ImportRemoved (object sender, DotNetProjectImportEventArgs e)
+ {
+ solutionContainingProjectBuildersToDispose = e.Project.ParentSolution;
+ }
+
+ void UnloadMSBuildHost ()
+ {
+ if (solutionContainingProjectBuildersToDispose == null)
+ return;
+
+ GuiSyncDispatch (() => {
+ foreach (IDotNetProject project in solutionContainingProjectBuildersToDispose.GetAllProjects ()) {
+ project.DisposeProjectBuilder ();
+ }
+ });
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementServices.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementServices.cs
index ccf2cb438c..f07f6e48b2 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementServices.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementServices.cs
@@ -100,7 +100,7 @@ namespace ICSharpCode.PackageManagement
try {
return Settings.LoadDefaultSettings (null, null, null);
} catch (Exception ex) {
- LoggingService.LogInternalError ("Unable to load NuGet.Config.", ex);
+ LoggingService.LogError ("Unable to load NuGet.Config.", ex);
}
return NullSettings.Instance;
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementSolutionExtensions.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementSolutionExtensions.cs
new file mode 100644
index 0000000000..4f9ef87876
--- /dev/null
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageManagementSolutionExtensions.cs
@@ -0,0 +1,43 @@
+//
+// PackageManagementSolutionExtensions.cs
+//
+// Author:
+// Matt Ward <matt.ward@xamarin.com>
+//
+// Copyright (c) 2015 Xamarin Inc. (http://xamarin.com)
+//
+// 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 MonoDevelop.PackageManagement;
+using MonoDevelop.Projects;
+
+namespace ICSharpCode.PackageManagement
+{
+ public static class PackageManagementSolutionExtensions
+ {
+ public static IPackageManagementProject GetProject (this IPackageManagementSolution solution, DotNetProject project)
+ {
+ var projectProxy = new DotNetProjectProxy (project);
+ var repository = PackageManagementServices.PackageRepositoryCache.CreateAggregateWithPriorityMachineCacheRepository ();
+ return solution.GetProject (repository, projectProxy);
+ }
+ }
+}
+
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageRestoreRunner.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageRestoreRunner.cs
index 2dd4d79a71..0b905a25cb 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageRestoreRunner.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageRestoreRunner.cs
@@ -82,7 +82,7 @@ namespace MonoDevelop.PackageManagement
try {
RestorePackages (progressMonitor, progressMessage);
} catch (Exception ex) {
- LoggingService.LogInternalError (ex);
+ LoggingService.LogError (progressMessage.Error, ex);
progressMonitor.Log.WriteLine (ex.Message);
progressMonitor.ReportError (progressMessage.Error, null);
progressMonitor.ShowPackageConsole ();
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageRestorer.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageRestorer.cs
index 912e981ecc..f13c9f3fb3 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageRestorer.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageRestorer.cs
@@ -77,7 +77,7 @@ namespace MonoDevelop.PackageManagement
RestoreWithProgressMonitor (progressMessage);
}
} catch (Exception ex) {
- LoggingService.LogInternalError (ex);
+ LoggingService.LogError ("Package restore failed", ex);
RestoreFailed = true;
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageUpdatesEventMonitor.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageUpdatesEventMonitor.cs
deleted file mode 100644
index cfb21f91da..0000000000
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageUpdatesEventMonitor.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-//
-// PackageUpdatesEventMonitor.cs
-//
-// Author:
-// Matt Ward <matt.ward@xamarin.com>
-//
-// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com)
-//
-// 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 ICSharpCode.PackageManagement;
-using MonoDevelop.Core;
-using NuGet;
-
-namespace MonoDevelop.PackageManagement
-{
- public class PackageUpdatesEventMonitor : IDisposable
- {
- IPackageManagementEvents packageEvents;
- IProgressMonitor progressMonitor;
-
- public PackageUpdatesEventMonitor (IProgressMonitor progressMonitor)
- : this (
- progressMonitor,
- PackageManagementServices.PackageManagementEvents)
- {
- }
-
- public PackageUpdatesEventMonitor (
- IProgressMonitor progressMonitor,
- IPackageManagementEvents packageEvents)
- {
- this.progressMonitor = progressMonitor;
- this.packageEvents = packageEvents;
-
- packageEvents.PackageOperationMessageLogged += PackageOperationMessageLogged;
- }
-
- void PackageOperationMessageLogged (object sender, PackageOperationMessageLoggedEventArgs e)
- {
- progressMonitor.Log.WriteLine (e.Message.ToString ());
-
- if (e.Message.Level == MessageLevel.Warning) {
- WarningReported = true;
- }
- }
-
- public void Dispose ()
- {
- packageEvents.PackageOperationMessageLogged -= PackageOperationMessageLogged;
- }
-
- public bool WarningReported { get; private set; }
- }
-}
-
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProcessPackageAction.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProcessPackageAction.cs
index fa01bc2a1a..e7ed10250a 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProcessPackageAction.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProcessPackageAction.cs
@@ -140,8 +140,8 @@ namespace ICSharpCode.PackageManagement
void ReportPowerShellScriptWarning ()
{
- string message = GettextCatalog.GetString ("{0} Package contains PowerShell scripts which will not be run.", GetPackageId ());
- packageManagementEvents.OnPackageOperationMessageLogged (MessageLevel.Warning, message);
+ string message = GettextCatalog.GetString ("WARNING: {0} Package contains PowerShell scripts which will not be run.", GetPackageId ());
+ packageManagementEvents.OnPackageOperationMessageLogged (MessageLevel.Info, message);
}
void CheckLicenses ()
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProcessPackageOperationsAction.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProcessPackageOperationsAction.cs
index cf75931581..6cb5f30fb4 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProcessPackageOperationsAction.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProcessPackageOperationsAction.cs
@@ -28,9 +28,7 @@
using System.Collections.Generic;
using System.Linq;
-using MonoDevelop.PackageManagement;
using NuGet;
-using MonoDevelop.PackageManagement;
namespace ICSharpCode.PackageManagement
{
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProgressMonitorStatusMessageFactory.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProgressMonitorStatusMessageFactory.cs
index 6bc99bf3f8..6c42dbef5f 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProgressMonitorStatusMessageFactory.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ProgressMonitorStatusMessageFactory.cs
@@ -213,15 +213,6 @@ namespace MonoDevelop.PackageManagement
);
}
- public static ProgressMonitorStatusMessage CreateCheckingForPackageUpdatesMessage ()
- {
- return new ProgressMonitorStatusMessage (
- GetString ("Checking for package updates..."),
- GetString ("Packages are up to date."),
- GetString ("Could not check for package updates."),
- GetString ("No updates found but warnings were reported."));
- }
-
static string GetString (string phrase)
{
return GettextCatalog.GetString (phrase);
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RegisteredPackageSourceSettings.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RegisteredPackageSourceSettings.cs
index 8369605e22..1986fcc729 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RegisteredPackageSourceSettings.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RegisteredPackageSourceSettings.cs
@@ -39,7 +39,9 @@ namespace ICSharpCode.PackageManagement
{
public class RegisteredPackageSourceSettings
{
+ public static readonly string PackageSourcesSectionName = "packageSources";
public static readonly string ActivePackageSourceSectionName = "activePackageSource";
+ public static readonly string DisabledPackageSourceSectionName = "disabledPackageSources";
public static readonly PackageSource AggregatePackageSource =
new PackageSource("(Aggregate source)", "All");
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SettingsProvider.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SettingsProvider.cs
index 2488c558da..7f89c7f8bb 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SettingsProvider.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SettingsProvider.cs
@@ -66,7 +66,7 @@ namespace MonoDevelop.PackageManagement
try {
return LoadSettings (GetSolutionDirectory ());
} catch (Exception ex) {
- LoggingService.LogInternalError ("Unable to load NuGet.Config file.", ex);
+ LoggingService.LogError ("Unable to load NuGet.Config file.", ex);
}
return NullSettings.Instance;
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SharpDevelopProjectSystem.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SharpDevelopProjectSystem.cs
index 87c1707789..4684a24b57 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SharpDevelopProjectSystem.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SharpDevelopProjectSystem.cs
@@ -426,9 +426,10 @@ namespace ICSharpCode.PackageManagement
using (var updater = new EnsureNuGetPackageBuildImportsTargetUpdater ()) {
updater.RemoveImport (relativeTargetPath);
- project.DisposeProjectBuilder ();
project.Save ();
}
+
+ packageManagementEvents.OnImportRemoved (project, relativeTargetPath);
});
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ThreadSafePackageManagementEvents.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ThreadSafePackageManagementEvents.cs
index 5fd0086856..d85e9f4457 100644
--- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ThreadSafePackageManagementEvents.cs
+++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ThreadSafePackageManagementEvents.cs
@@ -319,5 +319,15 @@ namespace ICSharpCode.PackageManagement
{
unsafeEvents.OnReferenceRemoving (reference);
}
+
+ public event EventHandler<DotNetProjectImportEventArgs> ImportRemoved {
+ add { unsafeEvents.ImportRemoved += value; }
+ remove { unsafeEvents.ImportRemoved -= value; }
+ }
+
+ public void OnImportRemoved (IDotNetProject project, string import)
+ {
+ unsafeEvents.OnImportRemoved (project, import);
+ }
}
}
diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/AnalysisCommands.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/AnalysisCommands.cs
index 392aacd522..4064ce9cb6 100644
--- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/AnalysisCommands.cs
+++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/AnalysisCommands.cs
@@ -44,6 +44,7 @@ using System.Threading;
using System.IO;
using MonoDevelop.Refactoring;
using MonoDevelop.Ide.Gui.Dialogs;
+using MonoDevelop.Components.Extensions;
namespace MonoDevelop.AnalysisCore
{
@@ -120,6 +121,8 @@ namespace MonoDevelop.AnalysisCore
((System.Action)dataItem) ();
return;
}
+ if (!RefactoringService.CheckUserSettings ())
+ return;
var action = dataItem as IAnalysisFixAction;
if (action != null) {
action.Fix ();
@@ -289,7 +292,7 @@ namespace MonoDevelop.AnalysisCore
{
var lang = "text/x-csharp";
- OpenFileDialog dlg = new OpenFileDialog ("Export Rules", FileChooserAction.Save);
+ OpenFileDialog dlg = new OpenFileDialog ("Export Rules", SelectFileDialogAction.Save);
dlg.InitialFileName = "rules.html";
if (!dlg.Run ())
return;
diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionEditorExtension.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionEditorExtension.cs
index 8cbdfbf6dc..fc93c8dc00 100644
--- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionEditorExtension.cs
+++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionEditorExtension.cs
@@ -429,6 +429,8 @@ namespace MonoDevelop.CodeActions
void PopulateFixes (FixMenuDescriptor menu, ref int items)
{
+ if (!RefactoringService.ShowFixes)
+ return;
int mnemonic = 1;
bool gotImportantFix = false, addedSeparator = false;
var fixesAdded = new List<string> ();
diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.Rename/RenameItemDialog.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.Rename/RenameItemDialog.cs
index e4498221a7..69852183a5 100644
--- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.Rename/RenameItemDialog.cs
+++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.Rename/RenameItemDialog.cs
@@ -140,6 +140,7 @@ namespace MonoDevelop.Refactoring.Rename
buttonPreview.Clicked += OnPreviewClicked;
entry.Changed += delegate { buttonPreview.Sensitive = buttonOk.Sensitive = ValidateName (); };
ValidateName ();
+ this.hbox1.HideAll ();
}
bool ValidateName ()
diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.addin.xml b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.addin.xml
index 8151d80966..ed0ba0695c 100644
--- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.addin.xml
+++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.addin.xml
@@ -95,7 +95,7 @@
defaultHandler = "MonoDevelop.Refactoring.ResolveCommandHandler"
type="array"
_label = "Resolve"/>
-
+
<Command id = "MonoDevelop.Refactoring.RefactoryCommands.CurrentRefactoryOperations"
defaultHandler = "MonoDevelop.Refactoring.CurrentRefactoryOperationsHandler"
type="array"
@@ -182,7 +182,7 @@
func="MonoDevelop.AnalysisCore.Rules.NamingConventions.ClassNaming" />-->
</Category>
</Extension>
-
+
<Extension path = "/MonoDevelop/AnalysisCore/FixHandlers">
<Handler fixName="RenameMember" class = "MonoDevelop.AnalysisCore.Fixes.RenameMemberHandler" />
<Handler fixName="Generic" class = "MonoDevelop.AnalysisCore.Fixes.GenericFixHandler" />
diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.csproj b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.csproj
index d47fae2ad7..6fe3d47b41 100644
--- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.csproj
+++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.csproj
@@ -42,6 +42,7 @@
<NoWarn>1591;1573</NoWarn>
<DebugSymbols>true</DebugSymbols>
<DocumentationFile>..\..\..\build\AddIns\MonoDevelop.Refactoring\MonoDevelop.Refactoring.xml</DocumentationFile>
+ <DebugType>full</DebugType>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseMac|AnyCPU' ">
<Optimize>true</Optimize>
diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringService.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringService.cs
index 64096e8329..9e18efff67 100644
--- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringService.cs
+++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringService.cs
@@ -42,6 +42,7 @@ using Mono.TextEditor;
using MonoDevelop.Ide.TypeSystem;
using System.Diagnostics;
using MonoDevelop.Core.Instrumentation;
+using MonoDevelop.Ide;
namespace MonoDevelop.Refactoring
{
@@ -293,10 +294,53 @@ namespace MonoDevelop.Refactoring
return RunAll (allFixes, refactoringContext, script);
}
}
-
+
+ const string EnableRefactorings = "RefactoringSettings.EnableRefactorings";
+
+ internal static bool CheckUserSettings()
+ {
+ var hasRefactoringSettings = IdeApp.ProjectOperations.CurrentSelectedSolution == null ||
+ IdeApp.ProjectOperations.CurrentSelectedSolution.UserProperties.HasValue (EnableRefactorings);
+ if (!hasRefactoringSettings) {
+ var useRefactoringsButton = new AlertButton (GettextCatalog.GetString("Use refactorings on this solution"));
+ var text = GettextCatalog.GetString (
+@"WARNING: The Xamarin Studio refactoring operations do not yet support C# 6.
+
+You may continue to use refactoring operations with C# 6, however you should check the results carefully to make sure that they have not made incorrect changes to your code. In particular, the ""?."" null propagating dereference will be changed to ""."", a simple dereference, which can cause unexpected NullReferenceExceptions at runtime.");
+ var message = new QuestionMessage (text);
+ message.Buttons.Add (useRefactoringsButton);
+ message.Buttons.Add (AlertButton.Cancel);
+ message.Icon = Gtk.Stock.DialogWarning;
+ message.DefaultButton = 1;
+
+ var result = MessageService.AskQuestion (message);
+ if (result == AlertButton.Cancel)
+ return false;
+ ShowFixes = result == useRefactoringsButton;
+ }
+ return ShowFixes;
+ }
+
+ internal static bool ShowFixes {
+ get {
+ if (Ide.IdeApp.ProjectOperations.CurrentSelectedSolution != null) {
+ var hasRefactoringSettings = IdeApp.ProjectOperations.CurrentSelectedSolution.UserProperties.HasValue (EnableRefactorings);
+ return !hasRefactoringSettings || IdeApp.ProjectOperations.CurrentSelectedSolution.UserProperties.GetValue<bool> (EnableRefactorings);
+ }
+ return true;
+ }
+ set {
+ IdeApp.ProjectOperations.CurrentSelectedSolution.UserProperties.SetValue (EnableRefactorings, value);
+ IdeApp.ProjectOperations.CurrentSelectedSolution.SaveUserProperties ();
+ }
+ }
+
+
public static void ApplyFix (CodeAction action, IRefactoringContext context)
{
- using(var script = context.CreateScript ()) {
+ if (!CheckUserSettings ())
+ return;
+ using (var script = context.CreateScript ()) {
action.Run (context, script);
}
}
diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoryCommands.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoryCommands.cs
index 1dd79118c7..d89a7c4081 100644
--- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoryCommands.cs
+++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoryCommands.cs
@@ -269,49 +269,49 @@ namespace MonoDevelop.Refactoring
}));
added = true;
}
-
- foreach (var refactoring in RefactoringService.Refactorings) {
- if (refactoring.IsValid (options)) {
- CommandInfo info = new CommandInfo (refactoring.GetMenuDescription (options));
- info.AccelKey = refactoring.AccelKey;
- ciset.CommandInfos.Add (info, new Action (new RefactoringOperationWrapper (refactoring, options).Operation));
+ if (RefactoringService.ShowFixes) {
+ foreach (var refactoring in RefactoringService.Refactorings) {
+ if (refactoring.IsValid (options)) {
+ CommandInfo info = new CommandInfo (refactoring.GetMenuDescription (options));
+ info.AccelKey = refactoring.AccelKey;
+ ciset.CommandInfos.Add (info, new Action (new RefactoringOperationWrapper (refactoring, options).Operation));
+ }
}
- }
- var refactoringInfo = doc.Annotation<RefactoringDocumentInfo> ();
- if (refactoringInfo == null) {
- refactoringInfo = new RefactoringDocumentInfo ();
- doc.AddAnnotation (refactoringInfo);
- }
- var loc = doc.Editor.Caret.Location;
- bool first = true;
- if (refactoringInfo.lastDocument != doc.ParsedDocument || loc != lastLocation) {
- try {
- refactoringInfo.validActions = RefactoringService.GetValidActions (doc, loc, new CancellationTokenSource (500).Token);
- } catch (TaskCanceledException) {
- } catch (AggregateException ae) {
- ae.Flatten ().Handle (x => x is TaskCanceledException);
+ var refactoringInfo = doc.Annotation<RefactoringDocumentInfo> ();
+ if (refactoringInfo == null) {
+ refactoringInfo = new RefactoringDocumentInfo ();
+ doc.AddAnnotation (refactoringInfo);
}
+ var loc = doc.Editor.Caret.Location;
+ bool first = true;
+ if (refactoringInfo.lastDocument != doc.ParsedDocument || loc != lastLocation) {
+ try {
+ refactoringInfo.validActions = RefactoringService.GetValidActions (doc, loc, new CancellationTokenSource (500).Token);
+ } catch (TaskCanceledException) {
+ } catch (AggregateException ae) {
+ ae.Flatten ().Handle (x => x is TaskCanceledException);
+ }
- lastLocation = loc;
- refactoringInfo.lastDocument = doc.ParsedDocument;
- }
- if (refactoringInfo.validActions != null && refactoringInfo.lastDocument != null && refactoringInfo.lastDocument.CreateRefactoringContext != null) {
- var context = refactoringInfo.lastDocument.CreateRefactoringContext (doc, CancellationToken.None);
+ lastLocation = loc;
+ refactoringInfo.lastDocument = doc.ParsedDocument;
+ }
+ if (refactoringInfo.validActions != null && refactoringInfo.lastDocument != null && refactoringInfo.lastDocument.CreateRefactoringContext != null) {
+ var context = refactoringInfo.lastDocument.CreateRefactoringContext (doc, CancellationToken.None);
- foreach (var fix_ in refactoringInfo.validActions.OrderByDescending (i => Tuple.Create (CodeActionEditorExtension.IsAnalysisOrErrorFix(i), (int)i.Severity, CodeActionEditorExtension.GetUsage (i.IdString)))) {
- if (CodeActionEditorExtension.IsAnalysisOrErrorFix (fix_))
- continue;
- var fix = fix_;
- if (first) {
- first = false;
- if (ciset.CommandInfos.Count > 0)
- ciset.CommandInfos.AddSeparator ();
- }
+ foreach (var fix_ in refactoringInfo.validActions.OrderByDescending (i => Tuple.Create (CodeActionEditorExtension.IsAnalysisOrErrorFix(i), (int)i.Severity, CodeActionEditorExtension.GetUsage (i.IdString)))) {
+ if (CodeActionEditorExtension.IsAnalysisOrErrorFix (fix_))
+ continue;
+ var fix = fix_;
+ if (first) {
+ first = false;
+ if (ciset.CommandInfos.Count > 0)
+ ciset.CommandInfos.AddSeparator ();
+ }
- ciset.CommandInfos.Add (fix.Title, new Action (() => RefactoringService.ApplyFix (fix, context)));
+ ciset.CommandInfos.Add (fix.Title, new Action (() => RefactoringService.ApplyFix (fix, context)));
+ }
}
}
-
if (ciset.CommandInfos.Count > 0) {
ainfo.Add (ciset, null);
added = true;
diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.OptionPanels/HighlightingPanel.cs b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.OptionPanels/HighlightingPanel.cs
index 621ced902e..f6fbed6ace 100644
--- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.OptionPanels/HighlightingPanel.cs
+++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.OptionPanels/HighlightingPanel.cs
@@ -32,20 +32,31 @@ using MonoDevelop.Components;
using MonoDevelop.Core;
using MonoDevelop.Ide;
using MonoDevelop.Ide.Gui.Dialogs;
+using MonoDevelop.Components.Extensions;
namespace MonoDevelop.SourceEditor.OptionPanels
{
public partial class HighlightingPanel : Gtk.Bin, IOptionsPanel
{
string schemeName;
+ ListStore styleStore = new ListStore (typeof (string), typeof (Mono.TextEditor.Highlighting.ColorScheme), typeof(bool));
+ Lazy<Gdk.Pixbuf> errorPixbuf = new Lazy<Gdk.Pixbuf> (() => ImageService.GetIcon (Stock.DialogError, IconSize.Menu).ToPixbuf ());
-
- ListStore styleStore = new ListStore (typeof (string), typeof (Mono.TextEditor.Highlighting.ColorScheme));
-
public HighlightingPanel ()
{
this.Build ();
- styleTreeview.AppendColumn ("", new CellRendererText (), "markup", 0);
+ var col = new TreeViewColumn ();
+ var crpixbuf = new CellRendererPixbuf ();
+ col.PackStart (crpixbuf, false);
+ col.SetCellDataFunc (crpixbuf, (TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter) => {
+ var isError = (bool)styleStore.GetValue (iter, 2);
+ crpixbuf.Visible = isError;
+ crpixbuf.Pixbuf = isError ? errorPixbuf.Value : null;
+ });
+ var crtext = new CellRendererText ();
+ col.PackEnd (crtext, true);
+ col.SetAttributes (crtext, "markup", 0);
+ styleTreeview.AppendColumn (col);
styleTreeview.Model = styleStore;
// ensure that custom styles are loaded.
new SourceEditorDisplayBinding ();
@@ -101,7 +112,11 @@ namespace MonoDevelop.SourceEditor.OptionPanels
var sheme = (Mono.TextEditor.Highlighting.ColorScheme)styleStore.GetValue (iter, 1);
if (sheme == null)
return;
-
+ var isError = (bool)styleStore.GetValue (iter, 2);
+ if (isError) {
+ this.removeButton.Sensitive = true;
+ return;
+ }
DefaultSourceEditorOptions.Instance.ColorScheme = sheme.Name;
this.buttonExport.Sensitive = true;
string fileName = sheme.FileName;
@@ -118,19 +133,24 @@ namespace MonoDevelop.SourceEditor.OptionPanels
using (var editor = new ColorShemeEditor (this)) {
var colorScheme = (Mono.TextEditor.Highlighting.ColorScheme)this.styleStore.GetValue (selectedIter, 1);
editor.SetSheme (colorScheme);
- MessageService.ShowCustomDialog (editor, dialog);
+ MessageService. ShowCustomDialog (editor, dialog);
}
}
}
- Mono.TextEditor.Highlighting.ColorScheme LoadStyle (string styleName, bool showException = true)
+ Mono.TextEditor.Highlighting.ColorScheme LoadStyle (string styleName, out bool error)
{
try {
+ error = false;
return Mono.TextEditor.Highlighting.SyntaxModeService.GetColorStyle (styleName);
} catch (Exception e) {
- if (showException)
- MessageService.ShowError ("Error while importing color style " + styleName, (e.InnerException ?? e).Message);
- return Mono.TextEditor.Highlighting.SyntaxModeService.DefaultColorStyle;
+ LoggingService.LogError ("Error while loading color style " + styleName, e);
+ error = true;
+ var style = Mono.TextEditor.Highlighting.SyntaxModeService.DefaultColorStyle.Clone ();
+ style.Name = styleName;
+ style.Description = GettextCatalog.GetString ("Loading error:" + e.Message);
+ style.FileName = Mono.TextEditor.Highlighting.SyntaxModeService.GetFileName (styleName);
+ return style;
}
}
@@ -138,11 +158,12 @@ namespace MonoDevelop.SourceEditor.OptionPanels
internal void ShowStyles ()
{
styleStore.Clear ();
- TreeIter selectedIter = styleStore.AppendValues (GetMarkup (GettextCatalog.GetString ("Default"), GettextCatalog.GetString ("The default color scheme.")), LoadStyle ("Default"));
+ bool error;
+ TreeIter selectedIter = styleStore.AppendValues (GetMarkup (GettextCatalog.GetString ("Default"), GettextCatalog.GetString ("The default color scheme.")), LoadStyle ("Default", out error));
foreach (string styleName in Mono.TextEditor.Highlighting.SyntaxModeService.Styles) {
if (styleName == "Default")
continue;
- var style = LoadStyle (styleName);
+ var style = LoadStyle (styleName, out error);
string name = style.Name ?? "";
string description = style.Description ?? "";
// translate only build-in sheme names
@@ -154,7 +175,7 @@ namespace MonoDevelop.SourceEditor.OptionPanels
} catch {
}
}
- TreeIter iter = styleStore.AppendValues (GetMarkup (name, description), style);
+ TreeIter iter = styleStore.AppendValues (GetMarkup (name, description), style, error);
if (style.Name == DefaultSourceEditorOptions.Instance.ColorScheme)
selectedIter = iter;
}
@@ -179,7 +200,7 @@ namespace MonoDevelop.SourceEditor.OptionPanels
void HandleButtonExportClicked (object sender, EventArgs e)
{
- var dialog = new SelectFileDialog (GettextCatalog.GetString ("Highlighting Scheme"), Gtk.FileChooserAction.Save) {
+ var dialog = new SelectFileDialog (GettextCatalog.GetString ("Highlighting Scheme"), SelectFileDialogAction.Save) {
TransientFor = this.Toplevel as Gtk.Window,
};
dialog.AddFilter (GettextCatalog.GetString ("Color schemes"), "*.json");
@@ -198,7 +219,7 @@ namespace MonoDevelop.SourceEditor.OptionPanels
void AddColorScheme (object sender, EventArgs args)
{
- var dialog = new SelectFileDialog (GettextCatalog.GetString ("Highlighting Scheme"), Gtk.FileChooserAction.Open) {
+ var dialog = new SelectFileDialog (GettextCatalog.GetString ("Highlighting Scheme"), SelectFileDialogAction.Open) {
TransientFor = this.Toplevel as Gtk.Window,
};
dialog.AddFilter (GettextCatalog.GetString ("Color schemes"), "*.json");
diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.csproj b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.csproj
index 6030f79e7e..9c6b608723 100644
--- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.csproj
+++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.csproj
@@ -44,7 +44,7 @@
</Execution>
<DebugSymbols>true</DebugSymbols>
<NoWarn>1591;1573</NoWarn>
- <DocumentationFile>..\..\..\build\AddIns\DisplayBindings\SourceEditor\MonoDevelop.SourceEditor.xml</DocumentationFile>
+ <DocumentationFile>..\..\..\build\AddIns\DisplayBindings\SourceEditor\MonoDevelop.SourceEditor2.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\core\MonoDevelop.Core\MonoDevelop.Core.csproj">
diff --git a/main/src/addins/MonoDevelop.SourceEditor2/gtk-gui/gui.stetic b/main/src/addins/MonoDevelop.SourceEditor2/gtk-gui/gui.stetic
index 1f2e5837de..9ef97fcf7d 100644
--- a/main/src/addins/MonoDevelop.SourceEditor2/gtk-gui/gui.stetic
+++ b/main/src/addins/MonoDevelop.SourceEditor2/gtk-gui/gui.stetic
@@ -7,7 +7,6 @@
<import>
<widget-library name="../../../../build/bin/MonoDevelop.Ide.dll" />
<widget-library name="../../../../build/AddIns/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.dll" />
- <widget-library name="../../../../build/AddIns/MonoDevelop.Debugger/MonoDevelop.Debugger.dll" />
<widget-library name="../../../../build/bin/Mono.TextEditor.dll" />
<widget-library name="../../../../build/AddIns/DisplayBindings/SourceEditor/MonoDevelop.SourceEditor2.dll" internal="true" />
</import>
diff --git a/main/src/addins/MonoDeveloperExtensions/NUnit/NUnit.csproj b/main/src/addins/MonoDeveloperExtensions/NUnit/NUnit.csproj
index 0303e2ded5..2074526569 100644
--- a/main/src/addins/MonoDeveloperExtensions/NUnit/NUnit.csproj
+++ b/main/src/addins/MonoDeveloperExtensions/NUnit/NUnit.csproj
@@ -9,6 +9,7 @@
<OutputType>Library</OutputType>
<RootNamespace>NUnit</RootNamespace>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <AssemblyName>MonoDeveloperExtensions_nunit</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>True</DebugSymbols>
@@ -21,7 +22,6 @@
<Execution>
<Execution clr-version="Net_2_0" />
</Execution>
- <AssemblyName>MonoDeveloperExtensions_nunit</AssemblyName>
<DefineConstants>DEBUG</DefineConstants>
<NoWarn>1591;1573</NoWarn>
<DocumentationFile>..\..\..\..\build\AddIns\MonoDeveloperExtensions\MonoDeveloperExtensions_nunit.xml</DocumentationFile>
@@ -36,10 +36,9 @@
<Execution>
<Execution clr-version="Net_2_0" />
</Execution>
- <AssemblyName>NUnit</AssemblyName>
<DebugSymbols>true</DebugSymbols>
<NoWarn>1591;1573</NoWarn>
- <DocumentationFile>..\..\..\..\build\AddIns\MonoDeveloperExtensions\NUnit.xml</DocumentationFile>
+ <DocumentationFile>..\..\..\..\build\AddIns\MonoDeveloperExtensions\MonoDeveloperExtensions_nunit.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\MonoDeveloperExtensions.csproj">
diff --git a/main/src/addins/NUnit/Commands/NUnitCommands.cs b/main/src/addins/NUnit/Commands/NUnitCommands.cs
index f0d9322df4..0a581fdb81 100644
--- a/main/src/addins/NUnit/Commands/NUnitCommands.cs
+++ b/main/src/addins/NUnit/Commands/NUnitCommands.cs
@@ -41,7 +41,8 @@ namespace MonoDevelop.NUnit.Commands
ShowTestCode,
SelectTestInTree,
ShowTestDetails,
- GoToFailure
+ GoToFailure,
+ RerunTest,
}
public enum TestChartCommands
diff --git a/main/src/addins/NUnit/Gui/TestResultsPad.cs b/main/src/addins/NUnit/Gui/TestResultsPad.cs
index 638ed50d5f..5110f4de4d 100644
--- a/main/src/addins/NUnit/Gui/TestResultsPad.cs
+++ b/main/src/addins/NUnit/Gui/TestResultsPad.cs
@@ -105,6 +105,7 @@ namespace MonoDevelop.NUnit
public TestResultsPad ()
{
testService.TestSuiteChanged += new EventHandler (OnTestSuiteChanged);
+ IdeApp.Workspace.WorkspaceItemClosed += OnWorkspaceItemClosed;
panel = new VBox ();
@@ -212,7 +213,7 @@ namespace MonoDevelop.NUnit
buttonRun = new Button ();
buttonRun.Label = GettextCatalog.GetString ("Rerun Tests");
- buttonRun.Image = new Gtk.Image (Gtk.Stock.Execute, IconSize.Menu);
+ buttonRun.Image = new ImageView (ImageService.GetIcon ("nunit-run", IconSize.Menu));
buttonRun.Image.Show ();
buttonRun.Sensitive = false;
toolbar.Add (buttonRun);
@@ -249,6 +250,8 @@ namespace MonoDevelop.NUnit
progressBar.HeightRequest = infoLabel.SizeRequest ().Height;
runPanel.ShowAll ();
+ progressBar.Hide ();
+ infoSep.Hide ();
resultSummary = new UnitTestResult ();
UpdateCounters ();
}
@@ -259,14 +262,28 @@ namespace MonoDevelop.NUnit
public void OnTestSuiteChanged (object sender, EventArgs e)
{
+ if (rootTest != null) {
+ rootTest = testService.SearchTest (rootTest.FullName);
+ if (rootTest == null)
+ buttonRun.Sensitive = false;
+ }
+ }
+
+ void OnWorkspaceItemClosed (object sender, EventArgs e)
+ {
+ ClearResults ();
+ }
+
+ void ClearResults ()
+ {
if (failuresTreeView.IsRealized)
failuresTreeView.ScrollToPoint (0, 0);
results.Clear ();
-
+
error = null;
errorMessage = null;
-
+
failuresStore.Clear ();
outputView.Buffer.Clear ();
outIters.Clear ();
@@ -274,12 +291,10 @@ namespace MonoDevelop.NUnit
progressBar.Text = "";
testsRun = 0;
resultSummary = new UnitTestResult ();
+ resultLabel.Markup = "";
+ resultLabel.Hide ();
+ labels.Show ();
UpdateCounters ();
- if (rootTest != null) {
- rootTest = testService.SearchTest (rootTest.FullName);
- if (rootTest == null)
- buttonRun.Sensitive = false;
- }
}
bool Running {
@@ -501,7 +516,7 @@ namespace MonoDevelop.NUnit
Gtk.TreeIter iter;
if (!failuresTreeView.Selection.GetSelected (out foo, out iter))
return;
-
+
int type = (int)failuresStore.GetValue (iter, 5);
var clipboard = Clipboard.Get (Gdk.Atom.Intern ("CLIPBOARD", false));
@@ -524,9 +539,23 @@ namespace MonoDevelop.NUnit
{
UnitTest test = GetSelectedTest ();
if (test != null) {
- var result = test.GetLastResult ();
- if (result != null) {
- info.Enabled = !string.IsNullOrEmpty (result.StackTrace);
+ var last = test.GetLastResult ();
+
+ Gtk.TreeModel foo;
+ Gtk.TreeIter iter;
+ if (!failuresTreeView.Selection.GetSelected (out foo, out iter)) {
+ info.Enabled = false;
+ return;
+ }
+
+ int type = (int)failuresStore.GetValue (iter, 5);
+ switch (type) {
+ case ErrorMessage:
+ info.Enabled = !string.IsNullOrEmpty (last.Message);
+ return;
+ case StackTrace:
+ default:
+ info.Enabled = !string.IsNullOrEmpty (last.StackTrace);
return;
}
}
@@ -575,9 +604,19 @@ namespace MonoDevelop.NUnit
if (loc != null)
IdeApp.Workbench.OpenDocument (loc.FileName, loc.Line, loc.Column);
}
+
+ [CommandHandler (TestCommands.RerunTest)]
+ protected void OnRerunTest ()
+ {
+ UnitTest test = GetSelectedTest ();
+ if (test == null)
+ return;
+ NUnitService.Instance.RunTest (test, null);
+ }
[CommandUpdateHandler (TestCommands.ShowTestCode)]
[CommandUpdateHandler (TestCommands.GoToFailure)]
+ [CommandUpdateHandler (TestCommands.RerunTest)]
protected void OnUpdateRunTest (CommandInfo info)
{
UnitTest test = GetSelectedTest ();
diff --git a/main/src/addins/NUnit/MonoDevelop.NUnit.csproj b/main/src/addins/NUnit/MonoDevelop.NUnit.csproj
index 65cda081fd..40f784226e 100644
--- a/main/src/addins/NUnit/MonoDevelop.NUnit.csproj
+++ b/main/src/addins/NUnit/MonoDevelop.NUnit.csproj
@@ -30,7 +30,7 @@
<Optimize>True</Optimize>
<OutputPath>..\..\..\build\AddIns\NUnit\</OutputPath>
<ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
+ <WarningLevel>3</WarningLevel>
<Execution>
<Execution clr-version="Net_2_0" />
</Execution>
diff --git a/main/src/addins/NUnit/MonoDevelopNUnit.addin.xml b/main/src/addins/NUnit/MonoDevelopNUnit.addin.xml
index 96f4fb6295..25aef50656 100644
--- a/main/src/addins/NUnit/MonoDevelopNUnit.addin.xml
+++ b/main/src/addins/NUnit/MonoDevelopNUnit.addin.xml
@@ -91,6 +91,7 @@
<Command id = "MonoDevelop.NUnit.Commands.TestCommands.GoToFailure" _label = "Go to failure" />
<Command id = "MonoDevelop.NUnit.Commands.TestCommands.SelectTestInTree" _label = "Select test in tree" />
<Command id = "MonoDevelop.NUnit.Commands.TestCommands.ShowTestDetails" _label = "Show results pad" />
+ <Command id = "MonoDevelop.NUnit.Commands.TestCommands.RerunTest" _label = "Rerun test" />
<Command id = "MonoDevelop.NUnit.Commands.TestChartCommands.UseTimeScale" _label = "Proportional time scale" type="check"/>
<Command id = "MonoDevelop.NUnit.Commands.TestChartCommands.SingleDayResult" _label = "Show one result per day" type="check"/>
<Command id = "MonoDevelop.NUnit.Commands.TestChartCommands.ShowResults" _label = "Results chart" type="radio"/>
@@ -136,6 +137,7 @@
<CommandItem id = "MonoDevelop.NUnit.Commands.TestCommands.GoToFailure" />
<CommandItem id = "MonoDevelop.NUnit.Commands.TestCommands.ShowTestCode" />
<CommandItem id = "MonoDevelop.NUnit.Commands.TestCommands.SelectTestInTree" />
+ <CommandItem id = "MonoDevelop.NUnit.Commands.TestCommands.RerunTest" />
<SeparatorItem id = "s1" />
<CommandItem id = "MonoDevelop.Ide.Commands.EditCommands.Copy" />
</Extension>
diff --git a/main/src/addins/TextTemplating/TextTransform/TextTransform.csproj b/main/src/addins/TextTemplating/TextTransform/TextTransform.csproj
index 69822959b6..5cc987754f 100644
--- a/main/src/addins/TextTemplating/TextTransform/TextTransform.csproj
+++ b/main/src/addins/TextTemplating/TextTransform/TextTransform.csproj
@@ -32,6 +32,7 @@
<DebugSymbols>true</DebugSymbols>
<NoWarn>1591;1573</NoWarn>
<DocumentationFile>..\..\..\..\build\AddIns\MonoDevelop.TextTemplating\TextTransform.xml</DocumentationFile>
+ <Commandlineparameters>-o:out.txt in.tt</Commandlineparameters>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
diff --git a/main/src/addins/VBNetBinding/VBNetBinding.csproj b/main/src/addins/VBNetBinding/VBNetBinding.csproj
index d730d2a3f5..8fb1dca2f8 100644
--- a/main/src/addins/VBNetBinding/VBNetBinding.csproj
+++ b/main/src/addins/VBNetBinding/VBNetBinding.csproj
@@ -30,7 +30,7 @@
<Optimize>True</Optimize>
<OutputPath>..\..\..\build\AddIns\BackendBindings\</OutputPath>
<ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
+ <WarningLevel>3</WarningLevel>
<Execution>
<Execution clr-version="Net_2_0" />
</Execution>
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseGitRepositoryTests.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseGitRepositoryTests.cs
index a3d92cdaf7..e1767c556a 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseGitRepositoryTests.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseGitRepositoryTests.cs
@@ -392,6 +392,11 @@ index 0000000..009b64b
return new GitRepository (VersionControlService.GetVersionControlSystems ().First (id => id.Name == "Git"), path, url);
}
+ protected override Repository GetRepo ()
+ {
+ return new GitRepository ();
+ }
+
// This test is for a memory usage improvement on status.
[Test]
public void TestSameGitRevision ()
@@ -497,5 +502,34 @@ index 0000000..009b64b
foreach (var rev in revisions)
Assert.AreEqual (GettextCatalog.GetString ("working copy"), rev);
}
+
+ [Test]
+ public void TestGitRebaseCommitOrdering ()
+ {
+ var gitRepo = (GitRepository)Repo;
+
+ AddFile ("init", "init", toVcs: true, commit: true);
+
+ // Create a branch from initial commit.
+ gitRepo.CreateBranch ("test", null, null);
+
+ // Create two commits in master.
+ AddFile ("init2", "init", toVcs: true, commit: true);
+ AddFile ("init3", "init", toVcs: true, commit: true);
+
+ // Create two commits in test.
+ gitRepo.SwitchToBranch (new NullProgressMonitor (), "test");
+ AddFile ("init4", "init", toVcs: true, commit: true);
+ AddFile ("init5", "init", toVcs: true, commit: true);
+
+ gitRepo.Rebase ("master", GitUpdateOptions.None, new NullProgressMonitor ());
+
+ // Commits come in reverse (recent to old).
+ var history = gitRepo.GetHistory (LocalPath, null).Reverse ().ToArray ();
+ Assert.AreEqual (5, history.Length);
+ for (int i = 0; i < 5; ++i) {
+ Assert.AreEqual (string.Format ("Commit #{0}\n", i), history [i].Message);
+ }
+ }
}
}
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseRepositoryTests.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseRepositoryTests.cs
index bf8a61fa1c..46b64db071 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseRepositoryTests.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/BaseRepositoryTests.cs
@@ -654,8 +654,11 @@ namespace MonoDevelop.VersionControl.Tests
protected void Checkout (string path, string url)
{
- Repository _repo = GetRepo (path, url);
- _repo.Checkout (path, true, new NullProgressMonitor ());
+ var mockRepo = (UrlBasedRepository)GetRepo ();
+ mockRepo.Url = url;
+ mockRepo.Checkout (path, true, new NullProgressMonitor ());
+
+ var _repo = GetRepo (path, url);
if (Repo == null)
Repo = _repo;
else
@@ -714,6 +717,7 @@ namespace MonoDevelop.VersionControl.Tests
AddedItems.Add (added);
}
+ protected abstract Repository GetRepo ();
protected abstract Repository GetRepo (string path, string url);
protected static void DeleteDirectory (string path)
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/GitIntegrityTests.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/GitIntegrityTests.cs
index 491a8ff3df..99288e1474 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/GitIntegrityTests.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/GitIntegrityTests.cs
@@ -24,7 +24,7 @@
// 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;
using System.Linq;
using NUnit.Framework;
using System.IO;
@@ -54,7 +54,6 @@ namespace MonoDevelop.VersionControl.Git.Tests
}
[Test]
- [Ignore ("This fails with NGit, probably because the diff algorithm is different")]
public void TestBlameRevisionsWithMultipleCommits ()
{
Commit[] blameCommits = GetBlameForFixedFile ("c5f4319ee3e077436e3950c8a764959d50bf57c0");
@@ -84,7 +83,6 @@ namespace MonoDevelop.VersionControl.Git.Tests
}
[Test]
- [Ignore ("This fails with NGit, probably because the diff algorithm is different")]
public void TestBlameRevisionsWithTwoCommits ()
{
string commit1 = "b6e41ee2dd00e8744abc4835567e06667891b2cf";
@@ -134,12 +132,10 @@ namespace MonoDevelop.VersionControl.Git.Tests
[Test]
public void TestBlameLineCountWithNoCommits ()
{
- Commit[] blameCommits = GetBlameForFixedFile ("39fe1158de8da8b82822e299958d35c51d493298");
- Assert.That (blameCommits, Is.Null);
+ Assert.Throws<NotFoundException> (() => GetBlameForFixedFile ("39fe1158de8da8b82822e299958d35c51d493298"));
}
[Test]
- [Ignore]
public void TestBlameForProjectDom ()
{
Commit[] blameCommits = GetBlameForFile ("6469602e3c0ba6953fd3ef0ae01d77abe1d9ab70", "main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Dom.Parser/ProjectDom.cs");
@@ -277,13 +273,20 @@ namespace MonoDevelop.VersionControl.Git.Tests
if (blame == null)
{
- var result = repo.Blame (filePath);
- if (result == null)
+ var result = repo.Blame (filePath, new BlameOptions {
+ StartingAt = revision,
+ });
+ if (!result.Any ())
return null;
- blame = new Commit [result.Count ()];
- for (int i = 0; i < result.Count (); i ++)
- blame [i] = result[i].FinalCommit;
+ var count = result.Sum (hunk => hunk.LineCount);
+ blame = new Commit [count];
+ int x = 0;
+ foreach (var res in result) {
+ for (int i = 0; i < res.LineCount; ++i)
+ blame [x++] = res.FinalCommit;
+ }
+
blames.Add(key, blame);
}
@@ -316,4 +319,4 @@ namespace MonoDevelop.VersionControl.Git.Tests
}
}
}
-*/
+
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/MonoDevelop.VersionControl.Git.Tests.csproj b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/MonoDevelop.VersionControl.Git.Tests.csproj
index 8d3035bf6f..1fc7c56620 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/MonoDevelop.VersionControl.Git.Tests.csproj
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/MonoDevelop.VersionControl.Git.Tests.csproj
@@ -80,6 +80,7 @@
<NoWarn>1591;1573</NoWarn>
<DebugType>pdbonly</DebugType>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <ConsolePause>false</ConsolePause>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseMac|AnyCPU' ">
<Optimize>true</Optimize>
@@ -89,6 +90,7 @@
<NoWarn>1591;1573</NoWarn>
<DebugType>pdbonly</DebugType>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <ConsolePause>false</ConsolePause>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseGnome|AnyCPU' ">
<Optimize>true</Optimize>
@@ -98,6 +100,7 @@
<NoWarn>1591;1573</NoWarn>
<DebugType>pdbonly</DebugType>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <ConsolePause>false</ConsolePause>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git.csproj b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git.csproj
index 1c05383835..7b5fee7c62 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git.csproj
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git.csproj
@@ -80,10 +80,11 @@
<OutputPath>..\..\..\..\build\AddIns\VersionControl</OutputPath>
<WarningLevel>4</WarningLevel>
<DebugSymbols>true</DebugSymbols>
- <NoWarn>1591;1573</NoWarn>
+ <NoWarn>1591</NoWarn>
<DocumentationFile>..\..\..\..\build\AddIns\VersionControl\MonoDevelop.VersionControl.Git.xml</DocumentationFile>
<DebugType>pdbonly</DebugType>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <ConsolePause>false</ConsolePause>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseMac|AnyCPU' ">
<Optimize>true</Optimize>
@@ -94,6 +95,7 @@
<DocumentationFile>..\..\..\..\build\AddIns\VersionControl\MonoDevelop.VersionControl.Git.xml</DocumentationFile>
<DebugType>pdbonly</DebugType>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <ConsolePause>false</ConsolePause>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseGnome|AnyCPU' ">
<Optimize>true</Optimize>
@@ -104,6 +106,7 @@
<DocumentationFile>..\..\..\..\build\AddIns\VersionControl\MonoDevelop.VersionControl.Git.xml</DocumentationFile>
<DebugType>pdbonly</DebugType>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <ConsolePause>false</ConsolePause>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
@@ -113,6 +116,7 @@
<Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
<Reference Include="Mono.Posix" />
<Reference Include="System.Core" />
+ <Reference Include="System.Net.Http" />
</ItemGroup>
<ItemGroup>
<Compile Include="AssemblyInfo.cs" />
@@ -157,6 +161,7 @@
<Compile Include="MonoDevelop.VersionControl.Git\GitSelectRevisionDialog.cs" />
<Compile Include="AddinInfo.cs" />
<Compile Include="MonoDevelop.VersionControl.Git\ProjectTemplateHandler.cs" />
+ <Compile Include="MonoDevelop.VersionControl.Git\TfsSmartSubtransport.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\core\Mono.Texteditor\Mono.TextEditor.csproj">
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/EditRemoteDialog.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/EditRemoteDialog.cs
index 06d6659086..5e05821a6e 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/EditRemoteDialog.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/EditRemoteDialog.cs
@@ -36,6 +36,7 @@ namespace MonoDevelop.VersionControl.Git
{
}
+ bool sameUrls;
public EditRemoteDialog (Remote remote)
{
this.Build ();
@@ -47,10 +48,20 @@ namespace MonoDevelop.VersionControl.Git
entryUrl.Text = remote.Url ?? "";
entryPushUrl.Text = remote.PushUrl ?? "";
}
+
+ sameUrls = entryPushUrl.Text == entryUrl.Text;
+ SetPushUrlTextStyle (sameUrls);
+
checkImportTags.Visible = remote == null;
UpdateButtons ();
}
+ void SetPushUrlTextStyle (bool disabled)
+ {
+ entryPushUrl.ModifyText (Gtk.StateType.Normal, entryUrl.Style.Text (disabled ? Gtk.StateType.Insensitive : Gtk.StateType.Normal));
+ entryPushUrl.ModifyText (Gtk.StateType.Active, entryUrl.Style.Text (disabled ? Gtk.StateType.Insensitive : Gtk.StateType.Active));
+ }
+
public string RemoteName {
get { return entryName.Text; }
}
@@ -79,11 +90,21 @@ namespace MonoDevelop.VersionControl.Git
protected virtual void OnEntryUrlChanged (object sender, System.EventArgs e)
{
+ // If we had the same text or we're now having matching text, then change styling.
+ if (sameUrls || entryPushUrl.Text == entryUrl.Text) {
+ entryPushUrl.Text = entryUrl.Text;
+ sameUrls = true;
+ SetPushUrlTextStyle (sameUrls);
+ }
+
UpdateButtons ();
}
protected void OnEntryPushUrlChanged (object sender, System.EventArgs e)
{
+ sameUrls = entryPushUrl.Text == entryUrl.Text;
+ SetPushUrlTextStyle (sameUrls);
+
UpdateButtons ();
}
}
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitCommitDialogExtension.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitCommitDialogExtension.cs
index eb5035ecf0..e058292500 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitCommitDialogExtension.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitCommitDialogExtension.cs
@@ -55,6 +55,12 @@ namespace MonoDevelop.VersionControl.Git
return false;
}
+ public override string FormatDialogTitle (ChangeSet changeSet, string title)
+ {
+ var gitRepo = changeSet.Repository as GitRepository;
+ return gitRepo != null ? string.Format ("{0} ({1})", title, gitRepo.GetCurrentBranch ()) : title;
+ }
+
public override bool OnBeginCommit (ChangeSet changeSet)
{
// In this callback we check if the user information configured in Git
@@ -178,10 +184,12 @@ namespace MonoDevelop.VersionControl.Git
var text = textView.Buffer.Text;
var lines = text.Split ('\n');
if (lines.Length > 0 && lines [0].Length > maxLengthConventionForFirstLineOfCommitMessage) {
- textView.TooltipText = String.Format (GettextCatalog.GetString (
- "When using Git, it is not recommended to surpass the character count of {0} in the first line of the commit message"),
- maxLengthConventionForFirstLineOfCommitMessage);
- textView.HasTooltip = true;
+ if (!textView.HasTooltip) {
+ textView.TooltipText = String.Format (GettextCatalog.GetString (
+ "When using Git, it is not recommended to surpass the character count of {0} in the first line of the commit message"),
+ maxLengthConventionForFirstLineOfCommitMessage);
+ textView.HasTooltip = true;
+ }
textView.Buffer.GetBounds (out start, out unused);
start.ForwardChars (maxLengthConventionForFirstLineOfCommitMessage);
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitConfigurationDialog.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitConfigurationDialog.cs
index bae9843ea2..2aca50c4b4 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitConfigurationDialog.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitConfigurationDialog.cs
@@ -72,6 +72,7 @@ namespace MonoDevelop.VersionControl.Git
string currentBranch = repo.GetCurrentBranch ();
var b = (Branch) storeBranches.GetValue (it, 0);
buttonRemoveBranch.Sensitive = b.FriendlyName != currentBranch;
+ buttonSetDefaultBranch.Sensitive = !b.IsCurrentRepositoryHead;
};
buttonRemoveBranch.Sensitive = buttonEditBranch.Sensitive = buttonSetDefaultBranch.Sensitive = false;
@@ -106,6 +107,9 @@ namespace MonoDevelop.VersionControl.Git
listTags.Model = storeTags;
listTags.HeadersVisible = true;
+ SemanticModelAttribute tagsModelAttr = new SemanticModelAttribute ("storeTags__Name");
+ TypeDescriptor.AddAttributes (storeTags, tagsModelAttr);
+
listTags.AppendColumn (GettextCatalog.GetString ("Tag"), new CellRendererText (), "text", 0);
listTags.Selection.Changed += delegate {
@@ -254,12 +258,14 @@ namespace MonoDevelop.VersionControl.Git
var dlg = new EditRemoteDialog (remote);
try {
if (MessageService.RunCustomDialog (dlg) == (int) ResponseType.Ok) {
- if (remote.Name != dlg.RemoteName)
- repo.RenameRemote (remote.Name, dlg.RemoteName);
if (remote.Url != dlg.RemoteUrl)
repo.ChangeRemoteUrl (remote.Name, dlg.RemoteUrl);
- if (remote.Url != dlg.RemotePushUrl)
+ if (remote.PushUrl != dlg.RemotePushUrl)
repo.ChangeRemotePushUrl (remote.Name, dlg.RemotePushUrl);
+
+ // Only do rename after we've done previous changes.
+ if (remote.Name != dlg.RemoteName)
+ repo.RenameRemote (remote.Name, dlg.RemoteName);
FillRemotes ();
}
} finally {
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitCredentials.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitCredentials.cs
index 0c23113c5d..f6aaa17013 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitCredentials.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitCredentials.cs
@@ -34,23 +34,42 @@ using MonoDevelop.Components;
namespace MonoDevelop.VersionControl.Git
{
+ public enum GitCredentialsType
+ {
+ Normal,
+ Tfs,
+ }
+
+ public class GitCredentialsState
+ {
+ public string UrlUsed { get; set; }
+ public bool AgentUsed { get; set; }
+ public int KeyUsed { get; set; }
+ public bool NativePasswordUsed { get; set; }
+ public Dictionary<string, int> KeyForUrl = new Dictionary<string, int> ();
+ public Dictionary<string, bool> AgentForUrl = new Dictionary<string, bool> ();
+
+ public GitCredentialsState ()
+ {
+ KeyUsed = -1;
+ }
+ }
+
static class GitCredentials
{
// Gather keys on initialize.
static readonly List<string> Keys = new List<string> ();
- static readonly Dictionary<string, int> KeyForUrl = new Dictionary<string, int> ();
- static readonly Dictionary<string, bool> AgentForUrl = new Dictionary<string, bool> ();
- static string urlUsed;
- static bool agentUsed;
- static int keyUsed = -1;
- static bool nativePasswordUsed;
+ static Dictionary<GitCredentialsType, GitCredentialsState> credState = new Dictionary<GitCredentialsType, GitCredentialsState> ();
static GitCredentials ()
{
string keyStorage = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.Personal), ".ssh");
- if (!Directory.Exists (keyStorage))
- return;
+ if (!Directory.Exists (keyStorage)) {
+ keyStorage = Path.Combine (Environment.ExpandEnvironmentVariables ("%HOME%"), ".ssh");
+ if (!Directory.Exists (keyStorage))
+ return;
+ }
foreach (var privateKey in Directory.EnumerateFiles (keyStorage)) {
string publicKey = privateKey + ".pub";
@@ -59,12 +78,15 @@ namespace MonoDevelop.VersionControl.Git
}
}
- public static Credentials TryGet (string url, string userFromUrl, SupportedCredentialTypes types)
+ public static Credentials TryGet (string url, string userFromUrl, SupportedCredentialTypes types, GitCredentialsType type)
{
bool result = true;
Uri uri = null;
- urlUsed = url;
+ GitCredentialsState state;
+ if (!credState.TryGetValue (type, out state))
+ credState [type] = state = new GitCredentialsState ();
+ state.UrlUsed = url;
// We always need to run the TryGet* methods as we need the passphraseItem/passwordItem populated even
// if the password store contains an invalid password/no password
@@ -72,8 +94,8 @@ namespace MonoDevelop.VersionControl.Git
uri = new Uri (url);
string username;
string password;
- if (!nativePasswordUsed && TryGetUsernamePassword (uri, out username, out password)) {
- nativePasswordUsed = true;
+ if (!state.NativePasswordUsed && TryGetUsernamePassword (uri, out username, out password)) {
+ state.NativePasswordUsed = true;
return new UsernamePasswordCredentials {
Username = username,
Password = password
@@ -86,13 +108,13 @@ namespace MonoDevelop.VersionControl.Git
cred = new UsernamePasswordCredentials ();
else {
// Try ssh-agent on Linux.
- if (!Platform.IsWindows && !agentUsed) {
+ if (!Platform.IsWindows && !state.AgentUsed) {
bool agentUsable;
- if (!AgentForUrl.TryGetValue (url, out agentUsable))
- AgentForUrl [url] = agentUsable = true;
+ if (!state.AgentForUrl.TryGetValue (url, out agentUsable))
+ state.AgentForUrl [url] = agentUsable = true;
if (agentUsable) {
- agentUsed = true;
+ state.AgentUsed = true;
return new SshAgentCredentials {
Username = userFromUrl,
};
@@ -100,9 +122,9 @@ namespace MonoDevelop.VersionControl.Git
}
int key;
- if (!KeyForUrl.TryGetValue (url, out key)) {
- if (keyUsed + 1 < Keys.Count)
- keyUsed++;
+ if (!state.KeyForUrl.TryGetValue (url, out key)) {
+ if (state.KeyUsed + 1 < Keys.Count)
+ state.KeyUsed++;
else {
SelectFileDialog dlg = null;
bool success = false;
@@ -135,13 +157,13 @@ namespace MonoDevelop.VersionControl.Git
throw new VersionControlException (GettextCatalog.GetString ("Invalid credentials were supplied. Aborting operation."));
}
} else
- keyUsed = key;
+ state.KeyUsed = key;
cred = new SshUserKeyCredentials {
Username = userFromUrl,
Passphrase = "",
- PrivateKey = Keys [keyUsed],
- PublicKey = Keys [keyUsed] + ".pub",
+ PrivateKey = Keys [state.KeyUsed],
+ PublicKey = Keys [state.KeyUsed] + ".pub",
};
return cred;
}
@@ -194,31 +216,40 @@ namespace MonoDevelop.VersionControl.Git
return false;
}
- internal static void StoreCredentials ()
+ internal static void StoreCredentials (GitCredentialsType type)
{
- nativePasswordUsed = false;
+ GitCredentialsState state;
+ if (!credState.TryGetValue (type, out state))
+ return;
+
+ var url = state.UrlUsed;
+ var key = state.KeyUsed;
- if (!string.IsNullOrEmpty (urlUsed))
- if (keyUsed != -1)
- KeyForUrl [urlUsed] = keyUsed;
+ state.NativePasswordUsed = false;
- Cleanup ();
+ if (!string.IsNullOrEmpty (url) && key != -1)
+ state.KeyForUrl [url] = key;
+
+ Cleanup (state);
}
- internal static void InvalidateCredentials ()
+ internal static void InvalidateCredentials (GitCredentialsType type)
{
- if (!string.IsNullOrEmpty (urlUsed))
- if (AgentForUrl.ContainsKey (urlUsed))
- AgentForUrl [urlUsed] &= !agentUsed;
+ GitCredentialsState state;
+ if (!credState.TryGetValue (type, out state))
+ return;
+
+ if (!string.IsNullOrEmpty (state.UrlUsed) && state.AgentForUrl.ContainsKey (state.UrlUsed))
+ state.AgentForUrl [state.UrlUsed] &= !state.AgentUsed;
- Cleanup ();
+ Cleanup (state);
}
- static void Cleanup ()
+ static void Cleanup (GitCredentialsState state)
{
- urlUsed = null;
- agentUsed = false;
- keyUsed = -1;
+ state.UrlUsed = null;
+ state.AgentUsed = false;
+ state.KeyUsed = -1;
}
}
}
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitRepository.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitRepository.cs
index 6802d5a322..a91ff501a2 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitRepository.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitRepository.cs
@@ -62,14 +62,14 @@ namespace MonoDevelop.VersionControl.Git
public GitRepository (VersionControlSystem vcs, FilePath path, string url) : base (vcs)
{
RootPath = path;
- string discovered = LibGit2Sharp.Repository.Discover (path);
- if (!string.IsNullOrEmpty (discovered))
- RootRepository = new LibGit2Sharp.Repository (discovered);
+ RootRepository = new LibGit2Sharp.Repository (path);
Url = url;
}
public override void Dispose ()
{
+ base.Dispose ();
+
if (VersionControlSystem != null)
((GitVersionControl)VersionControlSystem).UnregisterRepo (this);
@@ -77,7 +77,6 @@ namespace MonoDevelop.VersionControl.Git
RootRepository.Dispose ();
foreach (var rep in cachedSubmodules)
rep.Item2.Dispose ();
- base.Dispose ();
}
public override string[] SupportedProtocols {
@@ -163,33 +162,49 @@ namespace MonoDevelop.VersionControl.Git
return true;
}
+ const int progressThrottle = 200;
+ static System.Diagnostics.Stopwatch throttleWatch = new System.Diagnostics.Stopwatch ();
static bool OnTransferProgress (TransferProgress tp, IProgressMonitor monitor, ref int progress)
{
- if (progress == 0 && tp.ReceivedObjects == 0)
+ if (progress == 0 && tp.ReceivedObjects == 0) {
monitor.BeginTask ("Receiving and indexing objects", 2 * tp.TotalObjects);
+ throttleWatch.Restart ();
+ }
int currentProgress = tp.ReceivedObjects + tp.IndexedObjects;
int steps = currentProgress - progress;
- monitor.Step (steps);
+ if (throttleWatch.ElapsedMilliseconds > progressThrottle) {
+ monitor.Step (steps);
+ throttleWatch.Restart ();
+ }
progress = currentProgress;
- if (tp.IndexedObjects >= tp.TotalObjects)
+ if (tp.IndexedObjects >= tp.TotalObjects) {
monitor.EndTask ();
+ throttleWatch.Stop ();
+ }
return !monitor.IsCancelRequested;
}
static void OnCheckoutProgress (int completedSteps, int totalSteps, IProgressMonitor monitor, ref int progress)
{
- if (progress == 0 && completedSteps == 0)
+ if (progress == 0 && completedSteps == 0) {
monitor.BeginTask ("Checking out files", totalSteps);
+ throttleWatch.Restart ();
+ }
int steps = completedSteps - progress;
- monitor.Step (steps);
+ if (throttleWatch.ElapsedMilliseconds > progressThrottle) {
+ monitor.Step (steps);
+ throttleWatch.Restart ();
+ }
progress = completedSteps;
- if (completedSteps >= totalSteps)
+ if (completedSteps >= totalSteps) {
monitor.EndTask ();
+ throttleWatch.Stop ();
+ }
}
void NotifyFilesChangedForStash (Stash stash)
@@ -215,7 +230,7 @@ namespace MonoDevelop.VersionControl.Git
OnCheckoutProgress = (path, completedSteps, totalSteps) => OnCheckoutProgress (completedSteps, totalSteps, monitor, ref progress),
OnCheckoutNotify = RefreshFile,
CheckoutNotifyFlags = refreshFlags,
- }
+ },
});
NotifyFilesChangedForStash (RootRepository.Stashes [stashIndex]);
@@ -237,7 +252,7 @@ namespace MonoDevelop.VersionControl.Git
OnCheckoutProgress = (path, completedSteps, totalSteps) => OnCheckoutProgress (completedSteps, totalSteps, monitor, ref progress),
OnCheckoutNotify = RefreshFile,
CheckoutNotifyFlags = refreshFlags,
- }
+ },
});
NotifyFilesChangedForStash (stash);
if (monitor != null)
@@ -559,18 +574,16 @@ namespace MonoDevelop.VersionControl.Git
RootRepository.Branches.Update (RootRepository.Branches ["master"], branch => branch.TrackedBranch = "refs/remotes/origin/master");
- RetryUntilSuccess (monitor, delegate {
- RootRepository.Network.Push (RootRepository.Head, new PushOptions {
- OnPushStatusError = delegate (PushStatusError e) {
- RootRepository.Dispose ();
- RootRepository = null;
- if (RootPath.Combine (".git").IsDirectory)
- Directory.Delete (RootPath.Combine (".git"), true);
- throw new VersionControlException (e.Message);
- },
- CredentialsProvider = GitCredentials.TryGet
- });
- });
+ RetryUntilSuccess (monitor, credType => RootRepository.Network.Push (RootRepository.Head, new PushOptions {
+ OnPushStatusError = delegate (PushStatusError e) {
+ RootRepository.Dispose ();
+ RootRepository = null;
+ if (RootPath.Combine (".git").IsDirectory)
+ Directory.Delete (RootPath.Combine (".git"), true);
+ throw new VersionControlException (e.Message);
+ },
+ CredentialsProvider = (url, userFromUrl, types) => GitCredentials.TryGet (url, userFromUrl, types, credType)
+ }));
return this;
}
@@ -595,54 +608,61 @@ namespace MonoDevelop.VersionControl.Git
monitor.EndTask ();
}
- static void RetryUntilSuccess (IProgressMonitor monitor, Action func)
+ static void RetryUntilSuccess (IProgressMonitor monitor, Action<GitCredentialsType> func)
{
bool retry;
- do {
- try {
- func ();
- GitCredentials.StoreCredentials ();
- retry = false;
- } catch (AuthenticationException) {
- GitCredentials.InvalidateCredentials ();
- retry = true;
- } catch (VersionControlException e) {
- GitCredentials.InvalidateCredentials ();
- if (monitor != null)
- monitor.ReportError (e.Message, null);
- retry = false;
- } catch (UserCancelledException) {
- GitCredentials.StoreCredentials ();
- retry = false;
- } catch (LibGit2SharpException e) {
- GitCredentials.InvalidateCredentials ();
-
- string message;
- // TODO: Remove me once https://github.com/libgit2/libgit2/pull/3137 goes in.
- if (string.Equals (e.Message, "early EOF", StringComparison.OrdinalIgnoreCase))
- message = "Unable to authorize credentials for the repository.";
- else if (string.Equals (e.Message, "Received unexpected content-type", StringComparison.OrdinalIgnoreCase))
- message = "Not a valid git repository.";
- else
- message = e.Message;
+ using (var tfsSession = new TfsSmartSession ()) {
+ do {
+ var credType = tfsSession.Disposed ? GitCredentialsType.Normal : GitCredentialsType.Tfs;
+ try {
+ func (credType);
+ GitCredentials.StoreCredentials (credType);
+ retry = false;
+ } catch (AuthenticationException) {
+ GitCredentials.InvalidateCredentials (credType);
+ retry = true;
+ } catch (VersionControlException e) {
+ GitCredentials.InvalidateCredentials (credType);
+ if (monitor != null)
+ monitor.ReportError (e.Message, null);
+ retry = false;
+ } catch (UserCancelledException) {
+ GitCredentials.StoreCredentials (credType);
+ retry = false;
+ } catch (LibGit2SharpException e) {
+ GitCredentials.InvalidateCredentials (credType);
+
+ if (!tfsSession.Disposed) {
+ retry = true;
+ tfsSession.Dispose ();
+ continue;
+ }
- if (monitor != null)
- monitor.ReportError (message, null);
- retry = false;
- }
- } while (retry);
+ string message;
+ // TODO: Remove me once https://github.com/libgit2/libgit2/pull/3137 goes in.
+ if (string.Equals (e.Message, "early EOF", StringComparison.OrdinalIgnoreCase))
+ message = "Unable to authorize credentials for the repository.";
+ else if (string.Equals (e.Message, "Received unexpected content-type", StringComparison.OrdinalIgnoreCase))
+ message = "Not a valid git repository.";
+ else
+ message = e.Message;
+
+ if (monitor != null)
+ monitor.ReportError (message, null);
+ retry = false;
+ }
+ } while (retry);
+ }
}
public void Fetch (IProgressMonitor monitor, string remote)
{
monitor.Log.WriteLine (GettextCatalog.GetString ("Fetching from '{0}'", remote));
int progress = 0;
- RetryUntilSuccess (monitor, delegate {
- RootRepository.Fetch (remote, new FetchOptions {
- CredentialsProvider = GitCredentials.TryGet,
- OnTransferProgress = (tp) => OnTransferProgress (tp, monitor, ref progress),
- });
- });
+ RetryUntilSuccess (monitor, credType => RootRepository.Fetch (remote, new FetchOptions {
+ CredentialsProvider = (url, userFromUrl, types) => GitCredentials.TryGet (url, userFromUrl, types, credType),
+ OnTransferProgress = tp => OnTransferProgress (tp, monitor, ref progress),
+ }));
monitor.Step (1);
}
@@ -682,26 +702,27 @@ namespace MonoDevelop.VersionControl.Git
return true;
}
- void ConflictResolver(IProgressMonitor monitor, Commit resetToIfFail, string message)
+ bool ConflictResolver(IProgressMonitor monitor, Commit resetToIfFail, string message)
{
- bool commit = true;
foreach (var conflictFile in RootRepository.Index.Conflicts) {
ConflictResult res = ResolveConflict (RootRepository.FromGitPath (conflictFile.Ancestor.Path));
if (res == ConflictResult.Abort) {
RootRepository.Reset (ResetMode.Hard, resetToIfFail);
- commit = false;
- break;
+ return false;
}
if (res == ConflictResult.Skip) {
Revert (RootRepository.FromGitPath (conflictFile.Ancestor.Path), false, monitor);
break;
}
}
- if (commit)
- RootRepository.Commit (message);
+ if (!string.IsNullOrEmpty (message)) {
+ var sig = GetSignature ();
+ RootRepository.Commit (message, sig, sig);
+ }
+ return true;
}
- void CommonPostMergeRebase(int stashIndex, GitUpdateOptions options, IProgressMonitor monitor)
+ void CommonPostMergeRebase(int stashIndex, GitUpdateOptions options, IProgressMonitor monitor, Commit oldHead)
{
if ((options & GitUpdateOptions.SaveLocalChanges) == GitUpdateOptions.SaveLocalChanges) {
monitor.Step (1);
@@ -709,7 +730,13 @@ namespace MonoDevelop.VersionControl.Git
// Restore local changes
if (stashIndex != -1) {
monitor.Log.WriteLine (GettextCatalog.GetString ("Restoring local changes"));
- PopStash (monitor, stashIndex);
+ ApplyStash (monitor, stashIndex);
+ // FIXME: No StashApplyStatus.Conflicts here.
+ if (RootRepository.Index.Conflicts.Any () && !ConflictResolver (monitor, oldHead, string.Empty))
+ PopStash (monitor, stashIndex);
+ else
+ RootRepository.Stashes.Remove (stashIndex);
+
monitor.Step (1);
}
}
@@ -719,6 +746,8 @@ namespace MonoDevelop.VersionControl.Git
public void Rebase (string branch, GitUpdateOptions options, IProgressMonitor monitor)
{
int stashIndex = -1;
+ var oldHead = RootRepository.Head.Tip;
+
try {
monitor.BeginTask (GettextCatalog.GetString ("Rebasing"), 5);
if (!CommonPreMergeRebase (options, monitor, out stashIndex))
@@ -727,14 +756,14 @@ namespace MonoDevelop.VersionControl.Git
// Do a rebase.
var divergence = RootRepository.ObjectDatabase.CalculateHistoryDivergence (RootRepository.Head.Tip, RootRepository.Branches [branch].Tip);
var toApply = RootRepository.Commits.QueryBy (new CommitFilter {
- Since = RootRepository.Head.Tip,
- Until = divergence.CommonAncestor,
- SortBy = CommitSortStrategies.Topological
- });
+ IncludeReachableFrom = RootRepository.Head.Tip,
+ ExcludeReachableFrom = divergence.CommonAncestor,
+ SortBy = CommitSortStrategies.Topological | CommitSortStrategies.Reverse
+ }).ToArray ();
RootRepository.Reset (ResetMode.Hard, divergence.Another);
- int count = toApply.Count ();
+ int count = toApply.Length;
int i = 1;
foreach (var com in toApply) {
monitor.Log.WriteLine ("Cherry-picking {0} - {1}/{2}", com.Id, i, count);
@@ -747,13 +776,14 @@ namespace MonoDevelop.VersionControl.Git
++i;
}
} finally {
- CommonPostMergeRebase (stashIndex, options, monitor);
+ CommonPostMergeRebase (stashIndex, options, monitor, oldHead);
}
}
public void Merge (string branch, GitUpdateOptions options, IProgressMonitor monitor)
{
int stashIndex = -1;
+ var oldHead = RootRepository.Head.Tip;
Signature sig = GetSignature ();
if (sig == null)
@@ -772,7 +802,7 @@ namespace MonoDevelop.VersionControl.Git
if (mergeResult.Status == MergeStatus.Conflicts)
ConflictResolver (monitor, RootRepository.Head.Tip, RootRepository.Info.Message);
} finally {
- CommonPostMergeRebase (stashIndex, GitUpdateOptions.SaveLocalChanges, monitor);
+ CommonPostMergeRebase (stashIndex, GitUpdateOptions.SaveLocalChanges, monitor, oldHead);
}
}
@@ -824,7 +854,7 @@ namespace MonoDevelop.VersionControl.Git
(string)changeSet.ExtendedProperties ["Git.AuthorEmail"],
DateTimeOffset.Now), sig);
else
- repo.RootRepository.Commit (message, sig);
+ repo.RootRepository.Commit (message, sig, sig);
}
public bool IsUserInfoDefault ()
@@ -877,12 +907,13 @@ namespace MonoDevelop.VersionControl.Git
{
int transferProgress = 0;
int checkoutProgress = 0;
- RetryUntilSuccess (monitor, delegate {
+ RetryUntilSuccess (monitor, credType => {
RootPath = LibGit2Sharp.Repository.Clone (Url, targetLocalPath, new CloneOptions {
- CredentialsProvider = GitCredentials.TryGet,
+ CredentialsProvider = (url, userFromUrl, types) => GitCredentials.TryGet (url, userFromUrl, types, credType),
OnTransferProgress = (tp) => OnTransferProgress (tp, monitor, ref transferProgress),
OnCheckoutProgress = (path, completedSteps, totalSteps) => OnCheckoutProgress (completedSteps, totalSteps, monitor, ref checkoutProgress),
+ RecurseSubmodules = true,
});
});
@@ -1094,10 +1125,10 @@ namespace MonoDevelop.VersionControl.Git
RootRepository.Branches.Update (branch, b => b.TrackedBranch = "refs/remotes/" + remote + "/" + remoteBranch);
}
- RetryUntilSuccess (monitor, () =>
+ RetryUntilSuccess (monitor, credType =>
RootRepository.Network.Push (RootRepository.Network.Remotes [remote], "refs/heads/" + remoteBranch, new PushOptions {
OnPushStatusError = pushStatusErrors => success = false,
- CredentialsProvider = GitCredentials.TryGet
+ CredentialsProvider = (url, userFromUrl, types) => GitCredentials.TryGet (url, userFromUrl, types, credType)
})
);
@@ -1216,16 +1247,16 @@ namespace MonoDevelop.VersionControl.Git
public void PushTag (string name)
{
- RetryUntilSuccess (null, delegate {
- RootRepository.Network.Push (RootRepository.Network.Remotes [GetCurrentRemote ()], "refs/tags/" + name + ":refs/tags/" + name, new PushOptions {
- CredentialsProvider = GitCredentials.TryGet,
- });
- });
+ RetryUntilSuccess (null, credType => RootRepository.Network.Push (RootRepository.Network.Remotes [GetCurrentRemote ()], "refs/tags/" + name + ":refs/tags/" + name, new PushOptions {
+ CredentialsProvider = (url, userFromUrl, types) => GitCredentials.TryGet (url, userFromUrl, types, credType),
+ }));
}
public IEnumerable<string> GetRemoteBranches (string remoteName)
{
- return RootRepository.Branches.Where (b => b.IsRemote && b.Remote.Name == remoteName).Select (b => b.FriendlyName.Substring (b.FriendlyName.IndexOf ('/') + 1));
+ return RootRepository.Branches
+ .Where (b => b.IsRemote && b.Remote != null && b.Remote.Name == remoteName)
+ .Select (b => b.FriendlyName.Substring (b.FriendlyName.IndexOf ('/') + 1));
}
public string GetCurrentBranch ()
@@ -1377,6 +1408,9 @@ namespace MonoDevelop.VersionControl.Git
protected override void OnMoveFile (FilePath localSrcPath, FilePath localDestPath, bool force, IProgressMonitor monitor)
{
+ var srcRepo = GetRepository (localSrcPath);
+ var dstRepo = GetRepository (localDestPath);
+
VersionInfo vi = GetVersionInfo (localSrcPath, VersionInfoQueryFlags.IgnoreCache);
if (vi == null || !vi.IsVersioned) {
base.OnMoveFile (localSrcPath, localDestPath, force, monitor);
@@ -1385,10 +1419,16 @@ namespace MonoDevelop.VersionControl.Git
vi = GetVersionInfo (localDestPath, VersionInfoQueryFlags.IgnoreCache);
if (vi != null && ((vi.Status & (VersionStatus.ScheduledDelete | VersionStatus.ScheduledReplace)) != VersionStatus.Unversioned))
- RootRepository.Unstage (localDestPath);
+ dstRepo.Unstage (localDestPath);
- RootRepository.Move (localSrcPath, localDestPath);
- ClearCachedVersionInfo (localSrcPath, localDestPath);
+ if (srcRepo == dstRepo) {
+ srcRepo.Move (localSrcPath, localDestPath);
+ ClearCachedVersionInfo (localSrcPath, localDestPath);
+ } else {
+ File.Copy (localSrcPath, localDestPath);
+ srcRepo.Remove (localSrcPath, true);
+ dstRepo.Stage (localDestPath);
+ }
}
protected override void OnMoveDirectory (FilePath localSrcPath, FilePath localDestPath, bool force, IProgressMonitor monitor)
@@ -1422,7 +1462,7 @@ namespace MonoDevelop.VersionControl.Git
repositoryPath = repository.ToGitPath (repositoryPath);
var status = repository.RetrieveStatus (repositoryPath);
if (status != FileStatus.NewInIndex && status != FileStatus.NewInWorkdir) {
- foreach (var hunk in repository.Blame (repositoryPath, new BlameOptions { Strategy = BlameStrategy.FollowExactRenames })) {
+ foreach (var hunk in repository.Blame (repositoryPath, new BlameOptions { FindExactRenames = true, })) {
var commit = hunk.FinalCommit;
var author = hunk.FinalSignature;
working = new Annotation (commit.Sha, author.Name, author.When.LocalDateTime, String.Format ("<{0}>", author.Email));
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitUtil.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitUtil.cs
index 57b2afc7f3..44776dafe0 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitUtil.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitUtil.cs
@@ -71,12 +71,5 @@ namespace MonoDevelop.VersionControl.Git
repo.Network.Remotes.Add ("origin", url);
return repo;
}
-
- internal static bool IsGitRepository (this FilePath path)
- {
- // Maybe check if it has a HEAD file? But this check should be enough.
- var newPath = path.Combine (".git");
- return Directory.Exists (newPath) && Directory.Exists (newPath.Combine ("objects")) && Directory.Exists (newPath.Combine ("refs"));
- }
}
}
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitVersionControl.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitVersionControl.cs
index 89d279df66..96bc74e8fc 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitVersionControl.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/GitVersionControl.cs
@@ -63,11 +63,7 @@ namespace MonoDevelop.VersionControl.Git
protected override FilePath OnGetRepositoryPath (FilePath path, string id)
{
- if (path.IsEmpty || path.ParentDirectory.IsEmpty || path.IsNull || path.ParentDirectory.IsNull)
- return null;
- if (path.IsGitRepository ())
- return path;
- return OnGetRepositoryPath (path.ParentDirectory, id);
+ return LibGit2Sharp.Repository.Discover (path.ResolveLinks ());
}
internal void UnregisterRepo (GitRepository repo)
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/TfsSmartSubtransport.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/TfsSmartSubtransport.cs
new file mode 100644
index 0000000000..a9b1485780
--- /dev/null
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git/MonoDevelop.VersionControl.Git/TfsSmartSubtransport.cs
@@ -0,0 +1,166 @@
+//
+// NtlmSmartSubtransport.cs
+//
+// Author:
+// Marius Ungureanu <marius.ungureanu@xamarin.com>
+//
+// Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com)
+//
+// 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.Net.Http;
+using LibGit2Sharp;
+using System.IO;
+
+namespace MonoDevelop.VersionControl.Git
+{
+ public class TfsSmartSession : IDisposable
+ {
+ readonly SmartSubtransportRegistration<TfsSmartSubtransport> httpRegistration;
+ readonly SmartSubtransportRegistration<TfsSmartSubtransport> httpsRegistration;
+
+ public TfsSmartSession ()
+ {
+ httpRegistration = GlobalSettings.RegisterSmartSubtransport<TfsSmartSubtransport> ("http");
+ httpsRegistration = GlobalSettings.RegisterSmartSubtransport<TfsSmartSubtransport> ("https");
+ }
+
+ public bool Disposed { get; private set; }
+ public void Dispose ()
+ {
+ if (!Disposed) {
+ GlobalSettings.UnregisterSmartSubtransport<TfsSmartSubtransport> (httpRegistration);
+ GlobalSettings.UnregisterSmartSubtransport<TfsSmartSubtransport> (httpsRegistration);
+ Disposed = true;
+ }
+ }
+ }
+
+ public class TfsSmartSubtransport : RpcSmartSubtransport
+ {
+ protected override SmartSubtransportStream Action(string url, GitSmartSubtransportAction action)
+ {
+ string postContentType = null;
+ string serviceUri;
+
+ switch (action) {
+ case GitSmartSubtransportAction.UploadPackList:
+ serviceUri = url + "/info/refs?service=git-upload-pack";
+ break;
+ case GitSmartSubtransportAction.UploadPack:
+ serviceUri = url + "/git-upload-pack";
+ postContentType = "application/x-git-upload-pack-request";
+ break;
+ case GitSmartSubtransportAction.ReceivePackList:
+ serviceUri = url + "/info/refs?service=git-receive-pack";
+ break;
+ case GitSmartSubtransportAction.ReceivePack:
+ serviceUri = url + "/git-receive-pack";
+ postContentType = "application/x-git-receive-pack-request";
+ break;
+ default:
+ throw new InvalidOperationException();
+ }
+
+ // Grab the credentials from the user.
+ var httpClient = new HttpClient {
+ Timeout = TimeSpan.FromMinutes (1.0),
+ };
+
+ var res = httpClient.GetAsync (serviceUri).Result;
+ if (res.StatusCode == System.Net.HttpStatusCode.Unauthorized) {
+ var cred = (UsernamePasswordCredentials)GitCredentials.TryGet (url, "", SupportedCredentialTypes.UsernamePassword, GitCredentialsType.Tfs);
+
+ httpClient = new HttpClient (new HttpClientHandler { Credentials = new System.Net.NetworkCredential (cred.Username, cred.Password) }) {
+ Timeout = TimeSpan.FromMinutes (1.0),
+ };
+ }
+
+ return new TfsSmartSubtransportStream(this) {
+ HttpClient = httpClient,
+ ServiceUri = new Uri (serviceUri),
+ PostContentType = postContentType,
+ };
+ }
+
+ class TfsSmartSubtransportStream : SmartSubtransportStream
+ {
+ public HttpClient HttpClient;
+ public Uri ServiceUri;
+ public string PostContentType;
+
+ Lazy<Stream> responseStream;
+ MemoryStream requestStream;
+
+ public TfsSmartSubtransportStream(SmartSubtransport smartSubtransport) : base(smartSubtransport)
+ {
+ responseStream = new Lazy<Stream> (CreateResponseStream);
+ }
+
+ Stream CreateResponseStream()
+ {
+ HttpResponseMessage result;
+
+ if (requestStream == null)
+ result = HttpClient.GetAsync (ServiceUri, HttpCompletionOption.ResponseHeadersRead).Result;
+ else {
+ requestStream.Seek (0, SeekOrigin.Begin);
+
+ var streamContent = new StreamContent (requestStream);
+ if (!string.IsNullOrEmpty (PostContentType))
+ streamContent.Headers.Add ("Content-Type", PostContentType);
+
+ result = HttpClient.SendAsync (new HttpRequestMessage (HttpMethod.Post, ServiceUri) {
+ Content = streamContent,
+ }, HttpCompletionOption.ResponseHeadersRead).Result;
+ }
+
+ return result.EnsureSuccessStatusCode().Content.ReadAsStreamAsync().Result;
+ }
+
+ public override int Read(Stream dataStream, long length, out long bytesRead)
+ {
+ bytesRead = 0L;
+ var buffer = new byte[64 * 1024];
+ int count;
+
+ while (length > 0 && (count = responseStream.Value.Read(buffer, 0, (int)Math.Min(buffer.Length, length))) > 0) {
+ dataStream.Write(buffer, 0, count);
+ bytesRead += (long)count;
+ length -= (long)count;
+ }
+ return 0;
+ }
+
+ public override int Write(Stream dataStream, long length)
+ {
+ requestStream = requestStream ?? new MemoryStream ();
+
+ var buffer = new byte[64 * 1024];
+ int count;
+ while (length > 0 && (count = dataStream.Read(buffer, 0, (int)Math.Min(buffer.Length, length))) > 0) {
+ requestStream.Write(buffer, 0, count);
+ length -= (long)count;
+ }
+ return 0;
+ }
+ }
+ }
+}
+
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion.Tests/RepositoryTests.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion.Tests/RepositoryTests.cs
index ddbc5124ab..d46fe7313a 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion.Tests/RepositoryTests.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion.Tests/RepositoryTests.cs
@@ -137,6 +137,11 @@ namespace VersionControl.Subversion.Unix.Tests
{
return new SubversionRepository (new SvnClient (), url, path);
}
+
+ protected override Repository GetRepo ()
+ {
+ return new SubversionRepository (new SvnClient (), string.Empty, FilePath.Empty);
+ }
}
}
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion.Unix/MonoDevelop.VersionControl.Subversion.Unix.csproj b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion.Unix/MonoDevelop.VersionControl.Subversion.Unix.csproj
index b787abf01d..39a4ab53a3 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion.Unix/MonoDevelop.VersionControl.Subversion.Unix.csproj
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion.Unix/MonoDevelop.VersionControl.Subversion.Unix.csproj
@@ -57,6 +57,8 @@
<DebugSymbols>true</DebugSymbols>
<DocumentationFile>..\..\..\..\build\AddIns\VersionControl\MonoDevelop.VersionControl.Subversion.Unix.xml</DocumentationFile>
<DebugType>pdbonly</DebugType>
+ <ConsolePause>false</ConsolePause>
+ <NoWarn>1591;1573</NoWarn>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion.csproj b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion.csproj
index 5ffb4039fe..191e7cc630 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion.csproj
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion.csproj
@@ -29,9 +29,9 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>True</Optimize>
- <OutputPath>..\..\..\..\build\AddIns\VersionControl\</OutputPath>
+ <OutputPath>..\..\..\..\build\AddIns\VersionControl</OutputPath>
<ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
+ <WarningLevel>3</WarningLevel>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<Execution>
<Execution clr-version="Net_2_0" />
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion/SubversionRepository.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion/SubversionRepository.cs
index 13e705e53a..54dae06291 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion/SubversionRepository.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion/SubversionRepository.cs
@@ -124,7 +124,7 @@ namespace MonoDevelop.VersionControl.Subversion
var toLock = new List<FilePath>();
foreach (var path in paths) {
- if (!File.Exists (path) || !Svn.HasNeedLock (path) || (File.GetAttributes (path) & FileAttributes.ReadOnly) == 0)
+ if (!File.Exists (path) || !GetVersionInfo (path).IsVersioned || !Svn.HasNeedLock (path) || (File.GetAttributes (path) & FileAttributes.ReadOnly) == 0)
continue;
toLock.Add (path);
}
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion/SubversionVersionControl.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion/SubversionVersionControl.cs
index 6976a39e8d..b18cc66435 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion/SubversionVersionControl.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Subversion/MonoDevelop.VersionControl.Subversion/SubversionVersionControl.cs
@@ -251,18 +251,16 @@ namespace MonoDevelop.VersionControl.Subversion
public class SubversionException : VersionControlException
{
public int ErrorCode {
- get;
- private set;
+ get { return (int)Data ["ErrorCode"]; }
}
public SubversionException (string message, int errorCode) : base (message)
{
- ErrorCode = errorCode;
+ Data ["ErrorCode"] = errorCode;
}
- public SubversionException (string message) : base (message)
+ public SubversionException (string message) : this (message, 0)
{
- ErrorCode = 0;
}
}
}
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Dialogs/CommitDialog.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Dialogs/CommitDialog.cs
index 76b7e4337b..437ef02106 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Dialogs/CommitDialog.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Dialogs/CommitDialog.cs
@@ -39,14 +39,16 @@ using Mono.Addins;
using MonoDevelop.Ide;
using MonoDevelop.Projects;
using MonoDevelop.Components;
+using System.Collections.Generic;
+using System.Linq;
namespace MonoDevelop.VersionControl.Dialogs
{
partial class CommitDialog : Gtk.Dialog
{
ListStore store;
- ArrayList selected = new ArrayList ();
- ArrayList extensions = new ArrayList ();
+ List<FilePath> selected = new List<FilePath> ();
+ List<CommitDialogExtension> extensions = new List<CommitDialogExtension> ();
ChangeSet changeSet;
string oldMessage;
bool responseSensitive;
@@ -90,6 +92,10 @@ namespace MonoDevelop.VersionControl.Dialogs
continue;
}
if (ext.Initialize (changeSet)) {
+ var newTitle = ext.FormatDialogTitle (changeSet, Title);
+ if (newTitle != null)
+ Title = newTitle;
+
ext.CommitMessageTextViewHook (textview);
if (separatorRequired) {
HSeparator sep = new HSeparator ();
@@ -216,7 +222,7 @@ namespace MonoDevelop.VersionControl.Dialogs
}
// Update the change set
- ArrayList todel = new ArrayList ();
+ List<FilePath> todel = new List<FilePath> ();
foreach (ChangeSetItem it in changeSet.Items) {
if (!selected.Contains (it.LocalPath))
todel.Add (it.LocalPath);
@@ -229,7 +235,7 @@ namespace MonoDevelop.VersionControl.Dialogs
int n;
for (n=0; n<extensions.Count; n++) {
- CommitDialogExtension ext = (CommitDialogExtension) extensions [n];
+ CommitDialogExtension ext = extensions [n];
bool res;
try {
res = ext.OnBeginCommit (changeSet);
@@ -240,7 +246,7 @@ namespace MonoDevelop.VersionControl.Dialogs
if (!res) {
// Commit failed. Rollback the previous extensions
for (int m=0; m<n; m++) {
- ext = (CommitDialogExtension) extensions [m];
+ ext = extensions [m];
try {
ext.OnEndCommit (changeSet, false);
} catch {}
@@ -285,7 +291,7 @@ namespace MonoDevelop.VersionControl.Dialogs
public string[] GetFilesToCommit ()
{
- return (string[]) selected.ToArray (typeof(string));
+ return selected.ToPathStrings ().ToArray ();
}
public string Message {
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Dialogs/CommitMessageStylePanelWidget.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Dialogs/CommitMessageStylePanelWidget.cs
index ec28d6d478..79a73b6d11 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Dialogs/CommitMessageStylePanelWidget.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Dialogs/CommitMessageStylePanelWidget.cs
@@ -44,8 +44,7 @@ namespace MonoDevelop.VersionControl
public CommitMessageStylePanelWidget()
{
this.Build();
-
- textview.ModifyFont (FontService.MonospaceFont.CopyModified (0.8d));
+
textview.AcceptsTab = true;
}
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Dialogs/EditRepositoryDialog.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Dialogs/EditRepositoryDialog.cs
index 32a43eddf8..091af96b7b 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Dialogs/EditRepositoryDialog.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Dialogs/EditRepositoryDialog.cs
@@ -1,12 +1,13 @@
using System;
using System.Collections;
+using System.Collections.Generic;
namespace MonoDevelop.VersionControl.Dialogs
{
internal partial class EditRepositoryDialog : Gtk.Dialog
{
Repository repo;
- ArrayList systems = new ArrayList ();
+ List<VersionControlSystem> systems = new List<VersionControlSystem> ();
IRepositoryEditor editor;
public EditRepositoryDialog (Repository editedRepository)
@@ -58,7 +59,7 @@ namespace MonoDevelop.VersionControl.Dialogs
string oldname = repo != null ? repo.Name : "";
- VersionControlSystem vcs = (VersionControlSystem) systems [versionControlType.Active];
+ VersionControlSystem vcs = systems [versionControlType.Active];
repo = vcs.CreateRepositoryInstance ();
repo.Name = oldname;
repo.NameChanged += OnNameChanged;
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Dialogs/SelectRepositoryDialog.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Dialogs/SelectRepositoryDialog.cs
index 972fad24cf..a514938b0e 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Dialogs/SelectRepositoryDialog.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Dialogs/SelectRepositoryDialog.cs
@@ -6,6 +6,7 @@ using MonoDevelop.Core;
using Gtk;
using MonoDevelop.Ide;
using MonoDevelop.Components;
+using System.Collections.Generic;
namespace MonoDevelop.VersionControl.Dialogs
{
@@ -18,10 +19,10 @@ namespace MonoDevelop.VersionControl.Dialogs
internal partial class SelectRepositoryDialog : Gtk.Dialog
{
Repository repo;
- ArrayList systems = new ArrayList ();
+ List<VersionControlSystem> systems = new List<VersionControlSystem> ();
Gtk.TreeStore store;
SelectRepositoryMode mode;
- ArrayList loadingRepos = new ArrayList ();
+ List<Repository> loadingRepos = new List<Repository> ();
IRepositoryEditor currentEditor;
string defaultPath;
@@ -116,7 +117,7 @@ namespace MonoDevelop.VersionControl.Dialogs
if (repCombo.Active == -1)
return;
- VersionControlSystem vcs = (VersionControlSystem) systems [repCombo.Active];
+ VersionControlSystem vcs = systems [repCombo.Active];
repo = vcs.CreateRepositoryInstance ();
currentEditor = vcs.CreateRepositoryEditor (repo);
repoContainer.Add (currentEditor.Widget);
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/BlameWidget.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/BlameWidget.cs
index 51c3dbfa41..ef94cc2166 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/BlameWidget.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/BlameWidget.cs
@@ -399,7 +399,7 @@ namespace MonoDevelop.VersionControl.Views
}
internal double highlightPositon;
- internal Annotation highlightAnnotation;
+ internal Annotation highlightAnnotation, menuAnnotation;
protected override bool OnMotionNotifyEvent (EventMotion evnt)
{
TooltipText = null;
@@ -438,6 +438,9 @@ namespace MonoDevelop.VersionControl.Views
protected override bool OnButtonPressEvent (EventButton evnt)
{
if (evnt.TriggersContextMenu ()) {
+ int startLine = widget.Editor.YToLine (widget.Editor.VAdjustment.Value + evnt.Y);
+ menuAnnotation = startLine > 0 && startLine <= annotations.Count ? annotations[startLine - 1] : null;
+
CommandEntrySet opset = new CommandEntrySet ();
opset.AddItem (BlameCommands.ShowDiff);
opset.AddItem (BlameCommands.ShowLog);
@@ -460,24 +463,24 @@ namespace MonoDevelop.VersionControl.Views
[CommandHandler (BlameCommands.CopyRevision)]
protected void OnCopyRevision ()
{
- if (highlightAnnotation == null)
+ if (menuAnnotation == null)
return;
var clipboard = Clipboard.Get (Gdk.Atom.Intern ("CLIPBOARD", false));
- clipboard.Text = highlightAnnotation.Revision.ToString ();
+ clipboard.Text = menuAnnotation.Revision.ToString ();
clipboard = Clipboard.Get (Gdk.Atom.Intern ("PRIMARY", false));
- clipboard.Text = highlightAnnotation.Revision.ToString ();
+ clipboard.Text = menuAnnotation.Revision.ToString ();
}
[CommandHandler (BlameCommands.ShowDiff)]
protected void OnShowDiff ()
{
- if (highlightAnnotation == null)
+ if (menuAnnotation == null)
return;
foreach (var view in widget.info.Document.ParentDocument.Views) {
DiffView diffView = view.GetContent<DiffView> ();
if (diffView != null) {
view.Select ();
- var rev = widget.info.History.FirstOrDefault (h => h.ToString () == highlightAnnotation.Revision);
+ var rev = widget.info.History.FirstOrDefault (h => h.ToString () == menuAnnotation.Revision);
if (rev == null)
return;
diffView.ComparisonWidget.SetRevision (diffView.ComparisonWidget.DiffEditor, rev.GetPrevious ());
@@ -490,13 +493,13 @@ namespace MonoDevelop.VersionControl.Views
[CommandHandler (BlameCommands.ShowLog)]
protected void OnShowLog ()
{
- if (highlightAnnotation == null)
+ if (menuAnnotation == null)
return;
foreach (var view in widget.info.Document.ParentDocument.Views) {
LogView logView = view.GetContent<LogView> ();
if (logView != null) {
view.Select ();
- var rev = widget.info.History.FirstOrDefault (h => h.ToString () == highlightAnnotation.Revision);
+ var rev = widget.info.History.FirstOrDefault (h => h.ToString () == menuAnnotation.Revision);
if (rev == null)
return;
logView.LogWidget.SelectedRevision = rev;
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/LogWidget.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/LogWidget.cs
index 2c4e95e5b2..6d95084b78 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/LogWidget.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/LogWidget.cs
@@ -466,16 +466,18 @@ namespace MonoDevelop.VersionControl.Views
CellRendererText renderer = (CellRendererText)cell;
var rev = (Revision)model.GetValue (iter, 0);
string day;
- var age = rev.Time - DateTime.Now;
- if (age.Days == 0) {
+
+ // Grab today's day and the start of tomorrow's day to make Today/Yesterday calculations.
+ var now = DateTime.Now;
+ var age = new DateTime (now.Year, now.Month, now.Day).AddDays(1) - rev.Time;
+ if (age.Days >= 0 && age.Days < 1) { // Check whether it's a commit that's less than a day away. Also discard future commits.
day = GettextCatalog.GetString ("Today");
- } else if (age.Days == 1) {
+ } else if (age.Days < 2) { // Check whether it's a commit from yesterday.
day = GettextCatalog.GetString ("Yesterday");
} else {
day = rev.Time.ToShortDateString ();
}
- string time = rev.Time.ToString ("HH:MM");
- renderer.Text = day + " " + time;
+ renderer.Text = string.Format ("{0} {1:HH:MM}", day, rev.Time);
}
static void GraphFunc (Gtk.TreeViewColumn tree_column, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter)
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/VersionControlDocumentInfo.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/VersionControlDocumentInfo.cs
index 62faf89ddb..a002693010 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/VersionControlDocumentInfo.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl.Views/VersionControlDocumentInfo.cs
@@ -58,8 +58,8 @@ namespace MonoDevelop.VersionControl.Views
}
public Repository Repository {
- get;
- set;
+ get { return Item.Repository; }
+ set { Item.Repository = value; }
}
public bool Started {
@@ -70,7 +70,7 @@ namespace MonoDevelop.VersionControl.Views
{
this.Document = document;
this.Item = item;
- this.Repository = repository;
+ item.Repository = repository;
}
public void Start (bool rerun = false)
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/AddRemoveMoveCommand.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/AddRemoveMoveCommand.cs
index 70766591ea..7a164f686a 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/AddRemoveMoveCommand.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/AddRemoveMoveCommand.cs
@@ -33,13 +33,14 @@ namespace MonoDevelop.VersionControl
protected override void Run ()
{
IProgressMonitor monitor = Monitor;
-
+
foreach (VersionControlItemList list in items.SplitByRepository ())
list[0].Repository.Add (list.Paths, true, monitor);
Gtk.Application.Invoke (delegate {
VersionControlService.NotifyFileStatusChanged (items);
});
+ monitor.ReportSuccess (GettextCatalog.GetString ("Add operation completed."));
}
}
@@ -133,6 +134,7 @@ namespace MonoDevelop.VersionControl
Gtk.Application.Invoke (delegate {
VersionControlService.NotifyFileStatusChanged (items);
});
+ Monitor.ReportSuccess (GettextCatalog.GetString ("Remove operation completed."));
}
}
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/BlameCommand.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/BlameCommand.cs
index 123abd902f..26504cf950 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/BlameCommand.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/BlameCommand.cs
@@ -39,6 +39,7 @@ namespace MonoDevelop.VersionControl
static bool CanShow (VersionControlItem item)
{
return !item.IsDirectory
+ // FIXME: Review appending of Annotate support and use it.
&& item.VersionInfo.IsVersioned
&& AddinManager.GetExtensionObjects<IBlameViewHandler> (BlameViewHandlers).Any (h => h.CanHandle (item, null));
}
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/ChangeLogWriter.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/ChangeLogWriter.cs
index 40317e6674..c49cea3faa 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/ChangeLogWriter.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/ChangeLogWriter.cs
@@ -89,6 +89,7 @@ namespace MonoDevelop.VersionControl
formatter.MaxColumns = MessageFormat.MaxColumns;
formatter.TabWidth = MessageFormat.TabWidth;
formatter.TabsAsSpaces = MessageFormat.TabsAsSpaces;
+ formatter.KeepLines = true;
if (message_style.Header.Length > 0) {
string [,] tags = new string[,] { {"AuthorName", uinfo.Name}, {"AuthorEmail", uinfo.Email} };
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/CheckoutCommand.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/CheckoutCommand.cs
index f49b4e6b37..140d94f1b0 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/CheckoutCommand.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/CheckoutCommand.cs
@@ -70,7 +70,7 @@ namespace MonoDevelop.VersionControl
try {
vc.Checkout (path, null, true, Monitor);
} catch (VersionControlException e) {
- Monitor.ReportError (GettextCatalog.GetString (e.Message), null);
+ Monitor.ReportError (e.Message, null);
return;
}
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Commands.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Commands.cs
index a8ffdc9e4a..64dd18ff92 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Commands.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Commands.cs
@@ -37,21 +37,20 @@ namespace MonoDevelop.VersionControl
{
VersionControlItemList list = new VersionControlItemList ();
- WorkspaceItem wob;
- SolutionItem sol;
+ IWorkspaceObject wob;
Repository repo = null;
wob = IdeApp.ProjectOperations.CurrentSelectedWorkspaceItem;
if (wob != null)
repo = VersionControlService.GetRepository (wob);
if (repo == null) {
- sol = IdeApp.ProjectOperations.CurrentSelectedSolutionItem;
- if (sol != null)
- repo = VersionControlService.GetRepository (sol);
+ wob = IdeApp.ProjectOperations.CurrentSelectedSolutionItem;
+ if (wob != null)
+ repo = VersionControlService.GetRepository (wob);
}
if (repo == null || repo.VersionControlSystem == null || !repo.VersionControlSystem.IsInstalled)
return list;
- list.Add (new VersionControlItem (repo, wob, wob.FileName, true, null));
+ list.Add (new VersionControlItem (repo, wob, wob.BaseDirectory, true, null));
return list;
}
@@ -107,7 +106,7 @@ namespace MonoDevelop.VersionControl
return new VersionControlItem (repo, project, doc.FileName, false, null);
}
- protected override void Run ()
+ protected sealed override void Run ()
{
VersionControlItemList items = GetItems ();
RunCommand (items, false);
@@ -244,30 +243,28 @@ namespace MonoDevelop.VersionControl
}
}
- class CurrentFileDiffHandler : FileVersionControlCommandHandler
+ class CurrentFileViewHandler<T> : FileVersionControlCommandHandler where T:IAttachableViewContent
{
- protected override void Run ()
+ protected override bool RunCommand (VersionControlItemList items, bool test)
{
+ if (test)
+ return true;
+
var window = IdeApp.Workbench.ActiveDocument.Window;
- window.SwitchView (window.FindView<IDiffView> ());
+ window.SwitchView (window.FindView<T> ());
+ return true;
}
}
+
+ class CurrentFileDiffHandler : CurrentFileViewHandler<IDiffView>
+ {
+ }
- class CurrentFileBlameHandler : FileVersionControlCommandHandler
+ class CurrentFileBlameHandler : CurrentFileViewHandler<IBlameView>
{
- protected override void Run ()
- {
- var window = IdeApp.Workbench.ActiveDocument.Window;
- window.SwitchView (window.FindView<IBlameView> ());
- }
}
- class CurrentFileLogHandler : FileVersionControlCommandHandler
+ class CurrentFileLogHandler : CurrentFileViewHandler<ILogView>
{
- protected override void Run ()
- {
- var window = IdeApp.Workbench.ActiveDocument.Window;
- window.SwitchView (window.FindView<ILogView> ());
- }
}
}
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/CommitDialogExtension.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/CommitDialogExtension.cs
index 6c51bed69f..eb2d119063 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/CommitDialogExtension.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/CommitDialogExtension.cs
@@ -24,6 +24,11 @@ namespace MonoDevelop.VersionControl
return true;
}
+ public virtual string FormatDialogTitle (ChangeSet changeSet, string title)
+ {
+ return null;
+ }
+
public virtual void CommitMessageTextViewHook (Gtk.TextView textView)
{
}
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/DefaultBlameViewHandler.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/DefaultBlameViewHandler.cs
index c899794b45..1259363f52 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/DefaultBlameViewHandler.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/DefaultBlameViewHandler.cs
@@ -35,7 +35,7 @@ namespace MonoDevelop.VersionControl
{
public bool CanHandle (VersionControlItem item, DocumentView primaryView)
{
- return (primaryView == null || primaryView.GetContent <ITextFile> () != null)
+ return (primaryView == null || primaryView.GetContent <MonoDevelop.SourceEditor.SourceEditorView> () != null)
&& item.Repository.GetFileIsText (item.Path);
}
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/IgnoreCommand.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/IgnoreCommand.cs
index b36d523c30..b39bfb8af4 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/IgnoreCommand.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/IgnoreCommand.cs
@@ -81,7 +81,6 @@ namespace MonoDevelop.VersionControl
foreach (VersionControlItemList list in items.SplitByRepository ())
list[0].Repository.Ignore (list.Paths);
- Monitor.ReportSuccess (GettextCatalog.GetString ("Ignore operation completed."));
Gtk.Application.Invoke (delegate {
foreach (VersionControlItem item in items)
if (!item.IsDirectory)
@@ -89,6 +88,7 @@ namespace MonoDevelop.VersionControl
VersionControlService.NotifyFileStatusChanged (items);
});
+ Monitor.ReportSuccess (GettextCatalog.GetString ("Ignore operation completed."));
}
}
}
@@ -144,7 +144,6 @@ namespace MonoDevelop.VersionControl
foreach (VersionControlItemList list in items.SplitByRepository ())
list[0].Repository.Unignore (list.Paths);
- Monitor.ReportSuccess (GettextCatalog.GetString ("Unignore operation completed."));
Gtk.Application.Invoke (delegate {
foreach (VersionControlItem item in items)
if (!item.IsDirectory)
@@ -152,6 +151,7 @@ namespace MonoDevelop.VersionControl
VersionControlService.NotifyFileStatusChanged (items);
});
+ Monitor.ReportSuccess (GettextCatalog.GetString ("Unignore operation completed."));
}
}
}
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/LockCommand.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/LockCommand.cs
index 66507132e4..2e318afdd6 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/LockCommand.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/LockCommand.cs
@@ -60,11 +60,11 @@ namespace MonoDevelop.VersionControl
foreach (VersionControlItemList list in items.SplitByRepository ())
list[0].Repository.Lock (Monitor, list.Paths);
- Monitor.ReportSuccess (GettextCatalog.GetString ("Lock operation completed."));
Gtk.Application.Invoke (delegate {
VersionControlService.NotifyFileStatusChanged (items);
});
+ Monitor.ReportSuccess (GettextCatalog.GetString ("Lock operation completed."));
}
}
}
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/PublishCommand.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/PublishCommand.cs
index 1650087e48..5eca553917 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/PublishCommand.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/PublishCommand.cs
@@ -101,11 +101,10 @@ namespace MonoDevelop.VersionControl
return;
}
- Monitor.ReportSuccess (GettextCatalog.GetString ("Publish operation completed."));
-
Gtk.Application.Invoke (delegate {
VersionControlService.NotifyFileStatusChanged (new FileUpdateEventArgs (vc, path, true));
});
+ Monitor.ReportSuccess (GettextCatalog.GetString ("Publish operation completed."));
}
}
}
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Repository.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Repository.cs
index 5d7c81439b..205c00e128 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Repository.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Repository.cs
@@ -44,7 +44,7 @@ namespace MonoDevelop.VersionControl
VersionControlSystem = vcs;
Repositories.SetValue (Repositories.Count + 1, string.Format ("Repository #{0}", Repositories.Count + 1), new Dictionary<string, string> {
{ "Type", vcs.Name },
- { "Version", vcs.Version },
+ { "Type+Version", string.Format ("{0} {1}", vcs.Name, vcs.Version) },
});
}
@@ -94,9 +94,19 @@ namespace MonoDevelop.VersionControl
if (--references == 0)
Dispose ();
}
-
+
+ internal bool Disposed { get; private set; }
public virtual void Dispose ()
{
+ Disposed = true;
+ if (!queryRunning)
+ return;
+
+ lock (queryLock) {
+ fileQueryQueue.Clear ();
+ directoryQueryQueue.Clear ();
+ recursiveDirectoryQueryQueue.Clear ();
+ }
}
// Display name of the repository
@@ -327,7 +337,7 @@ namespace MonoDevelop.VersionControl
class RecursiveDirectoryInfoQuery : DirectoryInfoQuery
{
- public VersionInfo[] Result;
+ public VersionInfo[] Result = new VersionInfo[0];
public ManualResetEvent ResetEvent;
public int Count;
}
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/RevertCommand.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/RevertCommand.cs
index 8543f3733b..600af23154 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/RevertCommand.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/RevertCommand.cs
@@ -59,7 +59,6 @@ namespace MonoDevelop.VersionControl
foreach (VersionControlItemList list in items.SplitByRepository ())
list[0].Repository.Revert (list.Paths, true, Monitor);
- Monitor.ReportSuccess (GettextCatalog.GetString ("Revert operation completed."));
Gtk.Application.Invoke (delegate {
foreach (VersionControlItem item in items) {
if (!item.IsDirectory) {
@@ -72,6 +71,7 @@ namespace MonoDevelop.VersionControl
}
VersionControlService.NotifyFileStatusChanged (items);
});
+ Monitor.ReportSuccess (GettextCatalog.GetString ("Revert operation completed."));
}
}
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/RevertRevisionsCommands.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/RevertRevisionsCommands.cs
index 6e365cd1d5..dea73b39bf 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/RevertRevisionsCommands.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/RevertRevisionsCommands.cs
@@ -115,7 +115,6 @@ namespace MonoDevelop.VersionControl
if (!(isDir || Directory.Exists (path)))
isDir = false;
- Monitor.ReportSuccess (GettextCatalog.GetString ("Revert operation completed."));
Gtk.Application.Invoke (delegate {
if (!isDir) {
// Reload reverted files
@@ -128,6 +127,7 @@ namespace MonoDevelop.VersionControl
VersionControlService.NotifyFileStatusChanged (new FileUpdateEventArgs (vc, path, true));
}
});
+ Monitor.ReportSuccess (GettextCatalog.GetString ("Revert operation completed."));
}
}
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/UnlockCommand.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/UnlockCommand.cs
index 599e3d56f0..52b57bec2f 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/UnlockCommand.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/UnlockCommand.cs
@@ -62,10 +62,10 @@ namespace MonoDevelop.VersionControl
foreach (VersionControlItemList list in items.SplitByRepository ())
list[0].Repository.Unlock (Monitor, list.Paths);
- Monitor.ReportSuccess (GettextCatalog.GetString ("Unlock operation completed."));
Gtk.Application.Invoke (delegate {
VersionControlService.NotifyFileStatusChanged (items);
});
+ Monitor.ReportSuccess (GettextCatalog.GetString ("Unlock operation completed."));
}
}
}
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/UpdateCommand.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/UpdateCommand.cs
index 6677562bb1..5c4c641fc3 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/UpdateCommand.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/UpdateCommand.cs
@@ -33,10 +33,10 @@ namespace MonoDevelop.VersionControl
foreach (VersionControlItemList list in items.SplitByRepository ()) {
list[0].Repository.Update (list.Paths, true, Monitor);
}
- Monitor.ReportSuccess (GettextCatalog.GetString ("Update operation completed."));
Gtk.Application.Invoke (delegate {
VersionControlService.NotifyFileStatusChanged (items);
});
+ Monitor.ReportSuccess (GettextCatalog.GetString ("Update operation completed."));
}
}
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlItem.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlItem.cs
index 5eea5c18aa..9ee8889509 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlItem.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlItem.cs
@@ -48,10 +48,17 @@ namespace MonoDevelop.VersionControl
get;
private set;
}
-
+
+ Repository repository;
public Repository Repository {
- get;
- private set;
+ get {
+ if (repository != null && repository.Disposed)
+ repository = VersionControlService.GetRepository (WorkspaceObject);
+ return repository;
+ }
+ internal set {
+ repository = value;
+ }
}
public FilePath Path {
diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlService.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlService.cs
index 0ec15babca..1b305bdee5 100644
--- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlService.cs
+++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/VersionControlService.cs
@@ -95,7 +95,15 @@ namespace MonoDevelop.VersionControl
static void OnExtensionChanged (object s, ExtensionNodeEventArgs args)
{
- VersionControlSystem vcs = (VersionControlSystem) args.ExtensionObject;
+ VersionControlSystem vcs;
+
+ try {
+ vcs = (VersionControlSystem) args.ExtensionObject;
+ } catch (Exception e) {
+ LoggingService.LogError ("Failed to initialize VersionControlSystem type.", e);
+ return;
+ }
+
if (args.Change == ExtensionChange.Add) {
handlers.Add (vcs);
try {
@@ -124,9 +132,10 @@ namespace MonoDevelop.VersionControl
switch (status & VersionStatus.LocalChangesMask) {
case VersionStatus.Modified:
- case VersionStatus.ScheduledReplace:
case VersionStatus.ScheduledIgnore:
return overlay_modified;
+ case VersionStatus.ScheduledReplace:
+ return overlay_renamed;
case VersionStatus.Conflicted:
return overlay_conflicted;
case VersionStatus.ScheduledAdd:
@@ -209,26 +218,28 @@ namespace MonoDevelop.VersionControl
return repo;
}
-
+
public static Repository GetRepositoryReference (string path, string id)
{
VersionControlSystem detectedVCS = null;
- FilePath shortestPath = FilePath.Null;
+ FilePath bestMatch = FilePath.Null;
foreach (VersionControlSystem vcs in GetVersionControlSystems ()) {
var newPath = vcs.GetRepositoryPath (path, id);
if (!newPath.IsNullOrEmpty) {
- if (string.IsNullOrEmpty (shortestPath)) {
- shortestPath = newPath;
+ // Check whether we have no match or if a new match is found with a longer path.
+ // TODO: If the repo root is not the same as the repo reference, ask user for input.
+ // TODO: If we have two version control directories in the same place, ask user for input.
+ if (bestMatch.IsNullOrEmpty) {
+ bestMatch = newPath;
detectedVCS = vcs;
- } else if (shortestPath.CompareTo (newPath) <= 0) {
- // They are guaranteed to be on the same path segments, so choose by path length.
- shortestPath = newPath;
+ } else if (bestMatch.CompareTo (newPath) <= 0) {
+ bestMatch = newPath;
detectedVCS = vcs;
}
}
}
- return detectedVCS == null ? null : detectedVCS.GetRepositoryReference (shortestPath, id);
+ return detectedVCS == null ? null : detectedVCS.GetRepositoryReference (bestMatch, id);
}
diff --git a/main/src/addins/VersionControl/Subversion.Win32.Tests/RepositoryTests.cs b/main/src/addins/VersionControl/Subversion.Win32.Tests/RepositoryTests.cs
index 3d93fc42cf..e57d6c0ec5 100644
--- a/main/src/addins/VersionControl/Subversion.Win32.Tests/RepositoryTests.cs
+++ b/main/src/addins/VersionControl/Subversion.Win32.Tests/RepositoryTests.cs
@@ -42,19 +42,10 @@ namespace MonoDevelop.VersionControl.Subversion.Tests
public override void Setup ()
{
RemotePath = new FilePath (FileService.CreateTempDirectory ());
- RemoteUrl = "svn://localhost:3690/repo";
- SvnServe = new Process ();
+ RemoteUrl = "file://" + RemotePath + "/repo";
base.Setup ();
}
- [TearDown]
- public override void TearDown ()
- {
- SvnServe.Kill ();
-
- base.TearDown ();
- }
-
protected override void TestDiff ()
{
string difftext = @"--- testfile (revision 1)
@@ -131,6 +122,11 @@ namespace MonoDevelop.VersionControl.Subversion.Tests
{
return new SubversionRepository (new SvnSharpClient (), url, path);
}
+
+ protected override Repository GetRepo ()
+ {
+ return new SubversionRepository (new SvnSharpClient (), string.Empty, FilePath.Empty);
+ }
}
}
diff --git a/main/src/addins/VersionControl/Subversion.Win32/SvnSharpClient.cs b/main/src/addins/VersionControl/Subversion.Win32/SvnSharpClient.cs
index e15becae6d..009341e6e9 100644
--- a/main/src/addins/VersionControl/Subversion.Win32/SvnSharpClient.cs
+++ b/main/src/addins/VersionControl/Subversion.Win32/SvnSharpClient.cs
@@ -419,6 +419,9 @@ namespace SubversionAddinWindows
public override IEnumerable<VersionInfo> Status (Repository repo, FilePath path, SvnRevision revision, bool descendDirs, bool changedItemsOnly, bool remoteStatus)
{
+ if (path == FilePath.Null)
+ throw new ArgumentNullException ();
+
var list = new List<VersionInfo> ();
var args = new SvnStatusArgs {
Revision = GetRevision (revision),
@@ -430,12 +433,14 @@ namespace SubversionAddinWindows
try {
client.Status (path, args, (o, a) => list.Add (CreateVersionInfo (repo, a)));
} catch (SvnInvalidNodeKindException e) {
- if (e.SvnErrorCode == SvnErrorCode.SVN_ERR_WC_NOT_WORKING_COPY)
- list.Add (VersionInfo.CreateUnversioned (e.File, true));
- else if (e.SvnErrorCode == SvnErrorCode.SVN_ERR_WC_NOT_FILE)
- list.Add (VersionInfo.CreateUnversioned (e.File, false));
- else
- throw;
+ if (!string.IsNullOrEmpty (e.File)) {
+ if (e.SvnErrorCode == SvnErrorCode.SVN_ERR_WC_NOT_WORKING_COPY)
+ list.Add (VersionInfo.CreateUnversioned (e.File, true));
+ else if (e.SvnErrorCode == SvnErrorCode.SVN_ERR_WC_NOT_FILE)
+ list.Add (VersionInfo.CreateUnversioned (e.File, false));
+ else
+ throw;
+ }
} catch (SvnWorkingCopyPathNotFoundException e) {
list.Add (VersionInfo.CreateUnversioned (e.File, Directory.Exists (e.File)));
}
diff --git a/main/src/addins/VersionControl/Subversion.Win32/VersionControl.Subversion.Win32.csproj b/main/src/addins/VersionControl/Subversion.Win32/VersionControl.Subversion.Win32.csproj
index 644f6ff136..1488859c6f 100644
--- a/main/src/addins/VersionControl/Subversion.Win32/VersionControl.Subversion.Win32.csproj
+++ b/main/src/addins/VersionControl/Subversion.Win32/VersionControl.Subversion.Win32.csproj
@@ -60,10 +60,10 @@
<ItemGroup>
<Reference Include="System" />
<Reference Include="SharpSvn">
- <HintPath>..\..\..\..\packages\SharpSvn.1.8-x86.1.8013.3576.94\lib\net40\SharpSvn.dll</HintPath>
+ <HintPath>..\..\..\..\packages\SharpSvn.1.8-x86.1.8013.3694.107\lib\net40\SharpSvn.dll</HintPath>
</Reference>
<Reference Include="SharpSvn.UI">
- <HintPath>..\..\..\..\packages\SharpSvn.1.8-x86.1.8013.3576.94\lib\net40\SharpSvn.UI.dll</HintPath>
+ <HintPath>..\..\..\..\packages\SharpSvn.1.8-x86.1.8013.3694.107\lib\net40\SharpSvn.UI.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
@@ -127,11 +127,11 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
- <None Include="..\..\..\..\packages\SharpSvn.1.8-x86.1.8013.3576.94\lib\net40\SharpPlink-Win32.svnExe">
+ <None Include="..\..\..\..\packages\SharpSvn.1.8-x86.1.8013.3694.107\lib\net40\SharpPlink-Win32.svnExe">
<Link>SharpPlink-Win32.svnExe</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
- <None Include="..\..\..\..\packages\SharpSvn.1.8-x86.1.8013.3576.94\lib\net40\SharpSvn-DB44-20-win32.svnDll">
+ <None Include="..\..\..\..\packages\SharpSvn.1.8-x86.1.8013.3694.107\lib\net40\SharpSvn-DB44-20-win32.svnDll">
<Link>SharpSvn-DB44-20-win32.svnDll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
diff --git a/main/src/addins/VersionControl/Subversion.Win32/packages.config b/main/src/addins/VersionControl/Subversion.Win32/packages.config
index 825e3d922d..a4956b6c07 100644
--- a/main/src/addins/VersionControl/Subversion.Win32/packages.config
+++ b/main/src/addins/VersionControl/Subversion.Win32/packages.config
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="SharpSvn.1.8-x86" version="1.8013.3576.94" targetFramework="net45" />
+ <package id="SharpSvn.1.8-x86" version="1.8013.3694.107" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/main/src/addins/WindowsPlatform/WindowsPlatform/AddinInfo.cs b/main/src/addins/WindowsPlatform/WindowsPlatform/AddinInfo.cs
index 5e380e8435..5c76772ae5 100644
--- a/main/src/addins/WindowsPlatform/WindowsPlatform/AddinInfo.cs
+++ b/main/src/addins/WindowsPlatform/WindowsPlatform/AddinInfo.cs
@@ -1,9 +1,11 @@
using Mono.Addins;
+using Mono.Addins.Description;
[assembly:Addin ("WindowsPlatform",
Namespace = "MonoDevelop",
Version = MonoDevelop.BuildInfo.Version,
+ Flags = AddinFlags.Hidden,
Category = "Platform Support")]
[assembly:AddinName ("MonoDevelop Windows Platform Support")]
diff --git a/main/src/addins/WindowsPlatform/WindowsPlatform/Dialogs/CommonFileDialogExtensions.cs b/main/src/addins/WindowsPlatform/WindowsPlatform/Dialogs/CommonFileDialogExtensions.cs
index 8f3ad07d78..c12413887f 100644
--- a/main/src/addins/WindowsPlatform/WindowsPlatform/Dialogs/CommonFileDialogExtensions.cs
+++ b/main/src/addins/WindowsPlatform/WindowsPlatform/Dialogs/CommonFileDialogExtensions.cs
@@ -50,12 +50,12 @@ namespace MonoDevelop.Platform
dialog.Title = data.Title;
dialog.InitialDirectory = data.CurrentFolder;
+ dialog.ShowHiddenItems = data.ShowHidden;
var fileDialog = dialog as CommonOpenFileDialog;
if (fileDialog != null) {
fileDialog.Multiselect = data.SelectMultiple;
- fileDialog.ShowHiddenItems = data.ShowHidden;
- if (data.Action == FileChooserAction.SelectFolder) {
+ if (data.Action == SelectFileDialogAction.SelectFolder) {
fileDialog.IsFolderPicker = true;
return;
}
@@ -86,7 +86,7 @@ namespace MonoDevelop.Platform
return;
// FileDialog doesn't show the file extension when saving a file,
// so we try to look for the precise filter if none was specified.
- if (!string.IsNullOrEmpty (data.InitialFileName) && data.Action == FileChooserAction.Save && defExt == "*") {
+ if (!string.IsNullOrEmpty (data.InitialFileName) && data.Action == SelectFileDialogAction.Save && defExt == "*") {
string ext = Path.GetExtension (data.InitialFileName);
if (!string.IsNullOrEmpty (ext)) {
var pattern = "*" + ext;
diff --git a/main/src/addins/WindowsPlatform/WindowsPlatform/Dialogs/OpenFileDialogHandler.cs b/main/src/addins/WindowsPlatform/WindowsPlatform/Dialogs/OpenFileDialogHandler.cs
index 51e84a743f..c0a1619d9f 100644
--- a/main/src/addins/WindowsPlatform/WindowsPlatform/Dialogs/OpenFileDialogHandler.cs
+++ b/main/src/addins/WindowsPlatform/WindowsPlatform/Dialogs/OpenFileDialogHandler.cs
@@ -35,6 +35,7 @@ using System.Text;
using Microsoft.WindowsAPICodePack.Dialogs;
using Microsoft.WindowsAPICodePack.Dialogs.Controls;
using MonoDevelop.Core;
+using MonoDevelop.Components.Extensions;
using MonoDevelop.Ide;
using MonoDevelop.Ide.Extensions;
using MonoDevelop.Ide.Gui;
@@ -51,7 +52,7 @@ namespace MonoDevelop.Platform
{
var parent = data.TransientFor ?? MessageService.RootWindow;
CommonFileDialog dialog;
- if (data.Action == FileChooserAction.Open) {
+ if (data.Action == SelectFileDialogAction.Open) {
dialog = new CustomCommonOpenFileDialog {
EnsureFileExists = true
};
@@ -65,7 +66,7 @@ namespace MonoDevelop.Platform
var group = new CommonFileDialogGroupBox ("encoding", "Encoding:");
encodingCombo = new CustomCommonFileDialogComboBox ();
- BuildEncodingsCombo (encodingCombo, data.Action != FileChooserAction.Save, data.Encoding);
+ BuildEncodingsCombo (encodingCombo, data.Action != SelectFileDialogAction.Save, data.Encoding);
group.Items.Add (encodingCombo);
dialog.Controls.Add (group);
@@ -77,7 +78,7 @@ namespace MonoDevelop.Platform
SizeToContent = SizeToContent.WidthAndHeight
};
if (dlg.ShowDialog ().Value) {
- BuildEncodingsCombo (encodingCombo, data.Action != FileChooserAction.Save, data.Encoding);
+ BuildEncodingsCombo (encodingCombo, data.Action != SelectFileDialogAction.Save, data.Encoding);
dialog.ApplyControlPropertyChange ("Items", encodingCombo);
}
}
@@ -86,7 +87,7 @@ namespace MonoDevelop.Platform
CustomCommonFileDialogComboBox viewerCombo = null;
CommonFileDialogCheckBox closeSolution = null;
- if (data.ShowViewerSelector && data.Action == FileChooserAction.Open) {
+ if (data.ShowViewerSelector && data.Action == SelectFileDialogAction.Open) {
var group = new CommonFileDialogGroupBox ("openWith", "Open with:");
viewerCombo = new CustomCommonFileDialogComboBox {
diff --git a/main/src/addins/WindowsPlatform/WindowsPlatform/Dialogs/SelectFileDialogHandler.cs b/main/src/addins/WindowsPlatform/WindowsPlatform/Dialogs/SelectFileDialogHandler.cs
index ec5123aded..bcd6b36049 100644
--- a/main/src/addins/WindowsPlatform/WindowsPlatform/Dialogs/SelectFileDialogHandler.cs
+++ b/main/src/addins/WindowsPlatform/WindowsPlatform/Dialogs/SelectFileDialogHandler.cs
@@ -44,7 +44,7 @@ namespace MonoDevelop.Platform
var parent = data.TransientFor ?? MessageService.RootWindow;
CommonFileDialog dialog;
- if (data.Action == FileChooserAction.Open || data.Action == FileChooserAction.SelectFolder)
+ if ((data.Action & (SelectFileDialogAction.Open | SelectFileDialogAction.SelectFolder)) != 0)
dialog = new CustomCommonOpenFileDialog ();
else
dialog = new CommonSaveFileDialog ();
diff --git a/main/src/addins/WindowsPlatform/WindowsPlatform/JumpList.cs b/main/src/addins/WindowsPlatform/WindowsPlatform/JumpList.cs
index aaf01a6545..67ec27e51e 100644
--- a/main/src/addins/WindowsPlatform/WindowsPlatform/JumpList.cs
+++ b/main/src/addins/WindowsPlatform/WindowsPlatform/JumpList.cs
@@ -74,7 +74,10 @@ namespace MonoDevelop.Platform
private void UpdateJumpList ()
{
- Taskbar.JumpList jumplist = Taskbar.JumpList.CreateJumpList ();
+ Taskbar.JumpList jumplist = Taskbar.JumpList.CreateJumpListForIndividualWindow (
+ MonoDevelop.Core.BrandingService.ApplicationName,
+ GdkWin32.HgdiobjGet (MessageService.RootWindow.GdkWindow)
+ );
jumplist.KnownCategoryToDisplay = Taskbar.JumpListKnownCategoryType.Neither;
Taskbar.JumpListCustomCategory recentProjectsCategory = new Taskbar.JumpListCustomCategory ("Recent Solutions");
@@ -88,27 +91,34 @@ namespace MonoDevelop.Platform
// has been registered as supported in the registry can be added.
bool isSupportedFileExtension = this.supportedExtensions.Contains (Path.GetExtension (recentProject.FileName));
if (isSupportedFileExtension) {
- recentProjectsCategory.AddJumpListItems (new Taskbar.JumpListItem (recentProject.FileName));
+ recentProjectsCategory.AddJumpListItems (new Taskbar.JumpListLink (exePath, recentProject.DisplayName) {
+ Arguments = MonoDevelop.Core.Execution.ProcessArgumentBuilder.Quote (recentProject.FileName),
+ IconReference = new Microsoft.WindowsAPICodePack.Shell.IconReference (exePath, 0),
+ });
}
}
foreach (RecentFile recentFile in recentFiles.GetFiles ()) {
if (this.supportedExtensions.Contains (Path.GetExtension (recentFile.FileName)))
- recentFilesCategory.AddJumpListItems (new Taskbar.JumpListItem (recentFile.FileName));
+ recentFilesCategory.AddJumpListItems (new Taskbar.JumpListLink (exePath, recentFile.DisplayName) {
+ Arguments = MonoDevelop.Core.Execution.ProcessArgumentBuilder.Quote (recentFile.FileName),
+ IconReference = new Microsoft.WindowsAPICodePack.Shell.IconReference (exePath, 0),
+ });
}
jumplist.Refresh ();
}
+ string exePath;
private bool Initialize ()
{
this.supportedExtensions = new List<string> ();
// Determine the correct value for /HKCR/XamarinStudio/shell/Open/Command
ProcessModule monoDevelopAssembly = Process.GetCurrentProcess ().MainModule;
- string exePath = monoDevelopAssembly.FileName;
+ exePath = monoDevelopAssembly.FileName;
string executeString = exePath + " %1";
- string progId = Taskbar.TaskbarManager.Instance.ApplicationId;
+ string progId = MonoDevelop.Core.BrandingService.ProfileDirectoryName;
using (RegistryKey progIdKey = Registry.ClassesRoot.OpenSubKey (progId + @"\shell\Open\Command", false)) {
if (progIdKey == null) {
diff --git a/main/src/addins/WindowsPlatform/WindowsPlatform/WindowsPlatform.cs b/main/src/addins/WindowsPlatform/WindowsPlatform/WindowsPlatform.cs
index 67f98ad070..554cf2cf0b 100644
--- a/main/src/addins/WindowsPlatform/WindowsPlatform/WindowsPlatform.cs
+++ b/main/src/addins/WindowsPlatform/WindowsPlatform/WindowsPlatform.cs
@@ -64,11 +64,11 @@ namespace MonoDevelop.Platform
get { return "Windows"; }
}
- public override void Initialize ()
+ internal override void SetMainWindowDecorations (Gtk.Window window)
{
// Only initialize elements for Win7+.
if (TaskbarManager.IsPlatformSupported) {
- TaskbarManager.Instance.ApplicationId = BrandingService.ProfileDirectoryName;
+ TaskbarManager.Instance.SetApplicationIdForSpecificWindow (GdkWin32.HgdiobjGet (window.GdkWindow), BrandingService.ApplicationName);
}
}
diff --git a/main/src/addins/WindowsPlatform/WindowsPlatform/WindowsPlatform.csproj b/main/src/addins/WindowsPlatform/WindowsPlatform/WindowsPlatform.csproj
index 2a4612a1f0..0f19949e44 100644
--- a/main/src/addins/WindowsPlatform/WindowsPlatform/WindowsPlatform.csproj
+++ b/main/src/addins/WindowsPlatform/WindowsPlatform/WindowsPlatform.csproj
@@ -32,7 +32,7 @@
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<DebugSymbols>true</DebugSymbols>
<NoWarn>1591;1573</NoWarn>
- <DocumentationFile>..\..\..\build\AddIns\WindowsPlatform.xml</DocumentationFile>
+ <DocumentationFile>..\..\..\..\build\AddIns\WindowsPlatform\WindowsPlatform.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
diff --git a/main/src/addins/Xml/Properties/MonoDevelop.XmlEditor.addin.xml b/main/src/addins/Xml/Properties/MonoDevelop.XmlEditor.addin.xml
index 632f38711b..d2da8c8f7e 100644
--- a/main/src/addins/Xml/Properties/MonoDevelop.XmlEditor.addin.xml
+++ b/main/src/addins/Xml/Properties/MonoDevelop.XmlEditor.addin.xml
@@ -23,6 +23,7 @@
<Extension path = "/MonoDevelop/Xml/Editor/XmlFileAssociations">
<Association extension = ".build" namespaceUri="http://nant.sf.net/release/0.85-rc3/nant.xsd" />
<Association extension = ".config" namespaceUri="urn:app-config" />
+ <Association extension = ".manifest" namespaceUri="schemas-microsoft-com:asm.v1" />
<Association extension = ".xsd" namespaceUri="http://www.w3.org/2001/XMLSchema" namespacePrefix="xs" />
<Association extension = ".xsl" namespaceUri="http://www.w3.org/1999/XSL/Transform" namespacePrefix="xsl" />
<Association extension = ".xslt" namespaceUri="http://www.w3.org/1999/XSL/Transform" namespacePrefix="xsl" />
diff --git a/main/src/addins/Xml/Tests/MonoDevelop.Xml.Tests.csproj b/main/src/addins/Xml/Tests/MonoDevelop.Xml.Tests.csproj
index 19cc5c4b38..f218032b4d 100644
--- a/main/src/addins/Xml/Tests/MonoDevelop.Xml.Tests.csproj
+++ b/main/src/addins/Xml/Tests/MonoDevelop.Xml.Tests.csproj
@@ -39,6 +39,7 @@
</Execution>
<DebugSymbols>true</DebugSymbols>
<NoWarn>1591;1573</NoWarn>
+ <DefineConstants>TRACE</DefineConstants>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\core\MonoDevelop.Core\MonoDevelop.Core.csproj">
diff --git a/main/src/core/Mono.Texteditor/Mono.TextEditor.Highlighting/SemanticRule.cs b/main/src/core/Mono.Texteditor/Mono.TextEditor.Highlighting/SemanticRule.cs
index 0c8964a43d..6fb63701a5 100644
--- a/main/src/core/Mono.Texteditor/Mono.TextEditor.Highlighting/SemanticRule.cs
+++ b/main/src/core/Mono.Texteditor/Mono.TextEditor.Highlighting/SemanticRule.cs
@@ -56,6 +56,8 @@ namespace Mono.TextEditor
{
if (endOffset <= startOffset || startOffset >= doc.TextLength || inUpdate)
return;
+ if (startChunk.Style != "Comment(Line)" && startChunk.Style != "Comment(Block)")
+ return;
inUpdate = true;
try {
string text = doc.GetTextAt (startOffset, System.Math.Min (endOffset, doc.TextLength) - startOffset);
diff --git a/main/src/core/Mono.Texteditor/Mono.TextEditor.Highlighting/SyntaxModeService.cs b/main/src/core/Mono.Texteditor/Mono.TextEditor.Highlighting/SyntaxModeService.cs
index 2c36b575ca..0b74632ea2 100644
--- a/main/src/core/Mono.Texteditor/Mono.TextEditor.Highlighting/SyntaxModeService.cs
+++ b/main/src/core/Mono.Texteditor/Mono.TextEditor.Highlighting/SyntaxModeService.cs
@@ -92,13 +92,24 @@ namespace Mono.TextEditor.Highlighting
return styleLookup[style.Name];
return null;
}
-
+
+ public static string GetFileName (string name)
+ {
+ if (!styleLookup.ContainsKey (name))
+ throw new System.ArgumentException ("Style " + name + " not found", "name");
+ var provider = styleLookup [name];
+ if (provider is UrlStreamProvider) {
+ var usp = provider as UrlStreamProvider;
+ return usp.Url;
+ }
+ return null;
+ }
+
static void LoadStyle (string name)
{
if (!styleLookup.ContainsKey (name))
throw new System.ArgumentException ("Style " + name + " not found", "name");
var provider = styleLookup [name];
- styleLookup.Remove (name);
var stream = provider.Open ();
try {
if (provider is UrlStreamProvider) {
@@ -112,6 +123,7 @@ namespace Mono.TextEditor.Highlighting
} else {
styles [name] = ColorScheme.LoadFrom (stream);
}
+ styleLookup.Remove (name);
} catch (Exception e) {
throw new IOException ("Error while loading style :" + name, e);
} finally {
diff --git a/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/TextDocument.cs b/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/TextDocument.cs
index f69c94d427..a60ae490f5 100644
--- a/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/TextDocument.cs
+++ b/main/src/core/Mono.Texteditor/Mono.TextEditor/Document/TextDocument.cs
@@ -815,6 +815,7 @@ namespace Mono.TextEditor
operation.Undo (this);
isInUndo = false;
OnUndone (new UndoOperationEventArgs (operation));
+ CommitDocumentUpdate ();
}
public void RollbackTo (ICSharpCode.NRefactory.Editor.ITextSourceVersion version)
@@ -861,6 +862,7 @@ namespace Mono.TextEditor
operation.Redo (this);
isInUndo = false;
OnRedone (new UndoOperationEventArgs (operation));
+ CommitDocumentUpdate ();
}
internal protected virtual void OnRedone (UndoOperationEventArgs e)
diff --git a/main/src/core/Mono.Texteditor/Mono.TextEditor/Gui/GtkWorkarounds.cs b/main/src/core/Mono.Texteditor/Mono.TextEditor/Gui/GtkWorkarounds.cs
index 73fdfd2306..43bfd4e04b 100644
--- a/main/src/core/Mono.Texteditor/Mono.TextEditor/Gui/GtkWorkarounds.cs
+++ b/main/src/core/Mono.Texteditor/Mono.TextEditor/Gui/GtkWorkarounds.cs
@@ -489,13 +489,32 @@ namespace Mono.TextEditor
public static void ShowContextMenu (Gtk.Menu menu, Gtk.Widget parent, Gdk.EventButton evt, Gdk.Rectangle caret)
{
int x, y;
- var window = evt.Window;
+ uint time, button;
+
+ var window = evt != null ? evt.Window : parent.GdkWindow;
+
+ if (window == null)
+ return;
window.GetOrigin (out x, out y);
- x += (int)evt.X;
- y += (int)evt.Y;
- ShowContextMenuInternal (menu, parent, x, y, caret, window, evt.Time, evt.Button);
+ if (evt == null) {
+ evt = Global.CurrentEvent as Gdk.EventButton;
+ }
+
+ if (evt != null) {
+ button = evt.Button;
+ time = evt.Time;
+ x += (int)evt.X;
+ y += (int)evt.Y;
+ } else {
+ button = 3;
+ time = 0;
+ x += caret.X;
+ y += caret.Y;
+ }
+
+ ShowContextMenuInternal (menu, parent, x, y, caret, window, time, button);
}
public static void ShowContextMenu (Gtk.Menu menu, Gtk.Widget parent, int ix, int iy, Gdk.Rectangle caret)
@@ -1023,7 +1042,7 @@ namespace Mono.TextEditor
}
}
- static bool canSetOverlayScrollbarPolicy = true;
+ static bool canSetOverlayScrollbarPolicy = Platform.IsMac;
[DllImport (PangoUtil.LIBQUARTZ)]
static extern void gtk_scrolled_window_set_overlay_policy (IntPtr sw, Gtk.PolicyType hpolicy, Gtk.PolicyType vpolicy);
@@ -1190,6 +1209,13 @@ namespace Mono.TextEditor
else
return 1d;
}
+
+ public static int ConvertToPixelScale (int size)
+ {
+ double scale = GetPixelScale ();
+
+ return (int)(size * scale);
+ }
public static Gdk.Pixbuf RenderIcon (this Gtk.IconSet iconset, Gtk.Style style, Gtk.TextDirection direction, Gtk.StateType state, Gtk.IconSize size, Gtk.Widget widget, string detail, double scale)
{
diff --git a/main/src/core/Mono.Texteditor/Mono.TextEditor/Gui/TextArea.cs b/main/src/core/Mono.Texteditor/Mono.TextEditor/Gui/TextArea.cs
index f7fcf64ee9..7795463769 100644
--- a/main/src/core/Mono.Texteditor/Mono.TextEditor/Gui/TextArea.cs
+++ b/main/src/core/Mono.Texteditor/Mono.TextEditor/Gui/TextArea.cs
@@ -376,12 +376,6 @@ namespace Mono.TextEditor
#if ATK
TextEditorAccessible.Factory.Init (this);
#endif
-
- if (GtkGestures.IsSupported) {
- this.AddGestureMagnifyHandler ((sender, args) => {
- Options.Zoom += Options.Zoom * (args.Magnification / 4d);
- });
- }
OptionsChanged (this, EventArgs.Empty);
}
@@ -1297,13 +1291,9 @@ namespace Mono.TextEditor
scrollWindowTimer_mod = mod;
if (scrollWindowTimer == 0) {
scrollWindowTimer = GLib.Timeout.Add (50, delegate {
- //'If' below shouldn't be needed, but after reproducing bug with FireMotionEvent being called
- //when it shouldn't and attaching with debugger it turned out that it's called from here
- //even when scrollWindowTimer was 0, looks like GLib bug
- if (scrollWindowTimer == 0) {
- return false;
+ if (HasFocus) {
+ FireMotionEvent (scrollWindowTimer_x, scrollWindowTimer_y, scrollWindowTimer_mod);
}
- FireMotionEvent (scrollWindowTimer_x, scrollWindowTimer_y, scrollWindowTimer_mod);
return true;
});
}
diff --git a/main/src/core/Mono.Texteditor/Mono.TextEditor/Gui/TextViewMargin.cs b/main/src/core/Mono.Texteditor/Mono.TextEditor/Gui/TextViewMargin.cs
index c055338beb..b3dafffb02 100644
--- a/main/src/core/Mono.Texteditor/Mono.TextEditor/Gui/TextViewMargin.cs
+++ b/main/src/core/Mono.Texteditor/Mono.TextEditor/Gui/TextViewMargin.cs
@@ -476,7 +476,9 @@ namespace Mono.TextEditor
protected internal override void OptionsChanged ()
{
DisposeGCs ();
-
+ selectionColor = null;
+ currentLineColor = null;
+
var markerFont = textEditor.Options.Font.Copy ();
markerFont.Size = markerFont.Size * 8 / 10;
markerLayout.FontDescription = markerFont;
diff --git a/main/src/core/Mono.Texteditor/Mono.TextEditor/Platform.cs b/main/src/core/Mono.Texteditor/Mono.TextEditor/Platform.cs
index ec2f51e5ee..ec2f51e5ee 100755..100644
--- a/main/src/core/Mono.Texteditor/Mono.TextEditor/Platform.cs
+++ b/main/src/core/Mono.Texteditor/Mono.TextEditor/Platform.cs
diff --git a/main/src/core/Mono.Texteditor/Mono.TextEditor/SimpleEditMode.cs b/main/src/core/Mono.Texteditor/Mono.TextEditor/SimpleEditMode.cs
index 4f832f4456..824011e8a4 100644
--- a/main/src/core/Mono.Texteditor/Mono.TextEditor/SimpleEditMode.cs
+++ b/main/src/core/Mono.Texteditor/Mono.TextEditor/SimpleEditMode.cs
@@ -392,7 +392,9 @@ namespace Mono.TextEditor
keyBindings.Add (GetKeyCode (Gdk.Key.f, Gdk.ModifierType.ControlMask), CaretMoveActions.Right);
keyBindings.Add (GetKeyCode (Gdk.Key.b, Gdk.ModifierType.ControlMask), CaretMoveActions.Left);
keyBindings.Add (GetKeyCode (Gdk.Key.p, Gdk.ModifierType.ControlMask), CaretMoveActions.Up);
+ keyBindings.Add (GetKeyCode (Gdk.Key.p, Gdk.ModifierType.ControlMask | Gdk.ModifierType.ShiftMask), SelectionActions.MoveUp);
keyBindings.Add (GetKeyCode (Gdk.Key.n, Gdk.ModifierType.ControlMask), CaretMoveActions.Down);
+ keyBindings.Add (GetKeyCode (Gdk.Key.n, Gdk.ModifierType.ControlMask | Gdk.ModifierType.ShiftMask), SelectionActions.MoveDown);
keyBindings.Add (GetKeyCode (Gdk.Key.h, Gdk.ModifierType.ControlMask), DeleteActions.Backspace);
keyBindings.Add (GetKeyCode (Gdk.Key.d, Gdk.ModifierType.ControlMask), DeleteActions.Delete);
keyBindings.Add (GetKeyCode (Gdk.Key.o, Gdk.ModifierType.ControlMask), MiscActions.InsertNewLinePreserveCaretPosition);
diff --git a/main/src/core/Mono.Texteditor/SyntaxModes/XmlSyntaxMode.xml b/main/src/core/Mono.Texteditor/SyntaxModes/XmlSyntaxMode.xml
index 5b778909d5..ea169d2554 100644
--- a/main/src/core/Mono.Texteditor/SyntaxModes/XmlSyntaxMode.xml
+++ b/main/src/core/Mono.Texteditor/SyntaxModes/XmlSyntaxMode.xml
@@ -34,9 +34,8 @@
<End>--&gt;</End>
</Span>
- <Span color = "Xml Attribute" rule = "Comment">
- <Begin>&amp;</Begin>
-
+ <Span color = "Preprocessor" rule = "Comment">
+ <Begin>&amp;</Begin>
<End>;</End>
</Span>
@@ -62,14 +61,10 @@
</Span>
<Rule name = "Comment">
- <Span color = "Preprocessor">
- <Begin>&amp;</Begin>
- <End>;</End>
- </Span>
</Rule>
<Rule name = "InDocType" color = "Html Attribute Name" >
- <Span color = "Xml Attribute">
+ <Span color = "Preprocessor">
<Begin>&amp;</Begin>
<End>;</End>
</Span>
@@ -79,7 +74,7 @@
</Rule>
<Rule name = "InTag">
- <Span color = "Xml Attribute">
+ <Span color = "Preprocessor">
<Begin>&amp;</Begin>
<End>;</End>
</Span>
@@ -108,7 +103,7 @@
</Rule>
<Rule name = "InLiteral">
- <Span color = "Xml Attribute">
+ <Span color = "Preprocessor">
<Begin>&amp;</Begin>
<End>;</End>
</Span>
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Assemblies/MonoTargetRuntime.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Assemblies/MonoTargetRuntime.cs
index 837dac0d7a..84fc117ddc 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Assemblies/MonoTargetRuntime.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Assemblies/MonoTargetRuntime.cs
@@ -241,7 +241,10 @@ namespace MonoDevelop.Core.Assemblies
return;
foreach (string pcfile in GetAllPkgConfigFiles ()) {
try {
- ParsePCFile (new FilePath (pcfile).ResolveLinks ());
+ var pc = new FilePath (pcfile).ResolveLinks ();
+ if (!string.IsNullOrEmpty (pc))
+ ParsePCFile (pc);
+
if (ShuttingDown)
return;
}
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Instrumentation/TimeCounter.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Instrumentation/TimeCounter.cs
index 55227a859f..051e80845e 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Instrumentation/TimeCounter.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Instrumentation/TimeCounter.cs
@@ -26,6 +26,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
namespace MonoDevelop.Core.Instrumentation
{
@@ -52,7 +53,7 @@ namespace MonoDevelop.Core.Instrumentation
class TimeCounter: ITimeTracker
{
- DateTime begin;
+ Stopwatch stopWatch = new Stopwatch ();
TimerTraceList traceList;
TimerTrace lastTrace;
TimerCounter counter;
@@ -97,16 +98,18 @@ namespace MonoDevelop.Core.Instrumentation
internal void Begin ()
{
- begin = DateTime.Now;
+ stopWatch.Start ();
}
public void End ()
{
- if (counter == null) {
+ if (!stopWatch.IsRunning) {
Console.WriteLine ("Timer already finished");
return;
}
- traceList.TotalTime = DateTime.Now - begin;
+
+ stopWatch.Stop ();
+ traceList.TotalTime = TimeSpan.FromMilliseconds (stopWatch.ElapsedMilliseconds);
if (traceList.TotalTime.TotalSeconds < counter.MinSeconds)
counter.RemoveValue (traceList.ValueIndex);
else
@@ -118,7 +121,7 @@ namespace MonoDevelop.Core.Instrumentation
t.Dispose ();
} else if (linkedTrackers != null)
((IDisposable)linkedTrackers).Dispose ();
-
+ stopWatch.Reset ();
}
void IDisposable.Dispose ()
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Logging/FileLogger.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Logging/FileLogger.cs
index 317c9134ba..3d39961f7b 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Logging/FileLogger.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.Logging/FileLogger.cs
@@ -45,7 +45,9 @@ namespace MonoDevelop.Core.Logging
public FileLogger (string filename, bool append)
{
- writer = new StreamWriter (filename, append);
+ writer = new StreamWriter (filename, append) {
+ AutoFlush = true
+ };
name = filename;
}
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/ConsoleProgressMonitor.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/ConsoleProgressMonitor.cs
index 82410eae20..90cecfdb54 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/ConsoleProgressMonitor.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core.ProgressMonitoring/ConsoleProgressMonitor.cs
@@ -51,15 +51,12 @@ namespace MonoDevelop.Core.ProgressMonitoring
public ConsoleProgressMonitor () : this (Console.Out, true)
{
//TODO: can we efficiently update Console.WindowWidth when it changes?
- // TODO: Use Console.IsOutputRedirected in .NET 4.5.
- try {
- columns = Console.WindowWidth;
- }
//when the output is redirected, Mono returns 0 but .NET throws IOException
- catch (IOException) {
+ if (Console.IsOutputRedirected)
columns = 0;
- }
-
+ else
+ columns = Console.WindowWidth;
+
wrap = columns > 0;
}
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/FilePath.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/FilePath.cs
index 893ca1d520..d93a7257d6 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/FilePath.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/FilePath.cs
@@ -69,13 +69,13 @@ namespace MonoDevelop.Core
const int PATHMAX = 4096 + 1;
- static readonly char[] invalidPathChars = Path.GetInvalidPathChars ().Concat ("#%&").ToArray ();
+ static readonly char[] invalidPathChars = Path.GetInvalidPathChars ().Concat ("#%").ToArray ();
public static char[] GetInvalidPathChars()
{
return (char[])invalidPathChars.Clone();
}
- static readonly char[] invalidFileNameChars = Path.GetInvalidFileNameChars ().Concat ("#%&").ToArray ();
+ static readonly char[] invalidFileNameChars = Path.GetInvalidFileNameChars ().Concat ("#%").ToArray ();
public static char[] GetInvalidFileNameChars ()
{
return (char[])invalidFileNameChars.Clone ();
@@ -123,10 +123,12 @@ namespace MonoDevelop.Core
if (string.IsNullOrEmpty (fileName))
return FilePath.Empty;
string fp = Path.GetFullPath (fileName);
- if (fp.Length > 0 && fp [fp.Length - 1] == Path.DirectorySeparatorChar)
- return fp.TrimEnd (Path.DirectorySeparatorChar);
- if (fp.Length > 0 && fp [fp.Length - 1] == Path.AltDirectorySeparatorChar)
- return fp.TrimEnd (Path.AltDirectorySeparatorChar);
+ if (fp.Length > 0) {
+ if (fp [fp.Length - 1] == Path.DirectorySeparatorChar)
+ return fp.TrimEnd (Path.DirectorySeparatorChar);
+ if (fp [fp.Length - 1] == Path.AltDirectorySeparatorChar)
+ return fp.TrimEnd (Path.AltDirectorySeparatorChar);
+ }
return fp;
}
}
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/Gettext.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/Gettext.cs
index a3444fa3e4..db19326ea8 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/Gettext.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/Gettext.cs
@@ -43,6 +43,8 @@ namespace MonoDevelop.Core
[DllImport ("kernel32.dll", SetLastError = true)]
static extern int SetThreadUILanguage (int LangId);
+ const int LOCALE_CUSTOM_UNSPECIFIED = 4096;
+
static GettextCatalog ()
{
mainThread = Thread.CurrentThread;
@@ -59,7 +61,7 @@ namespace MonoDevelop.Core
if (ci.IsNeutralCulture) {
// We need a non-neutral culture
foreach (CultureInfo c in CultureInfo.GetCultures (CultureTypes.AllCultures & ~CultureTypes.NeutralCultures))
- if (c.Parent != null && c.Parent.Name == ci.Name) {
+ if (c.Parent != null && c.Parent.Name == ci.Name && c.LCID != LOCALE_CUSTOM_UNSPECIFIED) {
ci = c;
break;
}
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/LoggingService.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/LoggingService.cs
index b2c15f9a0e..bda363cc1d 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/LoggingService.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/LoggingService.cs
@@ -36,6 +36,7 @@ using Mono.Addins;
using MonoDevelop.Core.LogReporting;
using MonoDevelop.Core.Logging;
using Mono.Unix.Native;
+using System.Text;
namespace MonoDevelop.Core
{
@@ -492,20 +493,39 @@ namespace MonoDevelop.Core
#endregion
#region convenience methods (string message, Exception ex)
-
+
+ static string FormatExceptionText (string message, Exception ex)
+ {
+ if (ex == null)
+ return message;
+
+ var exceptionText = new StringBuilder ();
+ exceptionText.AppendLine (message);
+ exceptionText.Append (ex);
+ if (ex.Data.Count > 0) {
+ exceptionText.AppendLine ();
+ exceptionText.Append ("Exception Data:");
+ foreach (DictionaryEntry item in ex.Data) {
+ exceptionText.AppendLine ();
+ exceptionText.AppendFormat ("{0}: {1}", item.Key, item.Value);
+ }
+ }
+ return exceptionText.ToString ();
+ }
+
public static void LogDebug (string message, Exception ex)
{
- Log (LogLevel.Debug, message + (ex != null? Environment.NewLine + ex : string.Empty));
+ Log (LogLevel.Debug, FormatExceptionText (message, ex));
}
public static void LogInfo (string message, Exception ex)
{
- Log (LogLevel.Info, message + (ex != null? Environment.NewLine + ex : string.Empty));
+ Log (LogLevel.Info, FormatExceptionText (message, ex));
}
public static void LogWarning (string message, Exception ex)
{
- Log (LogLevel.Warn, message + (ex != null? Environment.NewLine + ex : string.Empty));
+ Log (LogLevel.Warn, FormatExceptionText (message, ex));
}
public static void LogError (string message, Exception ex)
@@ -516,7 +536,7 @@ namespace MonoDevelop.Core
[Obsolete ("Use LogError")]
public static void LogUserError (string message, Exception ex)
{
- Log (LogLevel.Error, message + (ex != null? Environment.NewLine + ex : string.Empty));
+ Log (LogLevel.Error, FormatExceptionText (message, ex));
}
/// <summary>
@@ -541,7 +561,7 @@ namespace MonoDevelop.Core
/// <param name="ex">Exception</param>
public static void LogInternalError (string message, Exception ex)
{
- Log (LogLevel.Error, message + (ex != null? Environment.NewLine + ex : string.Empty));
+ Log (LogLevel.Error, FormatExceptionText (message, ex));
ReportUnhandledException (ex, false, true, "internal");
}
@@ -560,7 +580,7 @@ namespace MonoDevelop.Core
/// <param name="ex">Exception</param>
public static void LogFatalError (string message, Exception ex)
{
- Log (LogLevel.Error, message + (ex != null? Environment.NewLine + ex : string.Empty));
+ Log (LogLevel.Fatal, FormatExceptionText (message, ex));
ReportUnhandledException (ex, true, false, "fatal");
}
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/SystemInformation.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/SystemInformation.cs
index 69e83d4d0b..bbf4868d2e 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Core/SystemInformation.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Core/SystemInformation.cs
@@ -120,6 +120,17 @@ namespace MonoDevelop.Core
Title = "Operating System",
Description = sb.ToString ()
};
+
+ string userAddins = string.Join (Environment.NewLine,
+ AddinManager.Registry.GetModules (AddinSearchFlags.IncludeAddins | AddinSearchFlags.LatestVersionsOnly)
+ .Where (addin => addin.IsUserAddin && addin.Enabled)
+ .Select (addin => string.Format ("{0} {1}", addin.Name, addin.Version))
+ );
+ if (!string.IsNullOrEmpty (userAddins))
+ yield return new SystemInformationSection () {
+ Title = "Enabled user installed addins",
+ Description = userAddins,
+ };
}
internal static string GetReleaseId ()
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildFileFormat.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildFileFormat.cs
index 05314dfdb7..814935bdbb 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildFileFormat.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildFileFormat.cs
@@ -347,7 +347,7 @@ namespace MonoDevelop.Projects.Formats.MSBuild
protected override bool SupportsToolsVersion (string version)
{
- return version == "4.0" || version == "12.0";
+ return version == "4.0" || version == "12.0" || version == "14.0";
}
}
}
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProjectHandler.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProjectHandler.cs
index 8f1a2ac0de..fe62395a0d 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProjectHandler.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProjectHandler.cs
@@ -119,6 +119,7 @@ namespace MonoDevelop.Projects.Formats.MSBuild
return SolutionFormat;
return new MSBuildFileFormatVS12 ();
case "12.0":
+ case "14.0":
return new MSBuildFileFormatVS12 ();
default:
throw new Exception ("Unknown ToolsVersion '" + ToolsVersion + "'");
@@ -312,7 +313,7 @@ namespace MonoDevelop.Projects.Formats.MSBuild
newContext = new TargetEvaluationContext (newContext);
var res = RunTarget (monitor, target, configuration, (TargetEvaluationContext) newContext);
CallContext.SetData ("MonoDevelop.Projects.TargetEvaluationResult", res);
- return res.BuildResult;
+ return res != null ? res.BuildResult : null;
} finally {
if (newContext != currentContext)
CallContext.SetData ("MonoDevelop.Projects.ProjectOperationContext", currentContext);
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProjectService.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProjectService.cs
index 51013f182a..c8efc96d0c 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProjectService.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/MSBuildProjectService.cs
@@ -504,12 +504,16 @@ namespace MonoDevelop.Projects.Formats.MSBuild
internal static RemoteProjectBuilder GetProjectBuilder (TargetRuntime runtime, string minToolsVersion, string file, string solutionFile)
{
lock (builders) {
- //attempt to use 12.0 builder first if available
- string toolsVersion = "12.0";
- string binDir = runtime.GetMSBuildBinPath ("12.0");
+ //attempt to use 14.0 builder first if available
+ string toolsVersion = "14.0";
+ string binDir = runtime.GetMSBuildBinPath ("14.0");
if (binDir == null) {
- //fall back to 4.0, we know it's always available
- toolsVersion = "4.0";
+ toolsVersion = "12.0";
+ binDir = runtime.GetMSBuildBinPath ("12.0");
+ if (binDir == null) {
+ //fall back to 4.0, we know it's always available
+ toolsVersion = "4.0";
+ }
}
//check the ToolsVersion we found can handle the project
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/RemoteProjectBuilder.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/RemoteProjectBuilder.cs
index ab59a88e1d..57f2e797e5 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/RemoteProjectBuilder.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/RemoteProjectBuilder.cs
@@ -159,7 +159,7 @@ namespace MonoDevelop.Projects.Formats.MSBuild
void CheckDisconnected ()
{
- if (engine.CheckDisconnected ()) {
+ if (engine != null && engine.CheckDisconnected ()) {
if (Disconnected != null)
Disconnected (this, EventArgs.Empty);
}
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/SlnFileFormat.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/SlnFileFormat.cs
index b1aacadd0e..0ebb7f4c4a 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/SlnFileFormat.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Formats.MSBuild/SlnFileFormat.cs
@@ -80,7 +80,7 @@ namespace MonoDevelop.Projects.Formats.MSBuild
monitor.BeginTask (GettextCatalog.GetString ("Saving solution: {0}", file), 1);
try {
if (File.Exists (file))
- tmpfilename = Path.GetTempFileName ();
+ tmpfilename = Path.GetDirectoryName (file) + Path.DirectorySeparatorChar + ".#" + Path.GetFileName (file);
} catch (IOException) {
}
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Policies/PolicyService.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Policies/PolicyService.cs
index 0e7b6e5b61..e3604edc2d 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Policies/PolicyService.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Policies/PolicyService.cs
@@ -1240,6 +1240,11 @@ namespace MonoDevelop.Projects.Policies
if (pset.Id == "Default") {
defaultPolicies = pset;
} else {
+ // if the policy file does not have a name, use the file name as one
+ if (!string.IsNullOrEmpty (pset.Name)) {
+ pset.Name = file.FileNameWithoutExtension;
+ }
+
AddUserPolicySet (pset);
}
xr.MoveToContent ();
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.SharedAssetsProjects/SharedAssetsProject.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.SharedAssetsProjects/SharedAssetsProject.cs
index 099b33784e..112b9e8fb0 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.SharedAssetsProjects/SharedAssetsProject.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.SharedAssetsProjects/SharedAssetsProject.cs
@@ -223,7 +223,7 @@ namespace MonoDevelop.Projects.SharedAssetsProjects
pref.Flags = ProjectItemFlags.DontPersist;
pref.SetItemsProjectPath (ProjItemsPath);
foreach (var f in Files) {
- if (pref.OwnerProject.Files.GetFile (f.FilePath) == null) {
+ if (pref.OwnerProject.Files.GetFile (f.FilePath) == null && f.Subtype != Subtype.Directory) {
var cf = (ProjectFile)f.Clone ();
cf.Flags |= ProjectItemFlags.DontPersist | ProjectItemFlags.Hidden;
pref.OwnerProject.Files.Add (cf);
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Text/TextFormatter.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Text/TextFormatter.cs
index 4d6efb199a..aee449009a 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Text/TextFormatter.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Text/TextFormatter.cs
@@ -113,6 +113,10 @@ namespace MonoDevelop.Projects.Text
}
}
}
+
+ public bool KeepLines {
+ get; set;
+ }
public bool TabsAsSpaces {
get { return tabsAsSpaces; }
@@ -304,8 +308,12 @@ namespace MonoDevelop.Projects.Text
void AppendCurrentWord (char separatorChar)
{
- if (currentWord.Length == 0)
+ if (currentWord.Length == 0) {
+ if (KeepLines && lineStart && separatorChar == '\n') {
+ AppendChar (separatorChar, true);
+ }
return;
+ }
if (Wrap == WrappingType.Word || Wrap == WrappingType.WordChar) {
if (curCol + currentWord.Length > MaxColumns) {
// If the last char was a word separator, remove it
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProject.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProject.cs
index 28040d75c5..904ecdf71a 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProject.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProject.cs
@@ -471,21 +471,28 @@ namespace MonoDevelop.Projects
for (int n=0; n<References.Count; n++) {
ProjectReference pr = References [n];
if (pr.ReferenceType == ReferenceType.Assembly && DefaultConfiguration != null) {
- if (pr.GetReferencedFileNames (DefaultConfiguration.Selector).Any (f => f == updatedFile))
+ if (pr.GetReferencedFileNames (DefaultConfiguration.Selector).Any (f => f == updatedFile)) {
+ SetFastBuildCheckDirty ();
pr.NotifyStatusChanged ();
+ }
} else if (pr.HintPath == updatedFile) {
+ SetFastBuildCheckDirty ();
var nr = pr.GetRefreshedReference ();
if (nr != null)
References [n] = nr;
}
}
+ /* Removed because it is very slow. SetFastBuildCheckDirty() is being called above. It is not the perfect solution but it is good enough
+ * In the new project model GetReferencedAssemblies is asynchronous, so the code can be uncommented there.
+
// If a referenced assembly changes, dirtify the project.
foreach (var asm in GetReferencedAssemblies (DefaultConfiguration.Selector))
if (asm == updatedFile) {
SetFastBuildCheckDirty ();
break;
}
+ */
}
internal override void OnFileChanged (object source, MonoDevelop.Core.FileEventArgs e)
@@ -960,8 +967,11 @@ namespace MonoDevelop.Projects
// Hack to keep backwards compatibility with the old behavior. For example, a MonoDroid project is a library, but OnGetSupportsExecute
// is not overriden, so it depends on DotNetProject to return true by default.
- if (compileTarget == CompileTarget.Library && GetType () == typeof (DotNetAssemblyProject))
- return false;
+ if (compileTarget == CompileTarget.Library) {
+ Type thisType = GetType ();
+ if (thisType == typeof (DotNetAssemblyProject) || thisType == typeof (PortableDotNetProject))
+ return false;
+ }
return true;
}
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProjectConfiguration.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProjectConfiguration.cs
index 19b60f692b..524f7a6587 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProjectConfiguration.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/DotNetProjectConfiguration.cs
@@ -247,7 +247,7 @@ namespace MonoDevelop.Projects
case "TARGETNAME": return conf.CompiledOutputName.FileName;
case "TARGETDIR": return conf.CompiledOutputName.ParentDirectory;
case "TARGETEXT": return conf.CompiledOutputName.Extension;
- case "PROJECTCONFIG": return conf.Name + "." + conf.Platform;
+ case "PROJECTCONFIG": return string.IsNullOrEmpty (conf.Platform) ? conf.Name : conf.Name + "." + conf.Platform;
case "PROJECTCONFIGNAME": return conf.Name;
case "PROJECTCONFIGPLAT": return conf.Platform;
}
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs
index a28e9009af..ce57c35a54 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs
@@ -69,6 +69,8 @@ namespace MonoDevelop.Projects
public TargetEvaluationResult RunTarget (IProgressMonitor monitor, string target, ConfigurationSelector configuration, TargetEvaluationContext context)
{
+ var currentContext = CallContext.GetData ("MonoDevelop.Projects.ProjectOperationContext");
+ var currentResult = CallContext.GetData ("MonoDevelop.Projects.TargetEvaluationResult");
try {
CallContext.SetData ("MonoDevelop.Projects.ProjectOperationContext", context);
CallContext.SetData ("MonoDevelop.Projects.TargetEvaluationResult", null);
@@ -82,8 +84,8 @@ namespace MonoDevelop.Projects
}
return new TargetEvaluationResult (r);
} finally {
- CallContext.SetData ("MonoDevelop.Projects.ProjectOperationContext", null);
- CallContext.SetData ("MonoDevelop.Projects.TargetEvaluationResult", null);
+ CallContext.SetData ("MonoDevelop.Projects.ProjectOperationContext", currentContext);
+ CallContext.SetData ("MonoDevelop.Projects.TargetEvaluationResult", currentResult);
}
}
@@ -102,6 +104,7 @@ namespace MonoDevelop.Projects
newContext = new TargetEvaluationContext ();
else if (!(newContext is TargetEvaluationContext))
newContext = new TargetEvaluationContext (newContext);
+
var res = OnRunTarget (monitor, target, configuration, (TargetEvaluationContext) newContext);
CallContext.SetData ("MonoDevelop.Projects.TargetEvaluationResult", res);
return res.BuildResult;
@@ -119,13 +122,20 @@ namespace MonoDevelop.Projects
internal protected virtual TargetEvaluationResult OnRunTarget (IProgressMonitor monitor, string target, ConfigurationSelector configuration, TargetEvaluationContext context)
{
- var r = base.OnRunTarget (monitor, target, configuration);
- var evalRes = CallContext.GetData ("MonoDevelop.Projects.TargetEvaluationResult") as TargetEvaluationResult;
- if (evalRes != null)
- evalRes.BuildResult = r;
- else
- evalRes = new TargetEvaluationResult (r);
- return evalRes;
+ var currentContext = CallContext.GetData ("MonoDevelop.Projects.ProjectOperationContext") as ProjectOperationContext;
+ CallContext.SetData ("MonoDevelop.Projects.ProjectOperationContext", context);
+
+ try {
+ var r = base.OnRunTarget (monitor, target, configuration);
+ var evalRes = CallContext.GetData ("MonoDevelop.Projects.TargetEvaluationResult") as TargetEvaluationResult;
+ if (evalRes != null)
+ evalRes.BuildResult = r;
+ else
+ evalRes = new TargetEvaluationResult (r);
+ return evalRes;
+ } finally {
+ CallContext.SetData ("MonoDevelop.Projects.ProjectOperationContext", currentContext);
+ }
}
string[] supportedMSBuildTargets;
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectFile.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectFile.cs
index 5032124097..a06690fdca 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectFile.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectFile.cs
@@ -89,7 +89,6 @@ namespace MonoDevelop.Projects
}
}
-
public string Name {
get { return filename; }
@@ -470,7 +469,7 @@ namespace MonoDevelop.Projects
}
}
- internal class ProjectFileVirtualPathChangedEventArgs : EventArgs
+ class ProjectFileVirtualPathChangedEventArgs : EventArgs
{
public ProjectFileVirtualPathChangedEventArgs (ProjectFile projectFile, FilePath oldPath, FilePath newPath)
{
@@ -484,7 +483,7 @@ namespace MonoDevelop.Projects
public FilePath NewVirtualPath { get; private set; }
}
- internal class ProjectFilePathChangedEventArgs : ProjectFileVirtualPathChangedEventArgs
+ class ProjectFilePathChangedEventArgs : ProjectFileVirtualPathChangedEventArgs
{
public ProjectFilePathChangedEventArgs (ProjectFile projectFile, FilePath oldPath, FilePath newPath, FilePath oldVirtualPath, FilePath newVirtualPath) : base (projectFile, oldVirtualPath, newVirtualPath)
{
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectService.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectService.cs
index cadf15d78c..ab4ca63590 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectService.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/ProjectService.cs
@@ -375,9 +375,10 @@ namespace MonoDevelop.Projects
obj.ConvertToFormat (format, true);
obj.Save (monitor);
List<FilePath> newFiles = obj.GetItemFiles (true);
-
+ var resolvedTargetPath = new FilePath (targetPath).ResolveLinks ().FullPath;
+
foreach (FilePath f in newFiles) {
- if (!f.IsChildPathOf (targetPath)) {
+ if (!f.IsChildPathOf (resolvedTargetPath)) {
if (obj is Solution)
monitor.ReportError ("The solution '" + obj.Name + "' is referencing the file '" + f.FileName + "' which is located outside the root solution directory.", null);
else
diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Solution.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Solution.cs
index fc9ee9731a..5b8217ddfa 100644
--- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Solution.cs
+++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Solution.cs
@@ -180,7 +180,6 @@ namespace MonoDevelop.Projects
}
// Used by serialization only
- [ProjectPathItemProperty ("StartupItem", DefaultValue=null, ReadOnly=true)]
internal string StartupItemFileName {
get {
if (SingleStartup && StartupItem != null)
@@ -191,8 +190,6 @@ namespace MonoDevelop.Projects
set { startItemFileName = value; }
}
- [ItemProperty ("StartupItems", ReadOnly=true)]
- [ProjectPathItemProperty ("Item", Scope="*")]
internal List<string> MultiStartupItemFileNames {
get {
if (SingleStartup)
diff --git a/main/src/core/MonoDevelop.Ide/AssemblyInfo.cs b/main/src/core/MonoDevelop.Ide/AssemblyInfo.cs
index df2563993f..84ab363a6f 100644
--- a/main/src/core/MonoDevelop.Ide/AssemblyInfo.cs
+++ b/main/src/core/MonoDevelop.Ide/AssemblyInfo.cs
@@ -10,6 +10,7 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyCopyright ("LGPL")]
[assembly: InternalsVisibleTo("MacPlatform")]
+[assembly: InternalsVisibleTo("WindowsPlatform")]
[assembly: InternalsVisibleTo("MonoDevelop.Debugger")]
[assembly: InternalsVisibleTo("MonoDevelop.DesignerSupport")]
[assembly: InternalsVisibleTo("Ide.Tests")]
diff --git a/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml b/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml
index 1ae62d65bf..3b0e686d93 100644
--- a/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml
+++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml
@@ -619,15 +619,15 @@
defaultHandler = "MonoDevelop.Ide.Commands.ZoomIn"
_label = "_Zoom In"
icon = "gtk-zoom-in"
- shortcut = "Control|+"
- macShortcut = "Meta|+"
+ shortcut = "Control|+ Control|="
+ macShortcut = "Meta|+ Meta|="
_description = "Zooms view in" />
<Command id = "MonoDevelop.Ide.Commands.ViewCommands.ZoomOut"
defaultHandler = "MonoDevelop.Ide.Commands.ZoomOut"
_label = "Zoom _Out"
icon = "gtk-zoom-out"
- shortcut = "Control|-"
- macShortcut = "Meta|-"
+ shortcut = "Control|- Control|_"
+ macShortcut = "Meta|- Meta|_"
_description = "Zooms view out" />
<Command id = "MonoDevelop.Ide.Commands.ViewCommands.ZoomReset"
defaultHandler = "MonoDevelop.Ide.Commands.ZoomReset"
@@ -683,26 +683,37 @@
defaultHandler = "MonoDevelop.Ide.Commands.InstrumentationViewerHandler"
_label = "Instrumentation Monitor" />
+ <Command id = "MonoDevelop.Ide.Commands.ToolCommands.ToggleSessionRecorder"
+ defaultHandler = "MonoDevelop.Ide.Commands.ToggleSessionRecorderHandler"
+ _label = "Start Session Recorder" />
+
+ <Command id = "MonoDevelop.Ide.Commands.ToolCommands.ReplaySession"
+ defaultHandler = "MonoDevelop.Ide.Commands.ReplaySessionHandler"
+ _label = "Replay Session..." />
</Category>
<!-- WindowCommands -->
<Category _name = "Window" id = "Window">
- <Command id = "MonoDevelop.Ide.Commands.WindowCommands.NextWindow"
- defaultHandler = "MonoDevelop.Ide.Commands.NextWindowHandler"
- _label = "_Next Window"
+ <Command id = "MonoDevelop.Ide.Commands.WindowCommands.NextDocument"
+ defaultHandler = "MonoDevelop.Ide.Commands.NextDocumentHandler"
+ _label = "_Next Document"
icon = "gtk-go-forward"
- _description = "Show next window"
+ _description = "Show next document"
shortcut = "Control|Page_Down"
macShortcut = "Meta|}" />
- <Command id = "MonoDevelop.Ide.Commands.WindowCommands.PrevWindow"
- defaultHandler = "MonoDevelop.Ide.Commands.PrevWindowHandler"
- _label = "_Previous Window"
+ <Command id = "MonoDevelop.Ide.Commands.WindowCommands.PrevDocument"
+ defaultHandler = "MonoDevelop.Ide.Commands.PrevDocumentHandler"
+ _label = "_Previous Document"
icon = "gtk-go-back"
- _description = "Show previous window"
+ _description = "Show previous document"
shortcut = "Control|Page_Up"
macShortcut = "Meta|{" />
+ <Command id = "MonoDevelop.Ide.Commands.WindowCommands.OpenDocumentList"
+ defaultHandler = "MonoDevelop.Ide.Commands.OpenDocumentListHandler"
+ type="radio|array"
+ _label = "Document List" />
<Command id = "MonoDevelop.Ide.Commands.WindowCommands.OpenWindowList"
defaultHandler = "MonoDevelop.Ide.Commands.OpenWindowListHandler"
type="radio|array"
diff --git a/main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml b/main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml
index e3a7cc997a..28e93193d0 100644
--- a/main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml
+++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml
@@ -222,6 +222,10 @@
<CommandItem id = "MonoDevelop.Ide.Commands.ToolCommands.ToolList" />
<CommandItem id = "MonoDevelop.Ide.Commands.ToolCommands.InstrumentationViewer" />
<CommandItem id = "MonoDevelop.Ide.Commands.EditCommands.InsertGuid" />
+ <ItemSet id = "SessionRecorder" _label = "Session Recorder" autohide = "true">
+ <CommandItem id = "MonoDevelop.Ide.Commands.ToolCommands.ToggleSessionRecorder" />
+ <CommandItem id = "MonoDevelop.Ide.Commands.ToolCommands.ReplaySession" />
+ </ItemSet>
<SeparatorItem id = "OptionsSection" />
<Condition id="Platform" value="windows">
<CommandItem id = "MonoDevelop.Ide.Commands.EditCommands.MonodevelopPreferences" />
@@ -230,8 +234,8 @@
</ItemSet>
<ItemSet id = "Window" _label = "_Window">
- <CommandItem id = "MonoDevelop.Ide.Commands.WindowCommands.NextWindow" />
- <CommandItem id = "MonoDevelop.Ide.Commands.WindowCommands.PrevWindow" />
+ <CommandItem id = "MonoDevelop.Ide.Commands.WindowCommands.NextDocument" />
+ <CommandItem id = "MonoDevelop.Ide.Commands.WindowCommands.PrevDocument" />
<SeparatorItem id ="NxtPrvSeparator" />
<CommandItem id = "MonoDevelop.Ide.Commands.FileCommands.CloseAllFiles" />
<!-- <SeparatorItem id ="SplitSeparator" />
@@ -241,6 +245,9 @@
<CommandItem id = "MonoDevelop.Ide.Commands.WindowCommands.SwitchSplitWindow" />-->
<SeparatorItem id = "contentSep" />
<CommandItem id = "MonoDevelop.Ide.Commands.WindowCommands.OpenWindowList" />
+ <SeparatorItem id = "windowDocSep" />
+ <CommandItem id = "MonoDevelop.Ide.Commands.WindowCommands.OpenDocumentList" />
+ <SeparatorItem id = "docMinimizeSep" />
</ItemSet>
<ItemSet id = "Help" _label = "_Help">
diff --git a/main/src/core/MonoDevelop.Ide/ExtensionModel/MimeTypes.addin.xml b/main/src/core/MonoDevelop.Ide/ExtensionModel/MimeTypes.addin.xml
index 4a4bd5b95a..b27e0cb69b 100644
--- a/main/src/core/MonoDevelop.Ide/ExtensionModel/MimeTypes.addin.xml
+++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/MimeTypes.addin.xml
@@ -67,6 +67,11 @@
<MimeType id="text/x-apple-strings" _description="Apple Strings" isText="true">
<File pattern="*.strings" />
</MimeType>
+
+ <MimeType id="text/x-sql" _description="sql files" isText="true">
+ <File pattern="*.sql" />
+ </MimeType>
+
<MimeType id="application/json" _description="JSON files" isText="true">
<File pattern="*.json" />
</MimeType>
diff --git a/main/src/core/MonoDevelop.Ide/ExtensionModel/Templates.addin.xml b/main/src/core/MonoDevelop.Ide/ExtensionModel/Templates.addin.xml
index 2c791534fe..d53bd4470a 100644
--- a/main/src/core/MonoDevelop.Ide/ExtensionModel/Templates.addin.xml
+++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/Templates.addin.xml
@@ -94,6 +94,11 @@
</Extension>
<Extension path="/MonoDevelop/Ide/ProjectTemplateCategories">
+ <Category id="multiplat" name="Multi-platform" icon="md-platform-cross-platform">
+ <Category id="library" name="Library">
+ <Category id="general" name="General" mappedCategories="crossplat/library/general" />
+ </Category>
+ </Category>
<Category id="other" name="Other" icon="md-platform-other">
<Category id="net" name=".NET">
<Category id="general" name="General" mappedCategories="C#" />
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Operations/ChildrenOperation.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Operations/ChildrenOperation.cs
index 34a2429352..0f27272baa 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Operations/ChildrenOperation.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Operations/ChildrenOperation.cs
@@ -30,12 +30,19 @@ namespace MonoDevelop.Components.AutoTest.Operations
{
public class ChildrenOperation : Operation
{
+ bool recursive;
+
+ public ChildrenOperation (bool recursive = true)
+ {
+ this.recursive = recursive;
+ }
+
public override List<AppResult> Execute (List<AppResult> resultSet)
{
List<AppResult> newResultSet = new List<AppResult> ();
foreach (var result in resultSet) {
- List<AppResult> flattenedChildren = result.Children ();
+ List<AppResult> flattenedChildren = result.Children (recursive);
if (flattenedChildren != null) {
newResultSet.AddRange (flattenedChildren);
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Operations/SelectedOperation.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Operations/SelectedOperation.cs
new file mode 100644
index 0000000000..51dfa0444b
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Operations/SelectedOperation.cs
@@ -0,0 +1,53 @@
+//
+// SelectedOperation.cs
+//
+// Author:
+// Manish Sinha <manish.sinha@xamarin.com>
+//
+// Copyright (c) 2015 Xamarin Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Collections.Generic;
+
+namespace MonoDevelop.Components.AutoTest.Operations
+{
+ public class SelectedOperation : Operation
+ {
+ public override List<AppResult> Execute (List<AppResult> resultSet)
+ {
+ List<AppResult> newResultSet = new List<AppResult> ();
+
+ foreach (var result in resultSet) {
+ AppResult newResult = result.Selected ();
+ if (newResult != null) {
+ newResultSet.Add (newResult);
+ }
+ }
+
+ return newResultSet;
+ }
+
+ public override string ToString ()
+ {
+ return string.Format ("Selected ()");
+ }
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkNotebookResult.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkNotebookResult.cs
index a0017d32e4..53ec341408 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkNotebookResult.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkNotebookResult.cs
@@ -59,6 +59,14 @@ namespace MonoDevelop.Components.AutoTest.Results
return null;
}
+ public override AppResult Selected ()
+ {
+ if (base.Selected () != null) {
+ return noteBook.CurrentPage == toBeSelected ? this : null;
+ }
+ return null;
+ }
+
public override bool Select ()
{
if (toBeSelected >= 0) {
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkTreeModelResult.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkTreeModelResult.cs
index a4a84f8525..bf7a4fd98b 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkTreeModelResult.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkTreeModelResult.cs
@@ -26,6 +26,7 @@
using System;
using System.Collections.Generic;
using Gtk;
+using System.Linq;
namespace MonoDevelop.Components.AutoTest.Results
{
@@ -51,12 +52,25 @@ namespace MonoDevelop.Components.AutoTest.Results
Column = column;
resultIter = iter;
}
-
+
public override AppResult Marked (string mark)
{
return null;
}
+ public override AppResult Selected ()
+ {
+ if (!resultIter.HasValue) {
+ return base.Selected ();
+ }
+
+ if (base.Selected () != null && ParentWidget is TreeView) {
+ TreeView treeView = (TreeView)ParentWidget;
+ return treeView.Selection.IterIsSelected (resultIter.Value) ? this : null;
+ }
+ return null;
+ }
+
public override AppResult CheckType (Type desiredType)
{
return null;
@@ -64,7 +78,11 @@ namespace MonoDevelop.Components.AutoTest.Results
public override AppResult Model (string column)
{
- return null;
+ var columnNumber = GetColumnNumber (column, TModel);
+ if (columnNumber == -1)
+ return null;
+ Column = columnNumber;
+ return this;
}
bool CheckForText (TreeModel model, TreeIter iter, bool exact)
@@ -108,7 +126,16 @@ namespace MonoDevelop.Components.AutoTest.Results
return MatchProperty (propertyName, objectToCompare, value);
}
- return null;
+ return MatchProperty (propertyName, ParentWidget, value);
+ }
+
+ public override ObjectProperties Properties ()
+ {
+ if (resultIter != null && resultIter.HasValue) {
+ var objectForProperties = TModel.GetValue (resultIter.Value, Column);
+ return base.GetProperties (objectForProperties);
+ }
+ return base.Properties ();
}
public override List<AppResult> NextSiblings ()
@@ -131,38 +158,90 @@ namespace MonoDevelop.Components.AutoTest.Results
{
if (resultIter == null || !resultIter.HasValue) {
List<AppResult> children = new List<AppResult> ();
- TModel.Foreach ((m, p, i) => {
- children.Add (new GtkTreeModelResult (ParentWidget, TModel, Column, i));
- return false;
- });
+ TreeIter topIter;
+ if (TModel.GetIterFirst (out topIter)) {
+ var child = new GtkTreeModelResult (ParentWidget, TModel, Column, topIter);
+ children.Add (child);
+ this.FirstChild = child;
+ child.ParentNode = this;
+
+ if (recursive) {
+ var topIterChildren = FetchIterChildren (topIter, child, recursive);
+ child.FirstChild = topIterChildren.FirstOrDefault ();
+ children.AddRange (topIterChildren);
+ }
+
+ GtkTreeModelResult previousSibling = child;
+ while (TModel.IterNext (ref topIter)) {
+ var nextSibling = new GtkTreeModelResult (ParentWidget, TModel, Column, topIter);
+ children.Add (nextSibling);
+
+ nextSibling.PreviousSibling = previousSibling;
+ previousSibling.NextSibling = nextSibling;
+ nextSibling.ParentNode = this;
+
+ if (recursive) {
+ var topIterChildren = FetchIterChildren (topIter, nextSibling, recursive);
+ nextSibling.FirstChild = topIterChildren.FirstOrDefault ();
+ children.AddRange (topIterChildren);
+ }
+ }
+ }
return children;
}
TreeIter currentIter = (TreeIter) resultIter;
- if (!TModel.IterHasChild (currentIter))
+ return FetchIterChildren (currentIter, this, recursive);
+ }
+
+ List<AppResult> FetchIterChildren (TreeIter iter, GtkTreeModelResult result, bool recursive)
+ {
+ List<AppResult> newList = new List<AppResult> ();
+ if (!TModel.IterHasChild (iter))
{
- return null;
+ return newList;
}
- List<AppResult> newList = new List<AppResult> ();
- for (int i = 0; i < TModel.IterNChildren (currentIter); i++) {
+ GtkTreeModelResult previousSibling = null;
+ for (int i = 0; i < TModel.IterNChildren (iter); i++) {
TreeIter childIter;
- if (TModel.IterNthChild (out childIter, currentIter, i)) {
- newList.Add (new GtkTreeModelResult (ParentWidget, TModel, Column, childIter));
+ if (TModel.IterNthChild (out childIter, iter, i)) {
+ var child = new GtkTreeModelResult (ParentWidget, TModel, Column, childIter);
+
+ child.ParentNode = this;
+ child.PreviousSibling = previousSibling;
+ if (previousSibling != null)
+ previousSibling.NextSibling = child;
+
+ newList.Add (child);
+ if (recursive) {
+ var childrenIter = FetchIterChildren (childIter, child, recursive);
+ newList.AddRange (childrenIter);
+ child.FirstChild = childrenIter.FirstOrDefault ();
+ }
+
+ previousSibling = child;
}
}
+ result.FirstChild = newList.FirstOrDefault ();
return newList;
}
public override bool Select ()
{
+ base.Select ();
+
if (!resultIter.HasValue) {
return false;
}
if (ParentWidget is TreeView) {
TreeView treeView = (TreeView) ParentWidget;
+ treeView.Selection.UnselectAll ();
+ treeView.ExpandRow (TModel.GetPath (resultIter.Value), false);
treeView.Selection.SelectIter ((TreeIter) resultIter);
+ treeView.SetCursor (TModel.GetPath ((TreeIter) resultIter), treeView.Columns [0], false);
+
} else if (ParentWidget is ComboBox) {
ComboBox comboBox = (ComboBox) ParentWidget;
comboBox.SetActiveIter ((TreeIter) resultIter);
@@ -182,23 +261,15 @@ namespace MonoDevelop.Components.AutoTest.Results
return false;
}
- public override bool TypeKey (char key, string state = "")
- {
- return false;
- }
-
- public override bool TypeKey (string keyString, string state = "")
- {
- throw new NotImplementedException ();
- }
-
- public override bool EnterText (string text)
- {
- return false;
- }
-
public override bool Toggle (bool active)
{
+ if (resultIter.HasValue) {
+ var modelValue = TModel.GetValue ((TreeIter)resultIter, Column);
+ if (modelValue is bool) {
+ TModel.SetValue ((TreeIter)resultIter, Column, active);
+ return true;
+ }
+ }
return false;
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkWidgetResult.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkWidgetResult.cs
index ee0a2ce5d0..50d4f4b082 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkWidgetResult.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkWidgetResult.cs
@@ -85,6 +85,11 @@ namespace MonoDevelop.Components.AutoTest.Results
return null;
}
+ public override AppResult Selected ()
+ {
+ return resultWidget.HasFocus ? this : null;
+ }
+
public override AppResult CheckType (Type desiredType)
{
if (resultWidget.GetType () == desiredType || resultWidget.GetType ().IsSubclassOf (desiredType)) {
@@ -147,7 +152,7 @@ namespace MonoDevelop.Components.AutoTest.Results
return null;
}
- TreeModel ModelFromWidget (Widget widget)
+ protected TreeModel ModelFromWidget (Widget widget)
{
TreeView tv = widget as TreeView;
if (tv != null) {
@@ -174,25 +179,23 @@ namespace MonoDevelop.Components.AutoTest.Results
}
// Check if the class has the SemanticModelAttribute
+ var columnNumber = GetColumnNumber (column, model);
+ return columnNumber == -1 ? null : new GtkTreeModelResult (resultWidget, model, columnNumber) { SourceQuery = this.SourceQuery };
+ }
+
+ protected int GetColumnNumber (string column, TreeModel model)
+ {
Type modelType = model.GetType ();
SemanticModelAttribute attr = modelType.GetCustomAttribute<SemanticModelAttribute> ();
-
if (attr == null) {
// Check if the instance has the attributes
AttributeCollection attrs = TypeDescriptor.GetAttributes (model);
attr = (SemanticModelAttribute)attrs [typeof(SemanticModelAttribute)];
-
if (attr == null) {
- return null;
+ return -1;
}
}
-
- int columnNumber = Array.IndexOf (attr.ColumnNames, column);
- if (columnNumber == -1) {
- return null;
- }
-
- return new GtkTreeModelResult (resultWidget, model, columnNumber) { SourceQuery = this.SourceQuery };
+ return Array.IndexOf (attr.ColumnNames, column);
}
public override AppResult Property (string propertyName, object value)
@@ -291,7 +294,7 @@ namespace MonoDevelop.Components.AutoTest.Results
}
}
- void RealTypeKey (Gdk.Key key, Gdk.ModifierType state)
+ internal void RealTypeKey (Gdk.Key key, Gdk.ModifierType state)
{
SendKeyEvent (resultWidget, (uint)key, state, Gdk.EventType.KeyPress, null);
SendKeyEvent (resultWidget, (uint)key, state, Gdk.EventType.KeyRelease, null);
@@ -395,6 +398,12 @@ namespace MonoDevelop.Components.AutoTest.Results
case "TAB":
return Gdk.Key.Tab;
+ case "BKSP":
+ return Gdk.Key.BackSpace;
+
+ case "DELETE":
+ return Gdk.Key.Delete;
+
default:
throw new Exception ("Unknown keystring: " + keyString);
}
@@ -437,12 +446,13 @@ namespace MonoDevelop.Components.AutoTest.Results
return;
}
- Cairo.Context cr = Gdk.CairoHelper.Create (resultWidget.GdkWindow);
- cr.SetSourceRGB (1.0, 0.0, 0.0);
+ using (var cr = Gdk.CairoHelper.Create (resultWidget.GdkWindow)) {
+ cr.SetSourceRGB (1.0, 0.0, 0.0);
- Gdk.Rectangle allocation = resultWidget.Allocation;
- Gdk.CairoHelper.Rectangle (cr, allocation);
- cr.Stroke ();
+ Gdk.Rectangle allocation = resultWidget.Allocation;
+ Gdk.CairoHelper.Rectangle (cr, allocation);
+ cr.Stroke ();
+ }
}
public override void Flash ()
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/NSObjectResult.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/NSObjectResult.cs
index d60b841183..e12c8ab3ed 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/NSObjectResult.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/NSObjectResult.cs
@@ -26,12 +26,15 @@
#if MAC
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Reflection;
using System.Xml;
using AppKit;
using Foundation;
+using MonoDevelop.Components.MainToolbar;
+
namespace MonoDevelop.Components.AutoTest.Results
{
public class NSObjectResult : AppResult
@@ -43,6 +46,11 @@ namespace MonoDevelop.Components.AutoTest.Results
ResultObject = resultObject;
}
+ public override string ToString ()
+ {
+ return string.Format ("NSObject: Type: {0}", ResultObject.GetType ().FullName);
+ }
+
public override void ToXml (XmlElement element)
{
AddAttribute (element, "type", ResultObject.GetType ().ToString ());
@@ -69,18 +77,29 @@ namespace MonoDevelop.Components.AutoTest.Results
public override AppResult Marked (string mark)
{
+ if (CheckForText (ResultObject.GetType ().FullName, mark, true)) {
+ return this;
+ }
+
if (ResultObject is NSView) {
- if (((NSView)ResultObject).Identifier == mark) {
+ if (CheckForText (((NSView)ResultObject).Identifier, mark, true)) {
return this;
}
+ }
- if (ResultObject.GetType ().FullName == mark) {
+ if (ResultObject is NSWindow) {
+ if (CheckForText (((NSWindow)ResultObject).Title, mark, true)) {
return this;
}
}
return null;
}
+ public override AppResult Selected ()
+ {
+ return null;
+ }
+
public override AppResult CheckType (Type desiredType)
{
if (ResultObject.GetType () == desiredType || ResultObject.GetType ().IsSubclassOf (desiredType)) {
@@ -98,6 +117,13 @@ namespace MonoDevelop.Components.AutoTest.Results
if (CheckForText (value, text, exact)) {
return this;
}
+
+ if (ResultObject is NSButton) {
+ var nsButton = (NSButton)ResultObject;
+ if (CheckForText (nsButton.Title, text, exact)) {
+ return this;
+ }
+ }
}
return null;
@@ -125,7 +151,7 @@ namespace MonoDevelop.Components.AutoTest.Results
public override AppResult Property (string propertyName, object value)
{
- return (GetPropertyValue (propertyName) == value) ? this : null;
+ return MatchProperty (propertyName, ResultObject, value);
}
public override List<AppResult> NextSiblings ()
@@ -150,7 +176,8 @@ namespace MonoDevelop.Components.AutoTest.Results
return false;
}
- control.PerformClick (null);
+ using (var nsObj = new NSObject ())
+ control.PerformClick (nsObj);
return true;
}
@@ -216,6 +243,55 @@ namespace MonoDevelop.Components.AutoTest.Results
{
}
+
+#region MacPlatform.MacIntegration.MainToolbar.SelectorView
+ public override bool SetActiveConfiguration (string configurationName)
+ {
+ Type type = ResultObject.GetType ();
+ PropertyInfo pinfo = type.GetProperty ("ConfigurationModel");
+ if (pinfo == null) {
+ return false;
+ }
+
+ IEnumerable<IConfigurationModel> model = (IEnumerable<IConfigurationModel>)pinfo.GetValue (ResultObject, null);
+ var configuration = model.FirstOrDefault (c => c.DisplayString == configurationName);
+ if (configuration == null) {
+ return false;
+ }
+
+ pinfo = type.GetProperty ("ActiveConfiguration");
+ if (pinfo == null) {
+ return false;
+ }
+
+ pinfo.SetValue (ResultObject, configuration);
+ return true;
+ }
+
+ public override bool SetActiveRuntime (string runtimeName)
+ {
+ Type type = ResultObject.GetType ();
+ PropertyInfo pinfo = type.GetProperty ("RuntimeModel");
+ if (pinfo == null) {
+ return false;
+ }
+
+ IEnumerable<IRuntimeModel> model = (IEnumerable<IRuntimeModel>)pinfo.GetValue (ResultObject, null);
+
+ var runtime = model.FirstOrDefault (r => r.GetMutableModel ().FullDisplayString == runtimeName);
+ if (runtime == null) {
+ return false;
+ }
+
+ pinfo = type.GetProperty ("ActiveRuntime");
+ if (pinfo == null) {
+ return false;
+ }
+
+ pinfo.SetValue (ResultObject, runtime);
+ return true;
+ }
+#endregion
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/ObjectResult.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/ObjectResult.cs
index 6657d42cf6..683b697037 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/ObjectResult.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/ObjectResult.cs
@@ -53,6 +53,11 @@ namespace MonoDevelop.Components.AutoTest.Results
return null;
}
+ public override AppResult Selected ()
+ {
+ return null;
+ }
+
public override AppResult CheckType (Type desiredType)
{
return null;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AppQuery.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AppQuery.cs
index 6e9e31a26e..fc08c971db 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AppQuery.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AppQuery.cs
@@ -293,6 +293,12 @@ namespace MonoDevelop.Components.AutoTest
return this;
}
+ public AppQuery Selected ()
+ {
+ operations.Add (new SelectedOperation ());
+ return this;
+ }
+
public AppQuery Model (string column = null)
{
operations.Add (new ModelOperation (column));
@@ -335,9 +341,9 @@ namespace MonoDevelop.Components.AutoTest
return this;
}
- public AppQuery Children ()
+ public AppQuery Children (bool recursive = true)
{
- operations.Add (new ChildrenOperation ());
+ operations.Add (new ChildrenOperation (recursive));
return this;
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AppResult.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AppResult.cs
index e2db5fbac6..20a71e2df5 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AppResult.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AppResult.cs
@@ -50,6 +50,7 @@ namespace MonoDevelop.Components.AutoTest
// Operations
public abstract AppResult Marked (string mark);
public abstract AppResult CheckType (Type desiredType);
+ public abstract AppResult Selected ();
public abstract AppResult Text (string text, bool exact);
public abstract AppResult Model (string column);
public abstract AppResult Property (string propertyName, object value);
@@ -62,9 +63,22 @@ namespace MonoDevelop.Components.AutoTest
public abstract bool TypeKey (string keyString, string state = "");
public abstract bool EnterText (string text);
public abstract bool Toggle (bool active);
-
public abstract void Flash ();
+ // More specific actions for complicated widgets
+
+ #region For MacPlatform.MacIntegration.MainToolbar.SelectorView
+ public virtual bool SetActiveConfiguration (string configurationName)
+ {
+ return false;
+ }
+
+ public virtual bool SetActiveRuntime (string runtimeName)
+ {
+ return false;
+ }
+ #endregion
+
// Inspection Operations
public abstract ObjectProperties Properties ();
public abstract string GetResultType ();
@@ -128,27 +142,30 @@ namespace MonoDevelop.Components.AutoTest
var properties = resultObject.GetType ().GetProperties (
BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
foreach (var property in properties) {
- var value = GetPropertyValue (property.Name, resultObject);
- AppResult result = null;
-
- var gtkNotebookValue = value as Gtk.Notebook;
- if (gtkNotebookValue != null)
- result = new GtkNotebookResult (gtkNotebookValue);
- var gtkTreeviewValue = value as Gtk.TreeView;
- if (gtkTreeviewValue != null && result == null)
- result = new GtkTreeModelResult (gtkTreeviewValue, gtkTreeviewValue.Model, 0);
- var gtkWidgetValue = value as Gtk.Widget;
- if (gtkWidgetValue != null && result == null)
- result = new GtkWidgetResult (gtkWidgetValue);
- #if MAC
- var nsObjectValue = value as Foundation.NSObject;
- if (nsObjectValue != null && result == null)
- result = new NSObjectResult (nsObjectValue);
- #endif
- if (result == null)
- result = new ObjectResult (value);
-
- propertiesObject.Add (property.Name, result, property);
+ try {
+ var value = GetPropertyValue (property.Name, resultObject);
+ AppResult result = null;
+
+ var gtkNotebookValue = value as Gtk.Notebook;
+ if (gtkNotebookValue != null)
+ result = new GtkNotebookResult (gtkNotebookValue);
+ var gtkTreeviewValue = value as Gtk.TreeView;
+ if (gtkTreeviewValue != null && result == null)
+ result = new GtkTreeModelResult (gtkTreeviewValue, gtkTreeviewValue.Model, 0);
+ var gtkWidgetValue = value as Gtk.Widget;
+ if (gtkWidgetValue != null && result == null)
+ result = new GtkWidgetResult (gtkWidgetValue);
+ #if MAC
+ var nsObjectValue = value as Foundation.NSObject;
+ if (nsObjectValue != null && result == null)
+ result = new NSObjectResult (nsObjectValue);
+ #endif
+ if (result == null)
+ result = new ObjectResult (value);
+ propertiesObject.Add (property.Name, result, property);
+ } catch (Exception e) {
+ MonoDevelop.Core.LoggingService.LogInfo ("Failed to fetch property '{0}' on '{1}' with Exception: {2}", property, resultObject, e);
+ }
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AutoTestClientSession.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AutoTestClientSession.cs
index d8d656db72..56047273c4 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AutoTestClientSession.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AutoTestClientSession.cs
@@ -65,6 +65,15 @@ namespace MonoDevelop.Components.AutoTest
if (file == null) {
var binDir = Path.GetDirectoryName (typeof(AutoTestClientSession).Assembly.Location);
file = Path.Combine (binDir, "MonoDevelop.exe");
+ if (!File.Exists (file)) {
+ file = Path.Combine (binDir, "XamarinStudio.exe");
+ }
+ } else if (!File.Exists (file)) {
+ file = file.Replace ("MonoDevelop.exe", "XamarinStudio.exe");
+ }
+
+ if (!File.Exists (file)) {
+ throw new FileNotFoundException (file);
}
MonoDevelop.Core.Execution.RemotingService.RegisterRemotingChannel ();
@@ -77,7 +86,6 @@ namespace MonoDevelop.Components.AutoTest
var pi = new ProcessStartInfo (file, args) { UseShellExecute = false };
pi.EnvironmentVariables ["MONO_AUTOTEST_CLIENT"] = sref;
- pi.EnvironmentVariables ["GTK_MODULES"] = "gail:atk-bridge";
if (environment != null)
foreach (var e in environment)
pi.EnvironmentVariables [e.Key] = e.Value;
@@ -355,11 +363,31 @@ namespace MonoDevelop.Components.AutoTest
}
}
+ public bool SetActiveConfiguration (Func<AppQuery, AppQuery> query, string configuration)
+ {
+ AppResult[] results = Query (query);
+ if (results.Length == 0) {
+ return false;
+ }
+
+ return session.SetActiveConfiguration (results [0], configuration);
+ }
+
+ public bool SetActiveRuntime (Func<AppQuery, AppQuery> query, string runtime)
+ {
+ AppResult[] results = Query (query);
+ if (results.Length == 0) {
+ return false;
+ }
+
+ return session.SetActiveRuntime (results [0], runtime);
+ }
+
public void RunAndWaitForTimer (Action action, string counterName, int timeout = 20000)
{
AutoTestSession.TimerCounterContext context = session.CreateNewTimerContext (counterName);
action ();
- session.WaitForTimerContext (context);
+ session.WaitForTimerContext (context, timeout);
}
public XmlDocument ResultsAsXml (AppResult[] results)
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AutoTestService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AutoTestService.cs
index 7c58a76780..64b48200c2 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AutoTestService.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AutoTestService.cs
@@ -26,10 +26,16 @@
using System;
using MonoDevelop.Components.Commands;
+using MonoDevelop.Core;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Remoting;
+using System.Diagnostics;
using System.Collections.Generic;
+using System.Linq;
+using System.Xml;
+using System.Xml.Linq;
+using System.Text;
namespace MonoDevelop.Components.AutoTest
{
@@ -41,6 +47,11 @@ namespace MonoDevelop.Components.AutoTest
get { return manager.currentSession; }
}
+ static SessionRecord currentRecordSession;
+ public static SessionRecord CurrentRecordSession {
+ get { return currentRecordSession; }
+ }
+
public static void Start (CommandManager commandManager, bool publishServer)
{
AutoTestService.commandManager = commandManager;
@@ -65,12 +76,35 @@ namespace MonoDevelop.Components.AutoTest
File.WriteAllText (SessionReferenceFile, sref);
}
}
-
+
+ public static void ReplaySessionFromFile (string filename)
+ {
+ currentRecordSession = new SessionRecord (commandManager, filename);
+ currentRecordSession.ReplayEvents (() => {
+ currentRecordSession = null;
+ });
+ }
+
public static SessionRecord StartRecordingSession ()
{
- return new SessionRecord (commandManager);
+ currentRecordSession = new SessionRecord (commandManager);
+ return currentRecordSession;
}
-
+
+ public static void StopRecordingSession (string filename = null)
+ {
+ if (currentRecordSession == null) {
+ return;
+ }
+
+ currentRecordSession.Pause ();
+
+ if (filename != null) {
+ currentRecordSession.WriteLogToFile (filename);
+ }
+ currentRecordSession = null;
+ }
+
internal static string SessionReferenceFile {
get {
return Path.Combine (Path.GetTempPath (), "monodevelop-autotest-objref");
@@ -146,18 +180,104 @@ namespace MonoDevelop.Components.AutoTest
{
CommandManager commandManager;
List<RecordEvent> events = new List<RecordEvent> ();
- bool recording;
-
- public class RecordEvent
+ enum State {
+ Idle,
+ Recording,
+ Replaying
+ };
+ State state;
+
+ StringBuilder pendingText;
+ Gdk.ModifierType pendingModifiers = Gdk.ModifierType.None;
+
+ public abstract class RecordEvent
{
+ public abstract XElement ToXML ();
+ public abstract void ParseXML (XElement element);
+ public abstract void Replay (AutoTestSession testSession);
}
public class KeyPressEvent: RecordEvent
{
public Gdk.Key Key { get; set; }
public Gdk.ModifierType Modifiers { get; set; }
+
+ public override XElement ToXML ()
+ {
+ return new XElement ("event", new XAttribute ("type", "KeyPressEvent"),
+ new XElement ("key", Key.ToString ()),
+ new XElement ("modifier", Modifiers.ToString ()));
+ }
+
+ public override void ParseXML (XElement element)
+ {
+ foreach (var e in element.Elements ()) {
+ if (e.Name == "key") {
+ Key = (Gdk.Key)Enum.Parse (typeof (Gdk.Key), e.Value);
+ } else if (e.Name == "modifier") {
+ Modifiers = (Gdk.ModifierType)Enum.Parse (typeof (Gdk.ModifierType), e.Value);
+ }
+ }
+ }
+
+ public override void Replay (AutoTestSession testSession)
+ {
+ // Select the main window and then we can push key events to it.
+ AppQuery query = testSession.CreateNewQuery ();
+ AppResult[] results = query.Window ().Marked ("MonoDevelop.Ide.Gui.DefaultWorkbench").Execute ();
+ if (results.Length == 0) {
+ return;
+ }
+
+ testSession.Select (results[0]);
+ // We need the GtkWidgetResult for the main window as we only have the keys as a Gdk key
+ if (results [0] is AutoTest.Results.GtkWidgetResult) {
+ AutoTest.Results.GtkWidgetResult widgetResult = (AutoTest.Results.GtkWidgetResult) results[0];
+ widgetResult.RealTypeKey (Key, Modifiers);
+ }
+ }
}
-
+
+ public class StringEvent: RecordEvent
+ {
+ internal string Text;
+ internal Gdk.ModifierType Modifiers { get; set; }
+
+ public override XElement ToXML ()
+ {
+ return new XElement ("event", new XAttribute ("type", "StringEvent"),
+ new XElement ("text", Text),
+ new XElement ("modifier", Modifiers.ToString ()));
+ }
+
+ public override void ParseXML (XElement element)
+ {
+ foreach (var e in element.Elements ()) {
+ if (e.Name == "text") {
+ Text = e.Value;
+ } else if (e.Name == "modifier") {
+ Modifiers = (Gdk.ModifierType)Enum.Parse (typeof(Gdk.ModifierType), e.Value);
+ }
+ }
+ }
+
+ public override void Replay (AutoTestSession testSession)
+ {
+ AppQuery query = testSession.CreateNewQuery ();
+ AppResult[] results = query.Window ().Marked ("MonoDevelop.Ide.Gui.DefaultWorkbench").Execute ();
+ if (results.Length == 0) {
+ return;
+ }
+
+ testSession.Select (results [0]);
+
+ if (results [0] is AutoTest.Results.GtkWidgetResult) {
+ AutoTest.Results.GtkWidgetResult widgetResult = (AutoTest.Results.GtkWidgetResult)results [0];
+ widgetResult.EnterText (Text);
+ }
+ }
+ }
+
public class CommandEvent: RecordEvent
{
public object CommandId { get; set; }
@@ -165,6 +285,29 @@ namespace MonoDevelop.Components.AutoTest
public bool IsCommandArray {
get { return DataItemIndex != -1; }
}
+
+ public override XElement ToXML ()
+ {
+ return new XElement ("event", new XAttribute ("type", "CommandEvent"),
+ new XElement ("commandID", CommandId.ToString ()),
+ new XElement ("dataItemIndex", DataItemIndex));
+ }
+
+ public override void ParseXML (XElement element)
+ {
+ foreach (var e in element.Elements ()) {
+ if (e.Name == "commandID") {
+ CommandId = e.Value;
+ } else if (e.Name == "dataItemIndex") {
+ DataItemIndex = Convert.ToInt32 (e.Value);
+ }
+ }
+ }
+
+ public override void Replay (AutoTestSession testSession)
+ {
+ testSession.ExecuteCommand (CommandId);
+ }
}
internal SessionRecord (CommandManager commandManager)
@@ -172,39 +315,56 @@ namespace MonoDevelop.Components.AutoTest
this.commandManager = commandManager;
Resume ();
}
+
+ internal SessionRecord (CommandManager commandManager, string logFile)
+ {
+ state = State.Idle;
+ this.commandManager = commandManager;
+ LoadFromLogFile (logFile);
+ }
public IEnumerable<RecordEvent> Events {
get {
- if (recording)
+ if (state == State.Recording)
throw new InvalidOperationException ("The record session must be paused before getting the recorded events.");
return events;
}
}
public bool IsPaused {
- get { return !recording; }
+ get { return state == State.Idle; }
+ }
+
+ public bool IsReplaying {
+ get { return state == State.Replaying; }
}
public void Pause ()
{
- if (recording) {
+ if (state == State.Recording) {
commandManager.KeyPressed -= HandleCommandManagerKeyPressed;
commandManager.CommandActivated -= HandleCommandManagerCommandActivated;
- recording = false;
+ state = State.Idle;
}
}
public void Resume ()
{
- if (!recording) {
+ if (state == State.Idle) {
commandManager.KeyPressed += HandleCommandManagerKeyPressed;
commandManager.CommandActivated += HandleCommandManagerCommandActivated;
- recording = true;
+ state = State.Recording;
+ LoggingService.LogError ("Starting up session recording");
}
}
void HandleCommandManagerCommandActivated (object sender, CommandActivationEventArgs e)
{
+ if ((string)e.CommandId == "MonoDevelop.Ide.Commands.ToolCommands.ToggleSessionRecorder" ||
+ (string)e.CommandId == "MonoDevelop.Ide.Commands.ToolCommands.ReplaySession") {
+ return;
+ }
+
CommandEvent cme = new CommandEvent () { CommandId = e.CommandId };
cme.DataItemIndex = -1;
@@ -219,9 +379,117 @@ namespace MonoDevelop.Components.AutoTest
events.Add (cme);
}
+ void CompleteStringEvent (string s, Gdk.ModifierType modifiers)
+ {
+ events.Add (new StringEvent { Text = pendingText.ToString (), Modifiers = pendingModifiers });
+ pendingText = null;
+ pendingModifiers = Gdk.ModifierType.None;
+ }
+
void HandleCommandManagerKeyPressed (object sender, KeyPressArgs e)
{
- events.Add (new KeyPressEvent () { Key = e.Key, Modifiers = e.Modifiers });
+ uint unicode = Gdk.Keyval.ToUnicode (e.KeyValue);
+ if (pendingText != null) {
+ if (pendingModifiers != e.Modifiers || unicode == 0) {
+ CompleteStringEvent (pendingText.ToString (), pendingModifiers);
+ } else {
+ pendingText.Append ((char)unicode);
+ return;
+ }
+
+ // If text event has been completed, then we need to reset the pending events
+ if (unicode != 0) {
+ pendingText = new StringBuilder ();
+ pendingText.Append ((char)unicode);
+ pendingModifiers = e.Modifiers;
+ } else {
+ // Don't have a unicode key, so just issue a standard key event
+ events.Add (new KeyPressEvent { Key = e.Key, Modifiers = e.Modifiers });
+ pendingText = null;
+ pendingModifiers = Gdk.ModifierType.None;
+ }
+ } else {
+ if (unicode == 0) {
+ events.Add (new KeyPressEvent () { Key = e.Key, Modifiers = e.Modifiers });
+ return;
+ }
+
+ pendingText = new StringBuilder ();
+ pendingText.Append ((char)unicode);
+ pendingModifiers = e.Modifiers;
+ }
+ }
+
+ public void WriteLogToFile (string filepath)
+ {
+ var doc = new XDocument (new XElement ("xs-event-replay-log",
+ from ev in events
+ select ev.ToXML ()));
+
+ using (XmlWriter xw = XmlWriter.Create (filepath, new XmlWriterSettings { Indent = true })) {
+ doc.Save (xw);
+ }
+ }
+
+ public bool LoadFromLogFile (string filepath)
+ {
+ XDocument doc = XDocument.Load (filepath);
+ foreach (XElement element in doc.Element("xs-event-replay-log").Elements ()) {
+ if (element == null) {
+ continue;
+ }
+
+ string evType = element.Attribute ("type").Value;
+ RecordEvent ev = null;
+ if (evType == "KeyPressEvent") {
+ ev = new KeyPressEvent ();
+ } else if (evType == "CommandEvent") {
+ ev = new CommandEvent ();
+ } else if (evType == "StringEvent") {
+ ev = new StringEvent ();
+ }
+
+ if (ev == null) {
+ return false;
+ }
+
+ ev.ParseXML (element);
+ events.Add (ev);
+ }
+
+ return true;
+ }
+
+ public void ReplayEvents (Action completionHandler = null)
+ {
+ AutoTestSession testSession = new AutoTestSession ();
+ Stopwatch sw = new Stopwatch ();
+ int eventCount = events.Count;
+
+ state = State.Replaying;
+
+ sw.Start ();
+ // Each spin of the main loop, remove an event from the queue and replay it.
+ GLib.Idle.Add (() => {
+ RecordEvent ev = events[0];
+ events.RemoveAt (0);
+
+ ev.Replay (testSession);
+
+ if (events.Count > 0) {
+ return true;
+ }
+
+ sw.Stop ();
+ LoggingService.LogInfo ("Time elapsed to replay {0} events: {1}", eventCount, sw.Elapsed);
+ state = State.Idle;
+
+ if (completionHandler != null) {
+ completionHandler ();
+ }
+
+ return false;
+ });
}
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AutoTestSession.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AutoTestSession.cs
index 2d35b53b90..a4fb16bb70 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AutoTestSession.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AutoTestSession.cs
@@ -194,6 +194,27 @@ namespace MonoDevelop.Components.AutoTest
throw;
}
});
+ #else
+ Sync (delegate {
+ try {
+ using (var bmp = new System.Drawing.Bitmap (System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
+ System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height)) {
+ using (var g = System.Drawing.Graphics.FromImage(bmp))
+ {
+ g.CopyFromScreen(System.Windows.Forms.Screen.PrimaryScreen.Bounds.X,
+ System.Windows.Forms.Screen.PrimaryScreen.Bounds.Y,
+ 0, 0,
+ bmp.Size,
+ System.Drawing.CopyPixelOperation.SourceCopy);
+ }
+ bmp.Save(screenshotPath);
+ }
+ return null;
+ } catch (Exception e) {
+ Console.WriteLine (e);
+ throw;
+ }
+ });
#endif
}
@@ -253,6 +274,8 @@ namespace MonoDevelop.Components.AutoTest
if (remaining == null)
return res;
+ else if (res == null)
+ return null;
else
return GetValue (res, res.GetType (), remaining);
}
@@ -302,14 +325,20 @@ namespace MonoDevelop.Components.AutoTest
public void ExecuteOnIdle (Action idleFunc, bool wait = true, int timeout = 20000)
{
+ if (DispatchService.IsGuiThread) {
+ idleFunc ();
+ return;
+ }
+
if (wait == false) {
GLib.Idle.Add (() => {
idleFunc ();
return false;
});
+
return;
}
-
+
syncEvent.Reset ();
GLib.Idle.Add (() => {
idleFunc ();
@@ -324,7 +353,7 @@ namespace MonoDevelop.Components.AutoTest
// Executes the query outside of a syncEvent wait so it is safe to call from
// inside an ExecuteOnIdleAndWait
- AppResult[] ExecuteQueryNoWait (AppQuery query)
+ internal AppResult[] ExecuteQueryNoWait (AppQuery query)
{
AppResult[] resultSet = query.Execute ();
Sync (() => {
@@ -346,7 +375,6 @@ namespace MonoDevelop.Components.AutoTest
} catch (TimeoutException e) {
throw new TimeoutException (string.Format ("Timeout while executing ExecuteQuery: {0}", query), e);
}
-
return resultSet;
}
@@ -530,6 +558,36 @@ namespace MonoDevelop.Components.AutoTest
}
}
+ public bool SetActiveConfiguration (AppResult result, string configuration)
+ {
+ bool success = false;
+
+ try {
+ ExecuteOnIdle (() => {
+ success = result.SetActiveConfiguration (configuration);
+ });
+ } catch (TimeoutException e) {
+ ThrowOperationTimeoutException ("SetActiveConfiguration", result.SourceQuery, result, e);
+ }
+
+ return success;
+ }
+
+ public bool SetActiveRuntime (AppResult result, string runtime)
+ {
+ bool success = false;
+
+ try {
+ ExecuteOnIdle (() => {
+ success = result.SetActiveRuntime (runtime);
+ });
+ } catch (TimeoutException e) {
+ ThrowOperationTimeoutException ("SetActiveRuntime", result.SourceQuery, result, e);
+ }
+
+ return success;
+ }
+
void ThrowOperationTimeoutException (string operation, string query, AppResult result, Exception innerException)
{
throw new TimeoutException (string.Format ("Timeout while executing {0}: {1}\n\ton Element: {2}", operation, query, result), innerException);
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/ObjectProperties.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/ObjectProperties.cs
index 9fa28fc9c5..84acd89973 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/ObjectProperties.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/ObjectProperties.cs
@@ -42,8 +42,10 @@ namespace MonoDevelop.Components.AutoTest
internal void Add (string propertyName, AppResult propertyValue, PropertyInfo propertyInfo)
{
- propertyMap.Add (propertyName, propertyValue);
- propertyMetaData.Add (propertyName, new PropertyMetadata (propertyInfo));
+ if (!propertyMap.ContainsKey (propertyName))
+ propertyMap.Add (propertyName, propertyValue);
+ if (!propertyMetaData.ContainsKey (propertyName))
+ propertyMetaData.Add (propertyName, new PropertyMetadata (propertyInfo));
}
public ReadOnlyCollection<string> GetPropertyNames ()
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs
index 205ac7ecfc..12296f22e9 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs
@@ -333,6 +333,12 @@ namespace MonoDevelop.Components.Commands
return null;
}
+ // If a modal dialog is running then the menus are disabled, even if the commands are not
+ // See MDMenuItem::IsGloballyDisabled
+ if (DesktopService.IsModalDialogRunning ()) {
+ return ev;
+ }
+
var gdkev = MonoDevelop.Components.Mac.GtkMacInterop.ConvertKeyEvent (ev);
if (gdkev != null) {
if (ProcessKeyEvent (gdkev))
@@ -348,7 +354,7 @@ namespace MonoDevelop.Components.Commands
e.RetVal = ProcessKeyEvent (e.Event);
}
- bool ProcessKeyEvent (Gdk.EventKey ev)
+ internal bool ProcessKeyEvent (Gdk.EventKey ev)
{
if (!IsEnabled)
return true;
@@ -426,7 +432,7 @@ namespace MonoDevelop.Components.Commands
void NotifyKeyPressed (Gdk.EventKey ev)
{
if (KeyPressed != null)
- KeyPressed (this, new KeyPressArgs () { Key = ev.Key, Modifiers = ev.State });
+ KeyPressed (this, new KeyPressArgs () { Key = ev.Key, KeyValue = ev.KeyValue, Modifiers = ev.State });
}
/// <summary>
@@ -1166,7 +1172,7 @@ namespace MonoDevelop.Components.Commands
return false;
commandId = CommandManager.ToCommandId (commandId);
-
+
List<HandlerCallback> handlers = new List<HandlerCallback> ();
ActionCommand cmd = null;
try {
@@ -2602,6 +2608,7 @@ namespace MonoDevelop.Components.Commands
public class KeyPressArgs: EventArgs
{
public Gdk.Key Key { get; internal set; }
+ public uint KeyValue { get; internal set; }
public Gdk.ModifierType Modifiers { get; internal set; }
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockNotebook.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockNotebook.cs
index c1a7cb5758..c293fd3b81 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockNotebook.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockNotebook.cs
@@ -79,22 +79,16 @@ namespace MonoDevelop.Components.DockNotebook
tabStrip.DropDownButton.Sensitive = false;
- tabStrip.DropDownButton.MenuCreator = delegate {
- Gtk.Menu menu = new Menu ();
+ tabStrip.DropDownButton.ContextMenuRequested = delegate {
+ ContextMenu menu = new ContextMenu ();
foreach (var tab in pages) {
- var mi = new Gtk.ImageMenuItem ("");
- menu.Insert (mi, -1);
- var label = (Gtk.AccelLabel) mi.Child;
- if (tab.Markup != null)
- label.Markup = tab.Markup;
- else
- label.Text = tab.Text;
+ var item = new ContextMenuItem (tab.Markup ?? tab.Text);
var locTab = tab;
- mi.Activated += delegate {
+ item.Clicked += (object sender, ContextMenuItemClickedEventArgs e) => {
CurrentTab = locTab;
};
+ menu.Items.Add (item);
}
- menu.ShowAll ();
return menu;
};
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/TabStrip.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/TabStrip.cs
index 4437cfeff1..90a8668d8e 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/TabStrip.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/TabStrip.cs
@@ -441,8 +441,10 @@ namespace MonoDevelop.Components.DockNotebook
// If the user clicks and drags on the 'x' which closes the current
// tab we can end up with a null tab here
- if (t == null)
+ if (t == null) {
+ TooltipText = null;
return base.OnMotionNotifyEvent (evnt);
+ }
SetHighlightedTab (t);
var newOver = IsOverCloseButton (t, (int)evnt.X, (int)evnt.Y);
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockFrame.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockFrame.cs
index 3938cb3d6d..6022b195bc 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockFrame.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockFrame.cs
@@ -886,6 +886,8 @@ namespace MonoDevelop.Components.Docking
t.Hide ();
t.Show ();
}
+
+ MonoDevelop.Ide.IdeApp.CommandService.RegisterTopWindow (win);
} else {
w.Parent = this;
w.Size = new Size (width, height);
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockItem.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockItem.cs
index 4aace5dc41..913edeebc1 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockItem.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockItem.cs
@@ -327,7 +327,12 @@ namespace MonoDevelop.Components.Docking
{
if (dockBarItem != null)
dockBarItem.Present (Status == DockItemStatus.AutoHide || giveFocus);
- else
+ else if (floatingWindow != null) {
+ if (giveFocus)
+ floatingWindow.Present ();
+ else
+ floatingWindow.Show ();
+ } else
frame.Present (this, Status == DockItemStatus.AutoHide || giveFocus);
}
@@ -412,6 +417,7 @@ namespace MonoDevelop.Components.Docking
SetRegionStyle (frame.GetRegionStyleForItem (this));
floatingWindow = new DockFloatingWindow ((Window)frame.Toplevel, GetWindowTitle ());
+ Ide.IdeApp.CommandService.RegisterTopWindow (floatingWindow);
VBox box = new VBox ();
box.Show ();
@@ -593,7 +599,6 @@ namespace MonoDevelop.Components.Docking
{
public DockFloatingWindow (Window dockParent, string title) : base (title)
{
- TypeHint = Gdk.WindowTypeHint.Utility;
this.DockParent = dockParent;
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Extensions/ISelectFileDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Extensions/ISelectFileDialog.cs
index 9784169415..1451ed1523 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Extensions/ISelectFileDialog.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Extensions/ISelectFileDialog.cs
@@ -40,7 +40,19 @@ namespace MonoDevelop.Components.Extensions
public interface ISelectFileDialogHandler : IDialogHandler<SelectFileDialogData>
{
}
-
+
+ [Flags]
+ public enum SelectFileDialogAction
+ {
+ CreateFolder = 1,
+ SelectFolder = 2,
+ Open = 4,
+ Save = 8,
+
+ FolderFlags = CreateFolder | SelectFolder,
+ FileFlags = Open | Save
+ }
+
/// <summary>
/// Data for the ISelectFileDialogHandler implementation
/// </summary>
@@ -50,7 +62,7 @@ namespace MonoDevelop.Components.Extensions
FilterSet = new FileFilterSet ();
}
internal FileFilterSet FilterSet { get; set; }
- public Gtk.FileChooserAction Action { get; set; }
+ public SelectFileDialogAction Action { get; set; }
public IList<SelectFileDialogFilter> Filters { get { return FilterSet.Filters; } }
public FilePath CurrentFolder { get; set; }
public bool SelectMultiple { get; set; }
@@ -107,7 +119,7 @@ namespace MonoDevelop.Components.Extensions
/// <summary>
/// Action to perform with the file dialog.
/// </summary>
- public Gtk.FileChooserAction Action {
+ public SelectFileDialogAction Action {
get { return data.Action; }
set { data.Action = value; }
}
@@ -269,7 +281,14 @@ namespace MonoDevelop.Components.Extensions
internal void SetDefaultProperties (FileSelector fdiag)
{
fdiag.Title = Title;
- fdiag.Action = Action;
+ if ((Action & SelectFileDialogAction.CreateFolder) != 0)
+ fdiag.Action = Gtk.FileChooserAction.CreateFolder;
+ else if ((Action & SelectFileDialogAction.SelectFolder) != 0)
+ fdiag.Action = Gtk.FileChooserAction.SelectFolder;
+ else if ((Action & SelectFileDialogAction.Open) != 0)
+ fdiag.Action = Gtk.FileChooserAction.Open;
+ else if ((Action & SelectFileDialogAction.Save) != 0)
+ fdiag.Action = Gtk.FileChooserAction.Save;
fdiag.LocalOnly = true;
fdiag.SelectMultiple = SelectMultiple;
fdiag.TransientFor = TransientFor;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainStatusBarContextImpl.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainStatusBarContextImpl.cs
index 84e6d44cdb..e381a31c65 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainStatusBarContextImpl.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainStatusBarContextImpl.cs
@@ -71,6 +71,7 @@ namespace MonoDevelop.Components.MainToolbar
public void ShowReady ()
{
statusBar.ShowReady ();
+ statusBar.SetMessageSourcePad (null);
}
public void SetMessageSourcePad (Pad pad)
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbar.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbar.cs
index 0c2f09ee5c..751ebc8329 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbar.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbar.cs
@@ -110,19 +110,22 @@ namespace MonoDevelop.Components.MainToolbar
return;
}
- renderer.Visible = runtime.Visible;
- renderer.Sensitive = runtime.Enabled;
- renderer.Xpad = (uint)(runtime.IsIndented ? 18 : 3);
-
- if (!runtimeCombo.PopupShown) {
- // no need to ident text when the combo dropdown is not showing
- if (Platform.IsWindows)
- renderer.Xpad = 3;
- renderer.Text = runtime.FullDisplayString;
- renderer.Attributes = normalAttributes;
- } else {
- renderer.Text = runtime.DisplayString;
- renderer.Attributes = runtime.Notable ? boldAttributes : normalAttributes;
+ using (var mutableModel = runtime.GetMutableModel ()) {
+ renderer.Visible = mutableModel.Visible;
+ renderer.Sensitive = mutableModel.Enabled;
+ renderer.Xpad = (uint)(runtime.IsIndented ? 18 : 3);
+
+ if (!runtimeCombo.PopupShown) {
+ // no need to ident text when the combo dropdown is not showing
+ if (Platform.IsWindows)
+ renderer.Xpad = 3;
+ renderer.Text = mutableModel.FullDisplayString;
+ renderer.Attributes = normalAttributes;
+ } else {
+ renderer.Text = mutableModel.DisplayString;
+ renderer.Attributes = runtime.Notable ? boldAttributes : normalAttributes;
+ }
+
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarController.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarController.cs
index e07e8dd7e3..70ea988491 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarController.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarController.cs
@@ -341,10 +341,16 @@ namespace MonoDevelop.Components.MainToolbar
bool SelectActiveRuntime (ref bool selected, ref ExecutionTarget defaultTarget, ref int defaultIter)
{
var runtimes = ToolbarView.RuntimeModel.Cast<RuntimeModel> ().ToList ();
+ string lastRuntimeForProject = currentStartupProject.UserProperties.GetValue<string> ("PreferredExecutionTarget", defaultValue: null);
+ var activeTarget = IdeApp.Workspace.ActiveExecutionTarget;
+ var activeTargetId = activeTarget != null ? activeTarget.Id : null;
+
for (int iter = 0; iter < runtimes.Count; ++iter) {
var item = runtimes [iter];
- if (!item.Enabled)
- continue;
+ using (var model = item.GetMutableModel ()) {
+ if (!model.Enabled)
+ continue;
+ }
var target = item.ExecutionTarget;
if (target == null || !target.Enabled)
@@ -354,12 +360,12 @@ namespace MonoDevelop.Components.MainToolbar
if (item.HasChildren)
continue;
- if (defaultTarget == null) {
+ if (defaultTarget == null || lastRuntimeForProject == target.Id) {
defaultTarget = target;
defaultIter = iter;
}
- if (target.Id == IdeApp.Workspace.PreferredActiveExecutionTarget) {
+ if (target.Id == activeTargetId) {
IdeApp.Workspace.ActiveExecutionTarget = target;
ToolbarView.ActiveRuntime = ToolbarView.RuntimeModel.ElementAt (iter);
UpdateBuildConfiguration ();
@@ -367,7 +373,7 @@ namespace MonoDevelop.Components.MainToolbar
return true;
}
- if (target.Equals (IdeApp.Workspace.ActiveExecutionTarget)) {
+ if (target.Equals (activeTarget)) {
ToolbarView.ActiveRuntime = ToolbarView.RuntimeModel.ElementAt (iter);
UpdateBuildConfiguration ();
selected = true;
@@ -395,7 +401,6 @@ namespace MonoDevelop.Components.MainToolbar
UpdateBuildConfiguration ();
}
}
-
} finally {
ignoreRuntimeChangedCount--;
}
@@ -438,6 +443,9 @@ namespace MonoDevelop.Components.MainToolbar
void TrackStartupProject ()
{
if (currentStartupProject != null && ((currentSolution != null && currentStartupProject != currentSolution.StartupItem) || currentSolution == null)) {
+ var runtime = (RuntimeModel)ToolbarView.ActiveRuntime;
+ if (runtime != null && runtime.Command == null)
+ currentStartupProject.UserProperties.SetValue<string> ("PreferredExecutionTarget", runtime.TargetId);
currentStartupProject.ExecutionTargetsChanged -= executionTargetsChanged;
currentStartupProject.Saved -= HandleUpdateCombos;
}
@@ -762,8 +770,6 @@ namespace MonoDevelop.Components.MainToolbar
public RuntimeModel (MainToolbarController controller, ExecutionTarget target) : this (controller)
{
ExecutionTarget = target;
- Enabled = !(ExecutionTarget is ExecutionTargetGroup);
- Visible = true;
}
public RuntimeModel (MainToolbarController controller, ExecutionTarget target, RuntimeModel parent) : this (controller, target)
@@ -785,6 +791,7 @@ namespace MonoDevelop.Components.MainToolbar
public IEnumerable<IRuntimeModel> Children {
get { return children; }
}
+
public bool Notable {
get { return ExecutionTarget != null && ExecutionTarget.Notable; }
}
@@ -799,16 +806,6 @@ namespace MonoDevelop.Components.MainToolbar
set;
}
- public bool Visible {
- get;
- private set;
- }
-
- public bool Enabled {
- get;
- private set;
- }
-
public bool IsSeparator {
get { return Command == null && ExecutionTarget == null; }
}
@@ -818,43 +815,72 @@ namespace MonoDevelop.Components.MainToolbar
set;
}
- public string DisplayString {
- get {
- if (Command != null) {
- var ci = IdeApp.CommandService.GetCommandInfo (Command, new CommandTargetRoute (Controller.lastCommandTarget));
- Visible = ci.Visible;
- Enabled = ci.Enabled;
- return RemoveUnderline (ci.Text);
- }
+ public bool NotifyActivated ()
+ {
+ if (Command != null && IdeApp.CommandService.DispatchCommand (Command, CommandSource.ContextMenu))
+ return true;
+ return false;
+ }
+ internal string TargetId {
+ get {
if (ExecutionTarget == null)
return "";
-
- return !HasParent ? ExecutionTarget.FullName : ExecutionTarget.Name;
+ return ExecutionTarget.Id;
}
}
- public string FullDisplayString {
- get {
- if (Command != null) {
- var ci = IdeApp.CommandService.GetCommandInfo (Command, new CommandTargetRoute (Controller.lastCommandTarget));
- Visible = ci.Visible;
- Enabled = ci.Enabled;
- return RemoveUnderline (ci.Text);
- }
+ public IRuntimeMutableModel GetMutableModel ()
+ {
+ return Command != null ? new RuntimeMutableModel (Controller, Command) : new RuntimeMutableModel (ExecutionTarget, HasParent);
+ }
+ }
- if (ExecutionTarget == null)
- return "";
+ class RuntimeMutableModel : IRuntimeMutableModel
+ {
+ public RuntimeMutableModel (MainToolbarController controller, object command)
+ {
+ var ci = IdeApp.CommandService.GetCommandInfo (command, new CommandTargetRoute (controller.lastCommandTarget));
+ Visible = ci.Visible;
+ Enabled = ci.Enabled;
+ DisplayString = FullDisplayString = RemoveUnderline (ci.Text);
+ }
- return ExecutionTarget.FullName;
+ public RuntimeMutableModel (ExecutionTarget target, bool hasParent)
+ {
+ Enabled = !(target is ExecutionTargetGroup);
+ Visible = true;
+ if (target == null)
+ DisplayString = FullDisplayString = string.Empty;
+ else {
+ FullDisplayString = target.FullName;
+ DisplayString = !hasParent ? target.FullName : target.Name;
}
}
- public bool NotifyActivated ()
+ // Marker so it won't be reused.
+ public void Dispose ()
{
- if (Command != null && IdeApp.CommandService.DispatchCommand (Command, CommandSource.ContextMenu))
- return true;
- return false;
+ }
+
+ public bool Visible {
+ get;
+ private set;
+ }
+
+ public bool Enabled {
+ get;
+ private set;
+ }
+
+ public string DisplayString {
+ get;
+ private set;
+ }
+
+ public string FullDisplayString {
+ get;
+ private set;
}
static string RemoveUnderline (string s)
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarModels.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarModels.cs
index bdd0036f0d..eb814b067b 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarModels.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarModels.cs
@@ -51,30 +51,6 @@ namespace MonoDevelop.Components.MainToolbar
IEnumerable<IRuntimeModel> Children { get; }
/// <summary>
- /// Gets the display string to be used inside a context menu.
- /// </summary>
- /// <value>The display string.</value>
- string DisplayString { get; }
-
- /// <summary>
- /// Gets the display string to be for selected items.
- /// </summary>
- /// <value>The full display string.</value>
- string FullDisplayString { get; }
-
- /// <summary>
- /// Gets whether the menu item is visible.
- /// </summary>
- /// <value><c>true</c> if visible; otherwise, <c>false</c>.</value>
- bool Visible { get; }
-
- /// <summary>
- /// Gets whether the menu item is enabled.
- /// </summary>
- /// <value><c>true</c> if enabled; otherwise, <c>false</c>.</value>
- bool Enabled { get; }
-
- /// <summary>
/// Gets whether the menu item is a separator.
/// </summary>
/// <value><c>true</c> if this instance is separator; otherwise, <c>false</c>.</value>
@@ -100,6 +76,39 @@ namespace MonoDevelop.Components.MainToolbar
/// </remarks>
/// <value><c>true</c> if this instance has a parent; otherwise, <c>false</c>.</value>
bool HasParent { get; }
+
+ /// <summary>
+ /// Gets the runtime combo item model.
+ /// </summary>
+ /// <value>The runtime combo item.</value>
+ IRuntimeMutableModel GetMutableModel();
+ }
+
+ public interface IRuntimeMutableModel : IDisposable
+ {
+ /// <summary>
+ /// Gets the display string to be used inside a context menu.
+ /// </summary>
+ /// <value>The display string.</value>
+ string DisplayString { get; }
+
+ /// <summary>
+ /// Gets the display string to be for selected items.
+ /// </summary>
+ /// <value>The full display string.</value>
+ string FullDisplayString { get; }
+
+ /// <summary>
+ /// Gets whether the menu item is visible.
+ /// </summary>
+ /// <value><c>true</c> if visible; otherwise, <c>false</c>.</value>
+ bool Visible { get; }
+
+ /// <summary>
+ /// Gets whether the menu item is enabled.
+ /// </summary>
+ /// <value><c>true</c> if enabled; otherwise, <c>false</c>.</value>
+ bool Enabled { get; }
}
public interface ISearchMenuModel
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchInSolutionSearchCategory.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchInSolutionSearchCategory.cs
index c204647762..cd1a9c87e5 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchInSolutionSearchCategory.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchInSolutionSearchCategory.cs
@@ -30,7 +30,7 @@ using MonoDevelop.Core;
using ICSharpCode.NRefactory.TypeSystem;
using MonoDevelop.Ide.FindInFiles;
using System.Linq;
-using MonoDevelop.Ide.Gui;
+using MonoDevelop.Ide;
namespace MonoDevelop.Components.MainToolbar
{
@@ -42,9 +42,13 @@ namespace MonoDevelop.Components.MainToolbar
public override Task<ISearchDataSource> GetResults (SearchPopupSearchPattern searchPattern, int resultsCount, CancellationToken token)
{
- return Task.Factory.StartNew (delegate {
- return (ISearchDataSource)new SearchInSolutionDataSource (searchPattern);
- });
+ if (IdeApp.ProjectOperations.CurrentSelectedSolution != null) {
+ return Task.Factory.StartNew (delegate {
+ return (ISearchDataSource)new SearchInSolutionDataSource (searchPattern);
+ });
+ }
+
+ return Task.FromResult<ISearchDataSource> (default(ISearchDataSource));
}
public override bool IsValidTag (string tag)
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchPopupWindow.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchPopupWindow.cs
index 7deca2de99..b84db63c31 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchPopupWindow.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchPopupWindow.cs
@@ -120,6 +120,7 @@ namespace MonoDevelop.Components.MainToolbar
categories.Add (new ProjectSearchCategory (this));
categories.Add (new FileSearchCategory (this));
categories.Add (new CommandSearchCategory (this));
+
categories.Add (new SearchInSolutionSearchCategory ());
categories.AddRange (AddinManager.GetExtensionObjects<SearchCategory> ("/MonoDevelop/Ide/SearchCategories"));
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/FilePathEditor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/FilePathEditor.cs
index 23df98afc8..37da6db915 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/FilePathEditor.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/FilePathEditor.cs
@@ -26,8 +26,9 @@
using System;
using System.Linq;
-using Gtk;
+
using MonoDevelop.Core;
+using MonoDevelop.Components.Extensions;
namespace MonoDevelop.Components.PropertyGrid.PropertyEditors
{
@@ -41,16 +42,17 @@ namespace MonoDevelop.Components.PropertyGrid.PropertyEditors
public override void LaunchDialogue ()
{
var kindAtt = this.Property.Attributes.OfType<FilePathIsFolderAttribute> ().FirstOrDefault ();
- FileChooserAction action;
+ SelectFileDialogAction action;
+
string title;
if (kindAtt == null) {
- action = FileChooserAction.Open;
+ action = SelectFileDialogAction.Open;
title = GettextCatalog.GetString ("Select File...");
} else {
- action = FileChooserAction.SelectFolder;
+ action = SelectFileDialogAction.SelectFolder;
title = GettextCatalog.GetString ("Select Folder...");
}
- var fs = new MonoDevelop.Components.SelectFileDialog (title, action);
+ var fs = new SelectFileDialog (title, action);
if (fs.Run ())
Property.SetValue (Instance, fs.SelectedFile);
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/TextEditor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/TextEditor.cs
index 7d7d5a0f9b..a553b2d48c 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/TextEditor.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/TextEditor.cs
@@ -88,6 +88,7 @@ namespace MonoDevelop.Components.PropertyGrid.PropertyEditors
// no standard values, so just use an entry
else {
entry = new Entry ();
+ entry.IsEditable = !session.Property.IsReadOnly;
PackStart (entry, true, true, 0);
}
@@ -96,9 +97,11 @@ namespace MonoDevelop.Components.PropertyGrid.PropertyEditors
entry.HasFrame = false;
entry.Changed += TextChanged;
entry.FocusOutEvent += FirePendingChangeEvent;
+ if (!entry.IsEditable)
+ entry.ModifyText (StateType.Normal, entry.Style.Text (Gtk.StateType.Insensitive));
}
- if (entry != null && ShouldShowDialogButton ()) {
+ if (entry != null && ShouldShowDialogButton () && entry.IsEditable) {
var button = new Button ("...");
PackStart (button, false, false, 0);
button.Clicked += ButtonClicked;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyGrid.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyGrid.cs
index 5f5e6d9e95..b3914cc0ec 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyGrid.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyGrid.cs
@@ -252,6 +252,10 @@ namespace MonoDevelop.Components.PropertyGrid
{
if (this.currentObject == obj)
return;
+ if (this.propertyProviders != null) {
+ foreach (var old in this.propertyProviders.OfType<IDisposable> ())
+ old.Dispose ();
+ }
this.currentObject = obj;
this.propertyProviders = propertyProviders;
UpdateTabs ();
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyGridTable.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyGridTable.cs
index b8b16247fd..f6e785dec9 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyGridTable.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyGridTable.cs
@@ -609,7 +609,7 @@ namespace MonoDevelop.Components.PropertyGrid
if (row != null && editSession == null) {
var bounds = GetInactiveEditorBounds (row);
- if (!bounds.IsEmpty && bounds.Contains ((int)evnt.X, (int)evnt.Y) && row.Enabled) {
+ if (!bounds.IsEmpty && bounds.Contains ((int)evnt.X, (int)evnt.Y)) {
StartEditing (row);
return true;
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsGtk.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsGtk.cs
index 52607bf131..1e4f383f88 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsGtk.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsGtk.cs
@@ -33,16 +33,38 @@ namespace MonoDevelop.Components
{
public static void ShowContextMenu (Gtk.Widget parent, Gdk.EventButton evt, ContextMenu menu)
{
+ ShowContextMenu (parent, evt, menu, null);
+ }
+
+ public static void ShowContextMenu (Gtk.Widget parent, Gdk.EventButton evt, ContextMenu menu, Action closeHandler)
+ {
if (parent == null)
throw new ArgumentNullException ("parent");
if (menu == null)
throw new ArgumentNullException ("menu");
- var gtkMenu = FromMenu (menu);
+ var gtkMenu = FromMenu (menu, closeHandler);
gtkMenu.ShowAll ();
ShowContextMenu (parent, evt, gtkMenu);
}
+ public static void ShowContextMenu (Gtk.Widget parent, int x, int y, ContextMenu menu)
+ {
+ ShowContextMenu (parent, x, y, menu, null);
+ }
+
+ public static void ShowContextMenu (Gtk.Widget parent, int x, int y, ContextMenu menu, Action closeHandler)
+ {
+ if (parent == null)
+ throw new ArgumentNullException ("parent");
+ if (menu == null)
+ throw new ArgumentNullException ("menu");
+
+ var gtkMenu = FromMenu (menu, closeHandler);
+ gtkMenu.ShowAll ();
+ ShowContextMenu (parent, x, y, gtkMenu);
+ }
+
public static void ShowContextMenu (Gtk.Widget parent, Gdk.EventButton evt, Gtk.Menu menu)
{
if (parent == null)
@@ -53,6 +75,16 @@ namespace MonoDevelop.Components
Mono.TextEditor.GtkWorkarounds.ShowContextMenu (menu, parent, evt);
}
+ public static void ShowContextMenu (Gtk.Widget parent, int x, int y, Gtk.Menu menu)
+ {
+ if (parent == null)
+ throw new ArgumentNullException ("parent");
+ if (menu == null)
+ throw new ArgumentNullException ("menu");
+
+ Mono.TextEditor.GtkWorkarounds.ShowContextMenu (menu, parent, x, y, parent.Allocation);
+ }
+
static Gtk.MenuItem CreateMenuItem (ContextMenuItem item)
{
if (!item.Visible)
@@ -74,7 +106,7 @@ namespace MonoDevelop.Components
}
if (item.SubMenu != null && item.SubMenu.Items.Count > 0) {
- menuItem.Submenu = FromMenu (item.SubMenu);
+ menuItem.Submenu = FromMenu (item.SubMenu, null);
}
else {
menuItem.Activated += (sender, e) => item.Click ();
@@ -100,7 +132,7 @@ namespace MonoDevelop.Components
return menuItem;
}
- static Gtk.Menu FromMenu (ContextMenu menu)
+ static Gtk.Menu FromMenu (ContextMenu menu, Action closeHandler)
{
var result = new Gtk.Menu ();
@@ -110,6 +142,9 @@ namespace MonoDevelop.Components
result.Append (item);
}
+ if (closeHandler != null) {
+ result.Hidden += (sender, e) => closeHandler ();
+ }
return result;
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsMac.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsMac.cs
index 0b03a1e8a3..3fd766ba13 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsMac.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsMac.cs
@@ -67,8 +67,18 @@ namespace MonoDevelop.Components
var toplevel = parent.Toplevel as Gtk.Window;
var nswindow = MonoDevelop.Components.Mac.GtkMacInterop.GetNSWindow (toplevel);
- var titleBarHeight = MonoDevelop.Components.Mac.GtkMacInterop.GetTitleBarHeight ();
- var pt = new CoreGraphics.CGPoint (x, nswindow.Frame.Height - y - titleBarHeight - 12);
+
+ int titleBarOffset;
+ if (toplevel.TypeHint == Gdk.WindowTypeHint.Toolbar && toplevel.Type == Gtk.WindowType.Toplevel && toplevel.Decorated == false) {
+ // Undecorated toplevel toolbars are used for auto-hide pad windows. Don't add a titlebar offset for them.
+ titleBarOffset = 0;
+ } else if (MonoDevelop.Ide.DesktopService.GetIsFullscreen (toplevel)) {
+ titleBarOffset = 0;
+ } else {
+ titleBarOffset = MonoDevelop.Components.Mac.GtkMacInterop.GetTitleBarHeight () + 12;
+ }
+
+ var pt = new CoreGraphics.CGPoint (x, nswindow.Frame.Height - y - titleBarOffset);
var tmp_event = NSEvent.MouseEvent (NSEventType.LeftMouseDown,
pt,
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/FileEntry.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/FileEntry.cs
index a47612b712..83029b1b73 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/FileEntry.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/FileEntry.cs
@@ -28,6 +28,8 @@
using System.ComponentModel;
+using MonoDevelop.Components.Extensions;
+
namespace MonoDevelop.Components
{
[Category ("MonoDevelop.Components")]
@@ -40,7 +42,7 @@ namespace MonoDevelop.Components
public FileEntry (string name) : base (name)
{
- Action = Gtk.FileChooserAction.Open;
+ Action = SelectFileDialogAction.Open;
}
protected override string ShowBrowseDialog (string name, string startIn)
@@ -57,6 +59,6 @@ namespace MonoDevelop.Components
return null;
}
- public Gtk.FileChooserAction Action { get; set; }
+ public SelectFileDialogAction Action { get; set; }
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/MenuButton.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/MenuButton.cs
index 6e6aaa468a..50443ef77c 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/MenuButton.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/MenuButton.cs
@@ -38,6 +38,7 @@ namespace MonoDevelop.Components
public class MenuButton : Button
{
MenuCreator creator;
+ ContextMenuCreator contextMenuCreator;
Label label;
Image image;
Arrow arrow;
@@ -65,31 +66,57 @@ namespace MonoDevelop.Components
{
}
-
+
+ [Obsolete ("Use ContextMenuRequested")]
public MenuCreator MenuCreator {
get { return creator; }
set { creator = value; }
}
-
+
+ public ContextMenuCreator ContextMenuRequested {
+ get { return contextMenuCreator; }
+ set { contextMenuCreator = value; }
+ }
+
+ ReliefStyle MenuOpened ()
+ {
+ isOpen = true;
+ //make sure the button looks depressed
+ ReliefStyle oldRelief = this.Relief;
+ this.Relief = ReliefStyle.Normal;
+ return oldRelief;
+ }
+
+ void MenuClosed (ReliefStyle oldRelief)
+ {
+ this.Relief = oldRelief;
+ isOpen = false;
+ this.State = StateType.Normal;
+ }
+
protected override void OnClicked ()
{
base.OnClicked ();
-
+ if (contextMenuCreator != null) {
+ ContextMenu menu = contextMenuCreator (this);
+ var oldRelief = MenuOpened ();
+
+ Gdk.Rectangle rect = this.Allocation;
+
+ // Offset the menu by the height of the rect
+ ContextMenuExtensionsGtk.ShowContextMenu (this, 0, rect.Height, menu, () => MenuClosed (oldRelief));
+ return;
+ }
+
if (creator != null) {
Menu menu = creator (this);
if (menu != null) {
- isOpen = true;
-
- //make sure the button looks depressed
- ReliefStyle oldRelief = this.Relief;
- this.Relief = ReliefStyle.Normal;
-
+ var oldRelief = MenuOpened ();
+
//clean up after the menu's done
menu.Hidden += delegate {
- this.Relief = oldRelief ;
- isOpen = false;
- this.State = StateType.Normal;
+ MenuClosed (oldRelief);
//FIXME: for some reason the menu's children don't get activated if we destroy
//directly here, so use a timeout to delay it
@@ -153,6 +180,8 @@ namespace MonoDevelop.Components
protected override void OnDestroyed ()
{
creator = null;
+ contextMenuCreator = null;
+
base.OnDestroyed ();
}
@@ -186,6 +215,7 @@ namespace MonoDevelop.Components
set { label.Markup = value; }
}
}
-
+
public delegate Menu MenuCreator (MenuButton button);
+ public delegate ContextMenu ContextMenuCreator (MenuButton button);
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PathBar.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PathBar.cs
index 8ff221923e..a13f021b63 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PathBar.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PathBar.cs
@@ -479,7 +479,13 @@ namespace MonoDevelop.Components
if (menuWidget is Menu) {
((Menu)menuWidget).Popup (null, null, PositionFunc, 0, Gtk.Global.CurrentEventTime);
} else {
+ var window = menuWidget as Gtk.Window;
PositionWidget (menuWidget);
+
+ if (window != null) {
+ window.TransientFor = this.Toplevel as Gtk.Window;
+ }
+
menuWidget.ShowAll ();
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SelectFileDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SelectFileDialog.cs
index 45913593b5..58d0b95a2f 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SelectFileDialog.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SelectFileDialog.cs
@@ -23,12 +23,9 @@
// 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 Gtk;
+
using MonoDevelop.Components.Extensions;
-
namespace MonoDevelop.Components
{
/// <summary>
@@ -40,11 +37,11 @@ namespace MonoDevelop.Components
{
}
- public SelectFileDialog (string title): this (title, FileChooserAction.Open)
+ public SelectFileDialog (string title): this (title, SelectFileDialogAction.Open)
{
}
- public SelectFileDialog (string title, Gtk.FileChooserAction action)
+ public SelectFileDialog (string title, SelectFileDialogAction action)
{
Title = title;
Action = action;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SelectFolderDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SelectFolderDialog.cs
index a2a253f162..c468bbf9d7 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SelectFolderDialog.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SelectFolderDialog.cs
@@ -39,14 +39,14 @@ namespace MonoDevelop.Components
{
public SelectFolderDialog ()
{
- Action = Gtk.FileChooserAction.SelectFolder;
+ Action = SelectFileDialogAction.SelectFolder;
}
- public SelectFolderDialog (string title): this (title, Gtk.FileChooserAction.SelectFolder)
+ public SelectFolderDialog (string title): this (title, SelectFileDialogAction.SelectFolder)
{
}
- public SelectFolderDialog (string title, Gtk.FileChooserAction action)
+ public SelectFolderDialog (string title, SelectFileDialogAction action)
{
Title = title;
Action = action;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Tabstrip.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Tabstrip.cs
index d6c04f907a..f2153678da 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Tabstrip.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Tabstrip.cs
@@ -277,6 +277,7 @@ namespace MonoDevelop.Components
this.Label = label;
layout = PangoUtil.CreateLayout (parent);
layout.SetText (label);
+ layout.Alignment = Pango.Alignment.Center;
layout.GetPixelSize (out w, out h);
if (IsSeparator)
@@ -335,13 +336,26 @@ namespace MonoDevelop.Components
cr.Fill ();
}
}
-
+
if (Active)
cr.SetSourceRGB (1, 1, 1);
else
cr.SetSourceColor (parent.Style.Text (StateType.Normal).ToCairoColor ());
- cr.MoveTo (rectangle.X + (rectangle.Width - w) / 2, (rectangle.Height - h) / 2);
+ if (layout.Width != (int)rectangle.Width)
+ layout.Width = (int)rectangle.Width;
+
+ #if MAC
+ /* On Cocoa, Pango doesn't render text correctly using layout width/height computation.
+ * For instance here we need to balance some kind of internal padding by two pixels which
+ * only happens on Mac.
+ */
+ const int verticalOffset = -2;
+ #else
+ const int verticalOffset = 0;
+ #endif
+
+ cr.MoveTo (rectangle.X + (int)(rectangle.Width / 2), (rectangle.Height - h) / 2 + verticalOffset);
Pango.CairoHelper.ShowLayout (cr, layout);
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Windows/GtkWPFWidget.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Windows/GtkWPFWidget.cs
new file mode 100644
index 0000000000..10dd3d4b6e
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Windows/GtkWPFWidget.cs
@@ -0,0 +1,142 @@
+//
+// GtkWPFWidget.cs
+//
+// Author:
+// Marius Ungureanu <marius.ungureanu@xamarin.com>
+//
+// Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com)
+//
+// 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.
+
+#if WIN32
+using System;
+using System.Windows;
+using System.Windows.Interop;
+using Gtk;
+using Gdk;
+
+namespace MonoDevelop.Components.Windows
+{
+ public class GtkWPFWidget : Widget
+ {
+ bool fromGtk;
+ internal System.Windows.Window wpfWindow {
+ get;
+ private set;
+ }
+
+ public GtkWPFWidget (System.Windows.Controls.Control wpfControl)
+ {
+ wpfWindow = new System.Windows.Window {
+ Content = wpfControl,
+ AllowsTransparency = true,
+ WindowStyle = WindowStyle.None,
+ Background = System.Windows.Media.Brushes.Transparent,
+ };
+ wpfWindow.PreviewKeyDown += (sender, e) => {
+ // TODO: Some commands check for toplevels, and this window is not a toplevel.
+ var key = e.Key == System.Windows.Input.Key.System ? e.SystemKey : e.Key;
+ e.Handled = Ide.IdeApp.CommandService.ProcessKeyEvent (GtkWin32Interop.ConvertKeyEvent (e.KeyboardDevice.Modifiers, key));
+ };
+
+ wpfWindow.Closed += (sender, e) => {
+ if (fromGtk)
+ return;
+
+ Ide.IdeApp.Exit ();
+ };
+ wpfWindow.ShowInTaskbar = false;
+ WidgetFlags |= WidgetFlags.NoWindow;
+ }
+
+ void RepositionWpfWindow ()
+ {
+ int x, y;
+
+ var gtkWnd = Toplevel as Gtk.Window;
+ int offset = 0;
+ if (gtkWnd.Decorated)
+ offset = System.Windows.Forms.SystemInformation.CaptionHeight;
+
+ int root_x, root_y;
+ gtkWnd.GetPosition (out root_x, out root_y);
+ if (TranslateCoordinates (Toplevel, root_x, root_y + offset, out x, out y)) {
+ wpfWindow.Left = x;
+ wpfWindow.Top = y;
+ } else {
+ wpfWindow.Left = Allocation.Left;
+ wpfWindow.Top = Allocation.Top;
+ }
+ wpfWindow.Width = Allocation.Width;
+ wpfWindow.Height = Allocation.Height;
+ }
+
+ protected override void OnRealized ()
+ {
+ base.OnRealized ();
+
+ RepositionWpfWindow ();
+ }
+
+ protected override void OnSizeAllocated (Gdk.Rectangle allocation)
+ {
+ base.OnSizeAllocated (allocation);
+
+ RepositionWpfWindow ();
+ }
+
+ protected override void OnDestroyed ()
+ {
+ base.OnDestroyed ();
+
+ fromGtk = true;
+ wpfWindow.Close ();
+ }
+
+ protected override void OnShown ()
+ {
+ base.OnShown ();
+
+ wpfWindow.Show ();
+ AttachWindow ();
+ }
+
+ void AttachWindow ()
+ {
+ IntPtr gtkWindowPtr = GtkWin32Interop.HWndGet (Ide.IdeApp.Workbench.RootWindow.GdkWindow);
+ IntPtr wpfWindowPtr = new WindowInteropHelper (wpfWindow).Handle;
+ GtkWin32Interop.SetWindowLongPtr (wpfWindowPtr, (int)GtkWin32Interop.GWLParameter.GWL_HWNDPARENT, gtkWindowPtr);
+ Ide.IdeApp.Workbench.RootWindow.ConfigureEvent += OnWindowConfigured;
+ }
+
+ void OnWindowConfigured (object sender, ConfigureEventArgs args)
+ {
+ RepositionWpfWindow ();
+ }
+
+ protected override void OnHidden ()
+ {
+ base.OnHidden ();
+
+ wpfWindow.Hide ();
+ Ide.IdeApp.Workbench.RootWindow.ConfigureEvent -= OnWindowConfigured;
+ }
+ }
+}
+#endif
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Windows/GtkWin32Interop.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Windows/GtkWin32Interop.cs
new file mode 100644
index 0000000000..49fcec4936
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Windows/GtkWin32Interop.cs
@@ -0,0 +1,118 @@
+//
+// GtkWin32Interop.cs
+//
+// Author:
+// Marius Ungureanu <marius.ungureanu@xamarin.com>
+//
+// Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com)
+//
+// 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.
+#if WIN32
+using System;
+using System.Runtime.InteropServices;
+using System.Windows.Input;
+
+namespace MonoDevelop.Components.Windows
+{
+ public static class GtkWin32Interop
+ {
+ internal const string LIBGDK = "libgdk-win32-2.0-0.dll";
+ internal const string USER32 = "user32.dll";
+
+ public enum ExtendedWindowStyles
+ {
+ // Hides it from alt-tab.
+ WS_EX_TOOLWINDOW = 0x80,
+ }
+
+ public enum GWLParameter
+ {
+ // Sets a new extended style.
+ GWL_EXSTYLE = -20,
+
+ // Sets a new application handle instance.
+ GWL_HINSTANCE = -6,
+
+ // Sets a new window handle as the parent.
+ GWL_HWNDPARENT = -8,
+
+ // Sets a new identifier of the window.
+ GWL_ID = -12,
+
+ // Sets a new window style.
+ GWL_STYLE = -16,
+
+ // Sets a new user data associated with the window. Initially zero.
+ GWL_USERDATA = -21,
+
+ // Sets a new address of the window procedure.
+ GWL_WNDPROC = -4,
+ }
+
+ [DllImport (LIBGDK, CallingConvention = CallingConvention.Cdecl)]
+ static extern IntPtr gdk_win32_window_get_impl_hwnd (IntPtr window);
+
+ public static IntPtr HWndGet (Gdk.Window window)
+ {
+ return gdk_win32_window_get_impl_hwnd (window.Handle);
+ }
+
+ [DllImport (USER32, EntryPoint="SetWindowLongPtr")]
+ static extern IntPtr SetWindowLongPtr64 (IntPtr hWnd, int nIndex, IntPtr dwNewLong);
+
+ [DllImport(USER32, EntryPoint="SetWindowLong")]
+ static extern IntPtr SetWindowLongPtr32 (IntPtr hWnd, int nIndex, IntPtr dwNewLong);
+
+ public static IntPtr SetWindowLongPtr (IntPtr hWnd, int nIndex, IntPtr dwNewLong)
+ {
+ if (IntPtr.Size == 4)
+ return SetWindowLongPtr32 (hWnd, nIndex, dwNewLong);
+ return SetWindowLongPtr64 (hWnd, nIndex, dwNewLong);
+ }
+
+ [DllImport (USER32, EntryPoint="GetWindowLongPtr")]
+ static extern IntPtr GetWindowLongPtr64 (IntPtr hWnd, int nIndex);
+
+ [DllImport(USER32, EntryPoint="GetWindowLong")]
+ static extern IntPtr GetWindowLongPtr32 (IntPtr hWnd, int nIndex);
+
+ public static IntPtr GetWindowLongPtr (IntPtr hWnd, int nIndex)
+ {
+ if (IntPtr.Size == 4)
+ return GetWindowLongPtr32 (hWnd, nIndex);
+ return GetWindowLongPtr64 (hWnd, nIndex);
+ }
+
+ internal static Gdk.EventKey ConvertKeyEvent (ModifierKeys mod, Key key)
+ {
+ var state = Gdk.ModifierType.None;
+ if ((mod & ModifierKeys.Control) != 0)
+ state |= Gdk.ModifierType.ControlMask;
+ if ((mod & ModifierKeys.Shift) != 0)
+ state |= Gdk.ModifierType.ShiftMask;
+ if ((mod & ModifierKeys.Windows) != 0)
+ state |= Gdk.ModifierType.MetaMask;
+ if ((mod & ModifierKeys.Alt) != 0)
+ state |= Gdk.ModifierType.Mod1Mask;
+
+ return GtkUtil.CreateKeyEventFromKeyCode ((ushort)KeyInterop.VirtualKeyFromKey (key), state, Gdk.EventType.KeyPress, Ide.IdeApp.Workbench.RootWindow.GdkWindow);
+ }
+ }
+}
+#endif
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionWindowManager.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionWindowManager.cs
index ab723739b3..80c7f67502 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionWindowManager.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionWindowManager.cs
@@ -92,8 +92,16 @@ namespace MonoDevelop.Ide.CodeCompletion
wnd = new CompletionListWindow ();
wnd.WordCompleted += HandleWndWordCompleted;
}
- if (ext != null)
+ if (ext != null) {
wnd.TransientFor = ext.document.Editor.Parent.Toplevel as Gtk.Window;
+ } else {
+ var widget = completionWidget as Gtk.Widget;
+ if (widget != null) {
+ var window = widget.Toplevel as Gtk.Window;
+ if (window != null)
+ wnd.TransientFor = window;
+ }
+ }
wnd.Extension = ext;
try {
if (!wnd.ShowListWindow (firstChar, list, completionWidget, completionContext)) {
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplate.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplate.cs
index cd4b4c4c64..6d78400369 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplate.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplate.cs
@@ -431,7 +431,7 @@ namespace MonoDevelop.Ide.CodeTemplates
document.Editor.Caret.Location = document.Editor.OffsetToLocation (newoffset) ;
var prettyPrinter = CodeFormatterService.GetFormatter (data.MimeType);
- if (prettyPrinter != null) {
+ if (prettyPrinter != null && prettyPrinter.SupportsOnTheFlyFormatting) {
int endOffset = template.InsertPosition + template.Code.Length;
var oldVersion = data.Version;
prettyPrinter.OnTheFlyFormat (document, template.InsertPosition, endOffset);
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileCommands.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileCommands.cs
index 38d4b566a4..5d460002c9 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileCommands.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileCommands.cs
@@ -34,10 +34,10 @@ using MonoDevelop.Ide.Gui;
using MonoDevelop.Projects;
using MonoDevelop.Ide.Gui.Content;
using System.IO;
-using Gtk;
using MonoDevelop.Ide.Projects;
using MonoDevelop.Ide.Desktop;
using System.Linq;
+using MonoDevelop.Components.Extensions;
namespace MonoDevelop.Ide.Commands
{
@@ -79,7 +79,7 @@ namespace MonoDevelop.Ide.Commands
{
protected override void Run ()
{
- var dlg = new OpenFileDialog (GettextCatalog.GetString ("File to Open"), Gtk.FileChooserAction.Open) {
+ var dlg = new OpenFileDialog (GettextCatalog.GetString ("File to Open"), SelectFileDialogAction.Open) {
TransientFor = IdeApp.Workbench.RootWindow,
ShowEncodingSelector = true,
ShowViewerSelector = true,
@@ -273,8 +273,12 @@ namespace MonoDevelop.Ide.Commands
int i = 0;
foreach (var ri in files) {
- string acceleratorKeyPrefix = i < 10 ? "_" + ((i + 1) % 10).ToString() + " " : "";
- var cmd = new CommandInfo (acceleratorKeyPrefix + ri.DisplayName.Replace ("_", "__")) {
+ string commandText = ri.DisplayName.Replace ("_", "__");
+ if (!Platform.IsMac) {
+ string acceleratorKeyPrefix = i < 10 ? "_" + ((i + 1) % 10).ToString() + " " : "";
+ commandText = acceleratorKeyPrefix + commandText;
+ }
+ var cmd = new CommandInfo (commandText) {
Description = GettextCatalog.GetString ("Open {0}", ri.FileName)
};
/* Gdk.Pixbuf icon = DesktopService.GetIconForFile (ri.FileName, IconSize.Menu);
@@ -347,13 +351,18 @@ namespace MonoDevelop.Ide.Commands
LoggingService.LogWarning ("Error building recent solutions list", ex);
continue;
}
-
- string acceleratorKeyPrefix = i < 10 ? "_" + ((i + 1) % 10).ToString() + " " : "";
+
+ string commandText = ri.DisplayName.Replace ("_", "__");
+ if (!Platform.IsMac) {
+ string acceleratorKeyPrefix = i < 10 ? "_" + ((i + 1) % 10).ToString() + " " : "";
+ commandText = acceleratorKeyPrefix + commandText;
+ }
+
string str = GettextCatalog.GetString ("Load solution {0}", ri.ToString ());
if (IdeApp.Workspace.IsOpen)
str += " - " + GettextCatalog.GetString ("Hold Control to open in current workspace.");
- var cmd = new CommandInfo (acceleratorKeyPrefix + ri.DisplayName.Replace ("_", "__")) {
+ var cmd = new CommandInfo (commandText) {
Icon = icon,
Description = str,
};
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileTabCommands.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileTabCommands.cs
index 60c9b06e60..20ace23f75 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileTabCommands.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileTabCommands.cs
@@ -35,6 +35,7 @@ using MonoDevelop.Ide.Gui;
using MonoDevelop.Ide.Navigation;
using MonoDevelop.Core;
using System.Linq;
+using MonoDevelop.Ide.Gui.Dialogs;
namespace MonoDevelop.Ide.Commands
{
@@ -49,33 +50,46 @@ namespace MonoDevelop.Ide.Commands
class CloseAllHandler : CommandHandler
{
+ protected virtual IViewContent GetDocumentException ()
+ {
+ return null;
+ }
+
protected override void Run ()
{
var active = IdeApp.Workbench.ActiveDocument;
if (active == null)
return;
+
var activeNotebook = ((SdiWorkspaceWindow)active.Window).TabControl;
- foreach (Document doc in IdeApp.Workbench.Documents.ToArray ()) {
- var w1 = (SdiWorkspaceWindow) doc.Window;
- if (w1.TabControl == activeNotebook)
+ var except = GetDocumentException ();
+
+ var docs = IdeApp.Workbench.Documents
+ .Where (doc => ((SdiWorkspaceWindow)doc.Window).TabControl == activeNotebook && (except == null || doc.Window.ViewContent != except))
+ .ToArray ();
+
+ var dirtyDialogShown = docs.Count (doc => doc.IsDirty) > 1;
+ if (dirtyDialogShown)
+ using (var dlg = new DirtyFilesDialog (docs, closeWorkspace: false, groupByProject: false)) {
+ dlg.Modal = true;
+ if (MessageService.ShowCustomDialog (dlg) != (int)Gtk.ResponseType.Ok)
+ return;
+ }
+
+ foreach (Document doc in docs)
+ if (dirtyDialogShown)
+ doc.Window.CloseWindow (true);
+ else
doc.Close ();
- }
}
}
- class CloseAllButThisHandler : CommandHandler
+ class CloseAllButThisHandler : CloseAllHandler
{
- protected override void Run ()
+ protected override IViewContent GetDocumentException ()
{
var active = IdeApp.Workbench.ActiveDocument;
- if (active == null)
- return;
- var activeNotebook = ((SdiWorkspaceWindow)active.Window).TabControl;
- foreach (Document doc in IdeApp.Workbench.Documents.ToArray ()) {
- var w1 = (SdiWorkspaceWindow) doc.Window;
- if (w1.TabControl == activeNotebook && doc != active)
- doc.Close ();
- }
+ return active == null ? null : active.Window.ViewContent;
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ProjectCommands.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ProjectCommands.cs
index ef43552ecf..a121725c3a 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ProjectCommands.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ProjectCommands.cs
@@ -571,9 +571,11 @@ namespace MonoDevelop.Ide.Commands
{
protected override void Update (CommandInfo info)
{
- info.Enabled = (IdeApp.ProjectOperations.CurrentSelectedSolution != null) &&
- (IdeApp.ProjectOperations.CurrentBuildOperation.IsCompleted) &&
- IdeApp.ProjectOperations.CurrentSelectedSolution.GetAllProjects ().Any (p => p.SupportsTarget ("RunCodeAnalysis"));
+ //TODO: Roslyn, switch back to SupportsTarget check
+ //info.Enabled = (IdeApp.ProjectOperations.CurrentSelectedSolution != null) &&
+ // (IdeApp.ProjectOperations.CurrentBuildOperation.IsCompleted) &&
+ // IdeApp.ProjectOperations.CurrentSelectedSolution.GetAllProjects ().Any (p => p.SupportsTarget ("RunCodeAnalysis"));
+ info.Enabled = true;
}
protected override void Run ()
@@ -591,7 +593,8 @@ namespace MonoDevelop.Ide.Commands
if (IdeApp.Workspace.IsOpen) {
var project = IdeApp.ProjectOperations.CurrentSelectedProject;
if (project != null) {
- info.Enabled = project.SupportsTarget ("RunCodeAnalysis");
+ //TODO: Roslyn, switch back to SupportsTarget check
+ info.Enabled = true;//project.SupportsTarget ("RunCodeAnalysis");
info.Text = GettextCatalog.GetString ("Run Code Analysis on {0}", project.Name.Replace ("_","__"));
return;
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ToolsCommands.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ToolsCommands.cs
index 797e266a66..109d363505 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ToolsCommands.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ToolsCommands.cs
@@ -25,11 +25,11 @@
//
//
-
+using MonoDevelop.Components.AutoTest;
using MonoDevelop.Components.Commands;
using MonoDevelop.Core;
using MonoDevelop.Core.Execution;
-using MonoDevelop.Ide.Gui;
+using MonoDevelop.Ide.Gui.Dialogs;
using System;
using MonoDevelop.Ide.Updater;
@@ -39,7 +39,9 @@ namespace MonoDevelop.Ide.Commands
{
AddinManager,
ToolList,
- InstrumentationViewer
+ InstrumentationViewer,
+ ToggleSessionRecorder,
+ ReplaySession,
}
internal class AddinManagerHandler : CommandHandler
@@ -138,4 +140,59 @@ namespace MonoDevelop.Ide.Commands
info.Visible = MonoDevelop.Core.Instrumentation.InstrumentationService.Enabled;
}
}
+
+ internal class ToggleSessionRecorderHandler : CommandHandler
+ {
+ protected override void Run ()
+ {
+ if (AutoTestService.CurrentRecordSession == null) {
+ AutoTestService.StartRecordingSession ();
+ } else {
+ var selector = new FileSelectorDialog ("Save session as...", Gtk.FileChooserAction.Save);
+ try {
+ var result = MessageService.RunCustomDialog (selector, MessageService.RootWindow);
+
+ if (result == (int)Gtk.ResponseType.Cancel) {
+ return;
+ }
+
+ AutoTestService.StopRecordingSession (selector.Filename);
+ } finally {
+ selector.Destroy ();
+ }
+ }
+ }
+
+ protected override void Update (CommandInfo info)
+ {
+ info.Visible = IdeApp.Preferences.EnableAutomatedTesting;
+ info.Text = AutoTestService.CurrentRecordSession == null ? "Start Session Recorder" : "Stop Session Recorder";
+ }
+ }
+
+ internal class ReplaySessionHandler : CommandHandler
+ {
+ protected override void Run ()
+ {
+ var selector = new FileSelectorDialog ("Open session");
+ string filename = null;
+ try {
+ var result = MessageService.RunCustomDialog (selector, MessageService.RootWindow);
+
+ if (result == (int)Gtk.ResponseType.Cancel) {
+ return;
+ }
+
+ filename = selector.Filename;
+ } finally {
+ selector.Destroy ();
+ }
+ AutoTestService.ReplaySessionFromFile (filename);
+ }
+
+ protected override void Update (CommandInfo info)
+ {
+ info.Visible = IdeApp.Preferences.EnableAutomatedTesting;
+ }
+ }
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/WindowCommands.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/WindowCommands.cs
index b1ca6d43d4..3f758fce2e 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/WindowCommands.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/WindowCommands.cs
@@ -37,8 +37,9 @@ namespace MonoDevelop.Ide.Commands
{
public enum WindowCommands
{
- NextWindow,
- PrevWindow,
+ NextDocument,
+ PrevDocument,
+ OpenDocumentList,
OpenWindowList,
SplitWindowVertically,
SplitWindowHorizontally,
@@ -48,7 +49,7 @@ namespace MonoDevelop.Ide.Commands
SwitchPreviousDocument
}
- internal class NextWindowHandler : CommandHandler
+ internal class NextDocumentHandler : CommandHandler
{
protected override void Update (CommandInfo info)
{
@@ -70,7 +71,7 @@ namespace MonoDevelop.Ide.Commands
}
}
- internal class PrevWindowHandler : CommandHandler
+ internal class PrevDocumentHandler : CommandHandler
{
protected override void Update (CommandInfo info)
{
@@ -91,7 +92,7 @@ namespace MonoDevelop.Ide.Commands
}
}
- internal class OpenWindowListHandler : CommandHandler
+ internal class OpenDocumentListHandler : CommandHandler
{
protected override void Update (CommandArrayInfo info)
{
@@ -103,7 +104,7 @@ namespace MonoDevelop.Ide.Commands
commandInfo.Text = document.Window.Title.Replace ("_", "__");
if (document == IdeApp.Workbench.ActiveDocument)
commandInfo.Checked = true;
- commandInfo.Description = GettextCatalog.GetString ("Activate window '{0}'", commandInfo.Text);
+ commandInfo.Description = GettextCatalog.GetString ("Activate document '{0}'", commandInfo.Text);
if (document.Window.ShowNotification) {
commandInfo.UseMarkup = true;
commandInfo.Text = "<span foreground=" + '"' + "blue" + '"' + ">" + commandInfo.Text + "</span>";
@@ -129,6 +130,34 @@ namespace MonoDevelop.Ide.Commands
}
}
+ internal class OpenWindowListHandler : CommandHandler
+ {
+ protected override void Update (CommandArrayInfo info)
+ {
+ int i = 0;
+ foreach (Gtk.Window window in IdeApp.CommandService.TopLevelWindowStack) {
+
+ //Create CommandInfo object
+ CommandInfo commandInfo = new CommandInfo ();
+ commandInfo.Text = window.Title.Replace ("_", "__");
+ if (window.HasToplevelFocus)
+ commandInfo.Checked = true;
+ commandInfo.Description = GettextCatalog.GetString ("Activate window '{0}'", commandInfo.Text);
+
+ //Add menu item
+ info.Add (commandInfo, window);
+
+ i++;
+ }
+ }
+
+ protected override void Run (object dataItem)
+ {
+ Window window = (Window)dataItem;
+ window.Present ();
+ }
+ }
+
internal class SplitWindowVertically : CommandHandler
{
protected override void Update (CommandInfo info)
@@ -223,7 +252,7 @@ namespace MonoDevelop.Ide.Commands
{
//FIXME: does this option need to exist?
if (!PropertyService.Get ("MonoDevelop.Core.Gui.EnableDocumentSwitchDialog", true)) {
- IdeApp.CommandService.DispatchCommand (next? WindowCommands.NextWindow : WindowCommands.PrevWindow);
+ IdeApp.CommandService.DispatchCommand (next? WindowCommands.NextDocument : WindowCommands.PrevDocument);
return;
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Desktop/RecentOpen.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Desktop/RecentOpen.cs
index d5bc44bb67..8ad57a0cfa 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Desktop/RecentOpen.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Desktop/RecentOpen.cs
@@ -44,7 +44,7 @@ namespace MonoDevelop.Ide.Desktop
const string projGroup = "MonoDevelop Projects";
const string fileGroup = "MonoDevelop Files";
- const int ItemLimit = 10;
+ const int ItemLimit = 25;
public FdoRecentFiles () : this (RecentFileStorage.DefaultPath)
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindInFilesDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindInFilesDialog.cs
index 024869101c..51b808b831 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindInFilesDialog.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindInFilesDialog.cs
@@ -146,8 +146,13 @@ namespace MonoDevelop.Ide.FindInFiles
properties = PropertyService.Get ("MonoDevelop.FindReplaceDialogs.SearchOptions", new Properties ());
SetButtonIcon (toggleReplaceInFiles, "gtk-find-and-replace");
SetButtonIcon (toggleFindInFiles, "gtk-find");
-
- TransientFor = IdeApp.Workbench.RootWindow;
+
+ // If we have an active floating window, attach the dialog to it. Otherwise use the main IDE window.
+ var current_toplevel = Gtk.Window.ListToplevels ().FirstOrDefault (x => x.IsActive);
+ if (current_toplevel is Components.DockNotebook.DockWindow)
+ TransientFor = current_toplevel;
+ else
+ TransientFor = IdeApp.Workbench.RootWindow;
toggleReplaceInFiles.Active = showReplace;
toggleFindInFiles.Active = !showReplace;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/ExtensibleTreeView.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/ExtensibleTreeView.cs
index 9e0f7e6724..6f22cda97c 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/ExtensibleTreeView.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/ExtensibleTreeView.cs
@@ -195,11 +195,20 @@ namespace MonoDevelop.Ide.Gui.Components
tree.MotionNotifyEvent += HandleMotionNotifyEvent;
tree.LeaveNotifyEvent += HandleLeaveNotifyEvent;
+ if (GtkGestures.IsSupported) {
+ tree.AddGestureMagnifyHandler ((sender, args) => {
+ Zoom += Zoom * (args.Magnification / 4d);
+ });
+ }
+
for (int n=3; n<16; n++) {
Gtk.Rc.ParseString ("style \"MonoDevelop.ExtensibleTreeView_" + n + "\" {\n GtkTreeView::expander-size = " + n + "\n }\n");
Gtk.Rc.ParseString ("widget \"*.MonoDevelop.ExtensibleTreeView_" + n + "\" style \"MonoDevelop.ExtensibleTreeView_" + n + "\"\n");
}
+ if (!string.IsNullOrEmpty (Id))
+ Zoom = PropertyService.Get<double> ("MonoDevelop.Ide.ExtensibleTreeView.Zoom." + Id, 1d);
+
this.Add (tree);
this.ShowAll ();
@@ -244,8 +253,9 @@ namespace MonoDevelop.Ide.Gui.Components
var info = (NodeInfo)model.GetValue (it, NodeInfoColumn);
var cell = (ZoomableCellRendererPixbuf)renderer;
- cell.Image = info.Icon != null && info.Icon != CellRendererImage.NullImage && info.DisabledStyle ? info.Icon.WithAlpha (0.5) : info.Icon;
- cell.ImageExpanderOpen = cell.Image;
+ var img = info.Icon != null && info.Icon != CellRendererImage.NullImage && info.DisabledStyle ? info.Icon.WithAlpha (0.5) : info.Icon;
+ cell.Image = img;
+ cell.ImageExpanderOpen = img;
cell.ImageExpanderClosed = info.ClosedIcon != null && info.ClosedIcon != CellRendererImage.NullImage && info.DisabledStyle ? info.ClosedIcon.WithAlpha (0.5) : info.ClosedIcon;
cell.OverlayBottomLeft = info.OverlayBottomLeft;
cell.OverlayBottomRight = info.OverlayBottomRight;
@@ -1019,12 +1029,92 @@ namespace MonoDevelop.Ide.Gui.Components
public event EventHandler CurrentItemActivated;
- [Obsolete ("Not supported anymore")]
+ #region Zoom
+
+ const double ZOOM_FACTOR = 1.1f;
+ const int ZOOM_MIN_POW = -4;
+ const int ZOOM_MAX_POW = 8;
+ static readonly double ZOOM_MIN = System.Math.Pow (ZOOM_FACTOR, ZOOM_MIN_POW);
+ static readonly double ZOOM_MAX = System.Math.Pow (ZOOM_FACTOR, ZOOM_MAX_POW);
+ double zoom;
+
public double Zoom {
- get { return 1d; }
- set { }
+ get {
+ return zoom;
+ }
+ set {
+ value = System.Math.Min (ZOOM_MAX, System.Math.Max (ZOOM_MIN, value));
+ if (value > ZOOM_MAX || value < ZOOM_MIN)
+ return;
+ //snap to one, if within 0.001d
+ if ((System.Math.Abs (value - 1d)) < 0.001d) {
+ value = 1d;
+ }
+ if (zoom != value) {
+ zoom = value;
+ OnZoomChanged (value);
+ }
+ }
}
+ void OnZoomChanged (double value)
+ {
+ pix_render.Zoom = value;
+ text_render.Zoom = value;
+
+ int expanderSize = (int) (12 * Zoom);
+ if (expanderSize < 3) expanderSize = 3;
+ if (expanderSize > 15) expanderSize = 15;
+ if (expanderSize != 12)
+ tree.Name = "MonoDevelop.ExtensibleTreeView_" + expanderSize;
+ else
+ tree.Name = "";
+ tree.ColumnsAutosize ();
+ if (!string.IsNullOrEmpty (Id)) {
+ PropertyService.Set ("MonoDevelop.Ide.ExtensibleTreeView.Zoom." + Id, Zoom);
+ }
+ }
+
+ [CommandHandler (ViewCommands.ZoomIn)]
+ public void ZoomIn ()
+ {
+ int oldPow = (int)System.Math.Round (System.Math.Log (zoom) / System.Math.Log (ZOOM_FACTOR));
+ Zoom = System.Math.Pow (ZOOM_FACTOR, oldPow + 1);
+ }
+
+ [CommandHandler (ViewCommands.ZoomOut)]
+ public void ZoomOut ()
+ {
+ int oldPow = (int)System.Math.Round (System.Math.Log (zoom) / System.Math.Log (ZOOM_FACTOR));
+ Zoom = System.Math.Pow (ZOOM_FACTOR, oldPow - 1);
+ }
+
+ [CommandHandler (ViewCommands.ZoomReset)]
+ public void ZoomReset ()
+ {
+ Zoom = 1d;
+ }
+
+ [CommandUpdateHandler (ViewCommands.ZoomIn)]
+ protected void UpdateZoomIn (CommandInfo cinfo)
+ {
+ cinfo.Enabled = zoom < ZOOM_MAX - 0.000001d;
+ }
+
+ [CommandUpdateHandler (ViewCommands.ZoomOut)]
+ protected void UpdateZoomOut (CommandInfo cinfo)
+ {
+ cinfo.Enabled = zoom > ZOOM_MIN + 0.000001d;
+ }
+
+ [CommandUpdateHandler (ViewCommands.ZoomReset)]
+ protected void UpdateZoomReset (CommandInfo cinfo)
+ {
+ cinfo.Enabled = zoom != 1d;
+ }
+
+ #endregion Zoom
+
[CommandHandler (EditCommands.Copy)]
public void CopyCurrentItem ()
{
@@ -1783,7 +1873,9 @@ namespace MonoDevelop.Ide.Gui.Components
void ShowPopup (Gdk.EventButton evt)
{
- var entryset = BuildEntrySet () ?? new CommandEntrySet ();
+ var entryset = BuildEntrySet ();
+ if (entryset == null)
+ return;
if (evt == null) {
var paths = tree.Selection.GetSelectedRows ();
@@ -1950,6 +2042,24 @@ namespace MonoDevelop.Ide.Gui.Components
}
}
+ protected override bool OnScrollEvent (Gdk.EventScroll evnt)
+ {
+ var modifier = !Platform.IsMac? Gdk.ModifierType.ControlMask
+ //Mac window manager already uses control-scroll, so use command
+ //Command might be either meta or mod1, depending on GTK version
+ : (Gdk.ModifierType.MetaMask | Gdk.ModifierType.Mod1Mask);
+
+ if ((evnt.State & modifier) !=0) {
+ if (evnt.Direction == Gdk.ScrollDirection.Up)
+ ZoomIn ();
+ else if (evnt.Direction == Gdk.ScrollDirection.Down)
+ ZoomOut ();
+
+ return true;
+ }
+ return base.OnScrollEvent (evnt);
+ }
+
protected virtual void OnNodeActivated (object sender, Gtk.RowActivatedArgs args)
{
ActivateCurrentItem ();
@@ -2248,6 +2358,7 @@ namespace MonoDevelop.Ide.Gui.Components
class CustomCellRendererText: Gtk.CellRendererText
{
+ double zoom;
Pango.Layout layout;
Pango.FontDescription scaledFont, customFont;
@@ -2309,7 +2420,7 @@ namespace MonoDevelop.Ide.Gui.Components
if (scaledFont != null)
scaledFont.Dispose ();
scaledFont = (customFont ?? parent.Style.FontDesc).Copy ();
- scaledFont.Size = customFont.Size;
+ scaledFont.Size = (int)(customFont.Size * Zoom);
if (layout != null)
layout.FontDescription = scaledFont;
}
@@ -2455,6 +2566,19 @@ namespace MonoDevelop.Ide.Gui.Components
width += (int) StatusIcon.Width + StatusIconSpacing;
}
+ public double Zoom {
+ get {
+ return zoom;
+ }
+ set {
+ if (scaledFont != null) {
+ scaledFont.Dispose ();
+ scaledFont = null;
+ }
+ zoom = value;
+ }
+ }
+
public bool PointerInButton (int px, int py)
{
return buttonScreenRect.Contains (px, py);
@@ -2535,6 +2659,8 @@ namespace MonoDevelop.Ide.Gui.Components
class ZoomableCellRendererPixbuf: CellRendererImage
{
+ double zoom = 1f;
+
Dictionary<Xwt.Drawing.Image,Xwt.Drawing.Image> resizedCache = new Dictionary<Xwt.Drawing.Image, Xwt.Drawing.Image> ();
Xwt.Drawing.Image overlayBottomLeft;
@@ -2542,6 +2668,17 @@ namespace MonoDevelop.Ide.Gui.Components
Xwt.Drawing.Image overlayTopLeft;
Xwt.Drawing.Image overlayTopRight;
+ public double Zoom {
+ get { return zoom; }
+ set {
+ if (zoom != value) {
+ zoom = value;
+ resizedCache.Clear ();
+ Notify ("image");
+ }
+ }
+ }
+
public override Xwt.Drawing.Image Image {
get {
return base.Image;
@@ -2616,7 +2753,20 @@ namespace MonoDevelop.Ide.Gui.Components
if (value == null || value == CellRendererImage.NullImage)
return null;
- return value;
+ if (zoom == 1)
+ return value;
+
+ Xwt.Drawing.Image resized;
+ if (resizedCache.TryGetValue (value, out resized))
+ return resized;
+
+ int w = (int) (zoom * (double) value.Width);
+ int h = (int) (zoom * (double) value.Height);
+ if (w == 0) w = 1;
+ if (h == 0) h = 1;
+ resized = value.WithSize (w, h);
+ resizedCache [value] = resized;
+ return resized;
}
public override void GetSize (Gtk.Widget widget, ref Gdk.Rectangle cell_area, out int x_offset, out int y_offset, out int width, out int height)
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/LogView.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/LogView.cs
index 17a65a2364..9932f93145 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/LogView.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/LogView.cs
@@ -112,8 +112,11 @@ namespace MonoDevelop.Ide.Gui.Components
var clipboard = Clipboard.Get (Gdk.Atom.Intern ("CLIPBOARD", false));
clipboard.Text = text;
- clipboard = Clipboard.Get (Gdk.Atom.Intern ("PRIMARY", false));
- clipboard.Text = text;
+ if (Platform.IsLinux) {
+ // gtk has different clipboards for CLIPBOARD and PRIMARY only on Linux.
+ clipboard = Clipboard.Get (Gdk.Atom.Intern ("PRIMARY", false));
+ clipboard.Text = text;
+ }
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/DirtyFilesDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/DirtyFilesDialog.cs
index 290c2f37a5..85be8e40f3 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/DirtyFilesDialog.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/DirtyFilesDialog.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections;
+using System.Collections.Generic;
using Gtk;
@@ -10,7 +11,6 @@ namespace MonoDevelop.Ide.Gui.Dialogs
{
internal class DirtyFilesDialog : Gtk.Dialog
{
-
Button btnSaveAndQuit;
Button btnQuit;
Button btnCancel;
@@ -18,21 +18,26 @@ namespace MonoDevelop.Ide.Gui.Dialogs
TreeStore tsFiles;
CellRendererToggle togRender;
CellRendererText textRender;
-
- public DirtyFilesDialog () : base (GettextCatalog.GetString ("Save Files"), IdeApp.Workbench.RootWindow, DialogFlags.Modal)
+
+ public DirtyFilesDialog () : this (IdeApp.Workbench.Documents, true, true)
+ {
+ }
+
+ public DirtyFilesDialog (IReadOnlyList<Document> docs, bool closeWorkspace, bool groupByProject) :
+ base (GettextCatalog.GetString ("Save Files"), IdeApp.Workbench.RootWindow, DialogFlags.Modal)
{
tsFiles = new TreeStore (typeof(string), typeof(bool), typeof(SdiWorkspaceWindow), typeof(bool));
tvFiles = new TreeView (tsFiles);
TreeIter topCombineIter = TreeIter.Zero;
Hashtable projectIters = new Hashtable ();
- foreach (Document doc in IdeApp.Workbench.Documents) {
+ foreach (Document doc in docs) {
if (!doc.IsDirty)
continue;
IViewContent viewcontent = doc.Window.ViewContent;
- if (viewcontent.Project != null) {
+ if (groupByProject && viewcontent.Project != null) {
TreeIter projIter = TreeIter.Zero;
if (projectIters.ContainsKey (viewcontent.Project))
projIter = (TreeIter)projectIters [viewcontent.Project];
@@ -79,9 +84,9 @@ namespace MonoDevelop.Ide.Gui.Dialogs
sc.BorderWidth = 6;
this.VBox.PackStart (sc, true, true, 6);
-
- btnSaveAndQuit = new Button (GettextCatalog.GetString ("_Save and Quit"));
- btnQuit = new Button (Gtk.Stock.Quit);
+
+ btnSaveAndQuit = new Button (closeWorkspace ? GettextCatalog.GetString ("_Save and Quit") : GettextCatalog.GetString ("_Save and Close"));
+ btnQuit = new Button (closeWorkspace ? Gtk.Stock.Quit : Gtk.Stock.Close);
btnCancel = new Button (Gtk.Stock.Cancel);
btnSaveAndQuit.Clicked += SaveAndQuit;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/OpenFileDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/OpenFileDialog.cs
index 430502ff21..62e39f17a9 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/OpenFileDialog.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/OpenFileDialog.cs
@@ -25,12 +25,10 @@
// THE SOFTWARE.
using System;
-using MonoDevelop.Core;
+using System.Text;
+
using MonoDevelop.Ide.Extensions;
using MonoDevelop.Components.Extensions;
-using System.Collections.Generic;
-using Mono.Addins;
-using System.Text;
namespace MonoDevelop.Ide.Gui.Dialogs
{
@@ -43,11 +41,11 @@ namespace MonoDevelop.Ide.Gui.Dialogs
{
}
- public OpenFileDialog (string title) : this (title, Gtk.FileChooserAction.Save)
+ public OpenFileDialog (string title) : this (title, SelectFileDialogAction.Save)
{
}
- public OpenFileDialog (string title, Gtk.FileChooserAction action)
+ public OpenFileDialog (string title, SelectFileDialogAction action)
{
Title = title;
Action = action;
@@ -90,10 +88,20 @@ namespace MonoDevelop.Ide.Gui.Dialogs
public FileViewer SelectedViewer {
get { return data.SelectedViewer; }
}
+
+ Gtk.FileChooserAction GetFileChooserAction ()
+ {
+ switch (Action) {
+ case SelectFileDialogAction.CreateFolder: return Gtk.FileChooserAction.CreateFolder;
+ case SelectFileDialogAction.SelectFolder: return Gtk.FileChooserAction.SelectFolder;
+ case SelectFileDialogAction.Save: return Gtk.FileChooserAction.Save;
+ default: return Gtk.FileChooserAction.Open;
+ }
+ }
protected override bool RunDefault ()
{
- var win = new FileSelectorDialog (Title, Action);
+ var win = new FileSelectorDialog (Title, GetFileChooserAction ());
win.SelectedEncoding = Encoding != null ? Encoding.CodePage : 0;
win.ShowEncodingSelector = ShowEncodingSelector;
win.ShowViewerSelector = ShowViewerSelector;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/KeyBindingsPanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/KeyBindingsPanel.cs
index 30136aceae..f1754c228c 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/KeyBindingsPanel.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/KeyBindingsPanel.cs
@@ -431,25 +431,29 @@ namespace MonoDevelop.Ide.Gui.OptionPanels
return;
}
globalWarningBox.Show ();
- conflicButton.MenuCreator = delegate {
- Menu menu = new Menu ();
+
+ conflicButton.ContextMenuRequested = delegate {
+ ContextMenu menu = new ContextMenu ();
+ bool first = true;
+
foreach (KeyBindingConflict conf in conflicts) {
- if (menu.Children.Length > 0) {
- SeparatorMenuItem it = new SeparatorMenuItem ();
- it.Show ();
- menu.Insert (it, -1);
+ if (first == false) {
+ ContextMenuItem item = new SeparatorContextMenuItem ();
+ menu.Items.Add (item);
}
+
foreach (Command cmd in conf.Commands) {
string txt = currentBindings.GetBinding (cmd) + " - " + cmd.Text;
- MenuItem item = new MenuItem (txt);
+ ContextMenuItem item = new ContextMenuItem (txt);
Command localCmd = cmd;
- item.Activated += delegate {
- SelectCommand (localCmd);
- };
- item.Show ();
- menu.Insert (item, -1);
+
+ item.Clicked += (sender, e) => SelectCommand (localCmd);
+
+ menu.Items.Add (item);
+ first = false;
}
}
+
return menu;
};
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/FolderNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/FolderNodeBuilder.cs
index 0734f172b9..2d9e6c4a76 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/FolderNodeBuilder.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/FolderNodeBuilder.cs
@@ -90,6 +90,9 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad
{
string dir;
+ if (!file.Visible || file.Flags.HasFlag (ProjectItemFlags.Hidden))
+ continue;
+
if (file.Subtype != Subtype.Directory) {
if (file.DependsOnFile != null)
continue;
@@ -130,6 +133,8 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad
foreach (var file in project.Files) {
FilePath path;
+ if (!file.Visible || file.Flags.HasFlag (ProjectItemFlags.Hidden))
+ continue;
if (file.Subtype != Subtype.Directory)
path = file.IsLink ? project.BaseDirectory.Combine (file.ProjectVirtualPath) : file.FilePath;
else
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFileNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFileNodeBuilder.cs
index ca2204543b..57608e02bb 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFileNodeBuilder.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFileNodeBuilder.cs
@@ -224,60 +224,6 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad
return DragOperation.Copy | DragOperation.Move;
}
- public override bool CanDropNode (object dataObject, DragOperation operation)
- {
- var target = (ProjectFile) CurrentNode.DataItem;
- var pf = dataObject as ProjectFile;
-
- return pf != null && pf != target && !pf.HasChildren && target.DependsOn == null;
- }
-
- void Drop (ProjectFile pf, DragOperation operation, HashSet<SolutionEntityItem> projectsToSave)
- {
- var target = (ProjectFile) CurrentNode.DataItem;
- var targetDirectory = target.FilePath.ParentDirectory;
-
- // file dependencies only work if they are in the same physical folder
- if (pf.FilePath.ParentDirectory != targetDirectory) {
- var targetPath = targetDirectory.Combine (pf.FilePath.FileName);
-
- // if copying to the same directory, make a copy with a different name
- if (targetPath == pf.FilePath)
- targetPath = ProjectOperations.GetTargetCopyName (targetPath, false);
-
- if (File.Exists (targetPath))
- if (!MessageService.Confirm (GettextCatalog.GetString ("The file '{0}' already exists. Do you want to overwrite it?", targetPath.FileName), AlertButton.OverwriteFile))
- return;
-
- // unlink the project file from its current parent
- pf.DependsOn = null;
-
- projectsToSave.Add (pf.Project);
-
- bool move = operation == DragOperation.Move;
- var opText = move ? GettextCatalog.GetString ("Moving file...") : GettextCatalog.GetString ("Copying file...");
-
- using (var monitor = IdeApp.Workbench.ProgressMonitors.GetStatusProgressMonitor (opText, Stock.StatusWorking, true))
- IdeApp.ProjectOperations.TransferFiles (monitor, pf.Project, pf.FilePath, target.Project, targetPath, move, true);
-
- pf = target.Project.Files.GetFile (targetPath);
- }
-
- // the dropped project file now depends on the file it was just dropped onto
- pf.DependsOn = target.FilePath.FileName;
- projectsToSave.Add (pf.Project);
- }
-
- public override void OnMultipleNodeDrop (object[] dataObjects, DragOperation operation)
- {
- var projectsToSave = new HashSet<SolutionEntityItem> ();
-
- foreach (var dataObject in dataObjects)
- Drop ((ProjectFile) dataObject, operation, projectsToSave);
-
- IdeApp.ProjectOperations.Save (projectsToSave);
- }
-
public override bool CanDeleteItem ()
{
return true;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFolderNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFolderNodeBuilder.cs
index 26b22e7047..28c623f1cf 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFolderNodeBuilder.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFolderNodeBuilder.cs
@@ -198,16 +198,16 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad
"The Delete option permanently removes the directory and any files it contains from your hard disk. " +
"Click Remove from Project if you only want to remove it from your current solution.")
};
- question.Buttons.Add (AlertButton.Cancel);
question.Buttons.Add (AlertButton.Delete);
question.Buttons.Add (removeButton);
+ question.Buttons.Add (AlertButton.Cancel);
var deleteOnlyQuestion = new QuestionMessage () {
AllowApplyToAll = folders.Count > 1,
SecondaryText = GettextCatalog.GetString ("The directory and any files it contains will be permanently removed from your hard disk. ")
};
- deleteOnlyQuestion.Buttons.Add (AlertButton.Cancel);
deleteOnlyQuestion.Buttons.Add (AlertButton.Delete);
+ deleteOnlyQuestion.Buttons.Add (AlertButton.Cancel);
foreach (var folder in folders) {
var project = folder.Project;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectNodeBuilder.cs
index b10b6ad8ff..28ac0a8e8a 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectNodeBuilder.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectNodeBuilder.cs
@@ -222,6 +222,9 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad
void AddFile (ProjectFile file, Project project)
{
+ if (!file.Visible || file.Flags.HasFlag (ProjectItemFlags.Hidden))
+ return;
+
ITreeBuilder tb = Context.GetTreeBuilder ();
if (file.DependsOnFile != null) {
@@ -402,9 +405,12 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad
public void SetAsStartupProject ()
{
Project project = CurrentNode.DataItem as Project;
- project.ParentSolution.SingleStartup = true;
project.ParentSolution.StartupItem = project;
- IdeApp.ProjectOperations.Save (project.ParentSolution);
+ if (!project.ParentSolution.SingleStartup) {
+ project.ParentSolution.SingleStartup = true;
+ IdeApp.ProjectOperations.Save (project.ParentSolution);
+ } else
+ project.ParentSolution.SaveUserProperties ();
}
public override void DeleteItem ()
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/ErrorListPad.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/ErrorListPad.cs
index d5fb26cf09..5ac9296bad 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/ErrorListPad.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/ErrorListPad.cs
@@ -49,6 +49,7 @@ using MonoDevelop.Ide.Gui.Components;
using MonoDevelop.Components.Commands;
using MonoDevelop.Ide.Commands;
using MonoDevelop.Components;
+using System.Linq;
namespace MonoDevelop.Ide.Gui.Pads
{
@@ -125,7 +126,7 @@ namespace MonoDevelop.Ide.Gui.Pads
DockItemToolbar toolbar = window.GetToolbar (PositionType.Top);
- errorBtn = new ToggleButton ();
+ errorBtn = new ToggleButton { Name = "toggleErrors" };
errorBtn.Active = (bool)PropertyService.Get (showErrorsPropertyName, true);
errorBtn.Image = new Gtk.Image (Stock.Error, Gtk.IconSize.Menu);
errorBtn.Image.Show ();
@@ -134,7 +135,7 @@ namespace MonoDevelop.Ide.Gui.Pads
UpdateErrorsNum();
toolbar.Add (errorBtn);
- warnBtn = new ToggleButton ();
+ warnBtn = new ToggleButton { Name = "toggleWarnings" };
warnBtn.Active = (bool)PropertyService.Get (showWarningsPropertyName, true);
warnBtn.Image = new Gtk.Image (Stock.Warning, Gtk.IconSize.Menu);
warnBtn.Image.Show ();
@@ -143,7 +144,7 @@ namespace MonoDevelop.Ide.Gui.Pads
UpdateWarningsNum();
toolbar.Add (warnBtn);
- msgBtn = new ToggleButton ();
+ msgBtn = new ToggleButton { Name = "toggleMessages" };
msgBtn.Active = (bool)PropertyService.Get (showMessagesPropertyName, true);
msgBtn.Image = new Gtk.Image (Stock.Information, Gtk.IconSize.Menu);
msgBtn.Image.Show ();
@@ -154,7 +155,7 @@ namespace MonoDevelop.Ide.Gui.Pads
toolbar.Add (new SeparatorToolItem ());
- logBtn = new ToggleButton ();
+ logBtn = new ToggleButton { Name = "toggleBuildOutput" };
logBtn.Label = GettextCatalog.GetString ("Build Output");
logBtn.Image = ImageService.GetImage ("md-message-log", Gtk.IconSize.Menu);
logBtn.Image.Show ();
@@ -230,7 +231,7 @@ namespace MonoDevelop.Ide.Gui.Pads
control.Add1 (sw);
- outputView = new LogView ();
+ outputView = new LogView { Name = "buildOutput" };
control.Add2 (outputView);
Control.ShowAll ();
@@ -302,31 +303,20 @@ namespace MonoDevelop.Ide.Gui.Pads
void LoadColumnsVisibility ()
{
- string columns = (string)PropertyService.Get ("Monodevelop.ErrorListColumns", "TRUE;TRUE;TRUE;TRUE;TRUE;TRUE;TRUE");
- string[] tokens = columns.Split (new char[] {';'}, StringSplitOptions.RemoveEmptyEntries);
- if (tokens.Length == 7 && view != null && view.Columns.Length == 7)
- {
- for (int i = 0; i < 7; i++)
- {
+ var columns = PropertyService.Get ("Monodevelop.ErrorListColumns", string.Join (";", Enumerable.Repeat ("TRUE", view.Columns.Length)));
+ var tokens = columns.Split (new [] { ';' }, StringSplitOptions.RemoveEmptyEntries);
+ if (view.Columns.Length == tokens.Length) {
+ for (int i = 0; i < tokens.Length; i++) {
bool visible;
- if (bool.TryParse (tokens[i], out visible))
- view.Columns[i].Visible = visible;
+ if (bool.TryParse (tokens [i], out visible))
+ view.Columns [i].Visible = visible;
}
}
}
void StoreColumnsVisibility ()
{
- string columns = String.Format ("{0};{1};{2};{3};{4};{5};{6};{7}",
- view.Columns[VisibleColumns.Type].Visible,
- view.Columns[VisibleColumns.Marked].Visible,
- view.Columns[VisibleColumns.Line].Visible,
- view.Columns[VisibleColumns.Description].Visible,
- view.Columns[VisibleColumns.File].Visible,
- view.Columns[VisibleColumns.Project].Visible,
- view.Columns[VisibleColumns.Path].Visible,
- view.Columns[VisibleColumns.Category].Visible);
- PropertyService.Set ("Monodevelop.ErrorListColumns", columns);
+ PropertyService.Set ("Monodevelop.ErrorListColumns", string.Join (";", view.Columns.Select (c => c.Visible ? "TRUE" : "FALSE")));
}
public void RedrawContent()
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/MonodocTreePad.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/MonodocTreePad.cs
index 915ae8612a..0eb985da7d 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/MonodocTreePad.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/MonodocTreePad.cs
@@ -46,7 +46,7 @@ namespace MonoDevelop.Ide.Gui.Pads
ScrolledWindow scroller;
TreeIter root_iter;
- public HelpTree () : base (GettextCatalog.GetString ("Help"), "md-help")
+ public HelpTree () : base (GettextCatalog.GetString ("Help"), Stock.Help)
{
tree_view = new MonoDevelop.Ide.Gui.Components.PadTreeView ();
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DefaultWorkbench.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DefaultWorkbench.cs
index 58d6768512..82a7646774 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DefaultWorkbench.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DefaultWorkbench.cs
@@ -1028,7 +1028,8 @@ namespace MonoDevelop.Ide.Gui
protected override bool OnConfigureEvent (Gdk.EventConfigure evnt)
{
SetActiveWidget (Focus);
- return base.OnConfigureEvent (evnt);
+ base.OnConfigureEvent (evnt);
+ return false;
}
protected override bool OnFocusInEvent (Gdk.EventFocus evnt)
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Document.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Document.cs
index 069845ada8..d3a12756c6 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Document.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Document.cs
@@ -52,6 +52,7 @@ using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using System.Text;
using System.Collections.ObjectModel;
+using MonoDevelop.Components.Extensions;
namespace MonoDevelop.Ide.Gui
{
@@ -414,7 +415,7 @@ namespace MonoDevelop.Ide.Gui
}
if (filename == null) {
- var dlg = new OpenFileDialog (GettextCatalog.GetString ("Save as..."), FileChooserAction.Save) {
+ var dlg = new OpenFileDialog (GettextCatalog.GetString ("Save as..."), SelectFileDialogAction.Save) {
TransientFor = IdeApp.Workbench.RootWindow,
Encoding = encoding,
ShowEncodingSelector = (tbuffer != null),
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/ProgressMonitors.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/ProgressMonitors.cs
index 05d64ce084..5e50878b93 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/ProgressMonitors.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/ProgressMonitors.cs
@@ -77,7 +77,7 @@ namespace MonoDevelop.Ide.Gui
public IProgressMonitor GetRunProgressMonitor ()
{
- return GetOutputProgressMonitor ("MonoDevelop.Ide.ApplicationOutput", GettextCatalog.GetString ("Application Output"), Stock.RunProgramIcon, true, true);
+ return GetOutputProgressMonitor ("MonoDevelop.Ide.ApplicationOutput", GettextCatalog.GetString ("Application Output"), Stock.RunProgramIcon, false, true);
}
public IProgressMonitor GetToolOutputProgressMonitor (bool bringToFront)
@@ -102,7 +102,7 @@ namespace MonoDevelop.Ide.Gui
public IConsole CreateConsole (bool closeOnDispose)
{
- return (IConsole) GetOutputProgressMonitor ("MonoDevelop.Ide.ApplicationOutput", GettextCatalog.GetString ("Application Output"), Stock.MessageLog, true, true);
+ return (IConsole) GetOutputProgressMonitor ("MonoDevelop.Ide.ApplicationOutput", GettextCatalog.GetString ("Application Output"), Stock.MessageLog, false, true);
}
/******************************/
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/StatusProgressMonitor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/StatusProgressMonitor.cs
index 65c7eb0d09..752f262e12 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/StatusProgressMonitor.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/StatusProgressMonitor.cs
@@ -90,32 +90,28 @@ namespace MonoDevelop.Ide.Gui
statusBar.EndProgress ();
- if (!IsCancelRequested) {
- try {
- if (Errors.Count > 0 || Warnings.Count > 0) {
- if (Errors.Count > 0) {
- statusBar.ShowError (Errors [Errors.Count - 1]);
- } else if (SuccessMessages.Count == 0) {
- statusBar.ShowWarning (Warnings [Warnings.Count - 1]);
- }
+ try {
+ if (Errors.Count > 0 || Warnings.Count > 0) {
+ if (Errors.Count > 0) {
+ statusBar.ShowError (Errors [Errors.Count - 1]);
+ } else if (SuccessMessages.Count == 0) {
+ statusBar.ShowWarning (Warnings [Warnings.Count - 1]);
+ }
- DesktopService.ShowGlobalProgressError ();
+ DesktopService.ShowGlobalProgressError ();
- base.OnCompleted ();
-
- if (showErrorDialogs)
- ShowResultDialog ();
- return;
- }
+ base.OnCompleted ();
- if (SuccessMessages.Count > 0)
- statusBar.ShowMessage (MonoDevelop.Ide.Gui.Stock.StatusSuccess, SuccessMessages [SuccessMessages.Count - 1]);
-
- } finally {
- statusBar.StatusSourcePad = statusSourcePad;
- statusBar.Dispose ();
+ if (!IsCancelRequested && showErrorDialogs)
+ ShowResultDialog ();
+ return;
}
- } else {
+
+ if (SuccessMessages.Count > 0)
+ statusBar.ShowMessage (MonoDevelop.Ide.Gui.Stock.StatusSuccess, SuccessMessages [SuccessMessages.Count - 1]);
+
+ } finally {
+ statusBar.StatusSourcePad = statusSourcePad;
statusBar.Dispose ();
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs
index 01ea62b0ca..58e4750c86 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs
@@ -201,6 +201,14 @@ namespace MonoDevelop.Ide.Gui
return false;
if (toplevel == RootWindow)
return true;
+ #if WIN32
+ var app = System.Windows.Application.Current;
+ if (app != null) {
+ var wpfWindow = app.Windows.OfType<System.Windows.Window>().SingleOrDefault (x => x.IsActive);
+ if (wpfWindow != null)
+ return true;
+ }
+ #endif
var dock = toplevel as DockFloatingWindow;
return dock != null && dock.DockParent == RootWindow;
}
@@ -311,6 +319,37 @@ namespace MonoDevelop.Ide.Gui
foreach (Document doc in docs)
doc.Save ();
}
+
+ internal bool SaveAllDirtyFiles ()
+ {
+ Document[] docs = Documents.Where (doc => doc.IsDirty && doc.Window.ViewContent != null).ToArray ();
+ if (!docs.Any ())
+ return true;
+
+ foreach (Document doc in docs) {
+ AlertButton result = PromptToSaveChanges (doc);
+ if (result == AlertButton.Cancel)
+ return false;
+
+ doc.Save ();
+ if (doc.IsDirty) {
+ doc.Select ();
+ return false;
+ }
+ }
+ return true;
+ }
+
+ static AlertButton PromptToSaveChanges (Document doc)
+ {
+ return MessageService.GenericAlert (MonoDevelop.Ide.Gui.Stock.Warning,
+ GettextCatalog.GetString ("Save the changes to document '{0}' before creating a new solution?",
+ doc.Window.ViewContent.IsUntitled
+ ? doc.Window.ViewContent.UntitledName
+ : System.IO.Path.GetFileName (doc.FileName)),
+ "",
+ AlertButton.Cancel, doc.Window.ViewContent.IsUntitled ? AlertButton.SaveAs : AlertButton.Save);
+ }
public void CloseAllDocuments (bool leaveActiveDocumentOpen)
{
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Navigation/NavigationHistoryService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Navigation/NavigationHistoryService.cs
index a1af09c25c..c8ff32acb6 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Navigation/NavigationHistoryService.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Navigation/NavigationHistoryService.cs
@@ -349,12 +349,11 @@ namespace MonoDevelop.Ide.Navigation
bool closedHistoryChanged = false;
foreach (ProjectFileRenamedEventInfo args in e) {
foreach (NavigationHistoryItem point in history) {
- DocumentNavigationPoint dp = point.NavigationPoint as DocumentNavigationPoint;
+ var dp = point.NavigationPoint as DocumentNavigationPoint;
historyChanged &= (dp != null && dp.HandleRenameEvent (args.OldName, args.NewName));
- }
- foreach (NavigationHistoryItem point in history) {
- DocumentNavigationPoint cdp = point.NavigationPoint as DocumentNavigationPoint;
- closedHistoryChanged &= (cdp != null && cdp.HandleRenameEvent (args.OldName, args.NewName));
+ closedHistoryChanged &= (dp != null && dp.HandleRenameEvent (args.OldName, args.NewName));
+ if (historyChanged && closedHistoryChanged)
+ break;
}
}
if (historyChanged)
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AddExternalFileDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AddExternalFileDialog.cs
index 10a0e87b66..111d928081 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AddExternalFileDialog.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AddExternalFileDialog.cs
@@ -37,6 +37,7 @@ namespace MonoDevelop.Ide.Projects
radioCopy.Active = true;
labelTitle.Markup = GettextCatalog.GetString (labelTitle.Text, "<b>" + GLib.Markup.EscapeText (file) + "</b>");
Resizable = false;
+ buttonOk.GrabFocus ();
}
public void ShowKeepOption (string dir)
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AddFileDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AddFileDialog.cs
index 6377843060..512bcf6940 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AddFileDialog.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AddFileDialog.cs
@@ -42,7 +42,7 @@ namespace MonoDevelop.Ide.Projects
public AddFileDialog (string title)
{
Title = title;
- Action = FileChooserAction.Open;
+ Action = SelectFileDialogAction.Open;
data.SelectMultiple = true;
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AssemblyReferencePanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AssemblyReferencePanel.cs
index 7c53d25e86..4bc2a95b56 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AssemblyReferencePanel.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AssemblyReferencePanel.cs
@@ -150,7 +150,7 @@ namespace MonoDevelop.Ide.Projects
void HandleClicked (object sender, EventArgs e)
{
- var dlg = new OpenFileDialog (GettextCatalog.GetString ("Select Assembly"), FileChooserAction.Open);
+ var dlg = new OpenFileDialog (GettextCatalog.GetString ("Select Assembly"), SelectFileDialogAction.Open);
// dlg.AddFilter (GettextCatalog.GetString ("Assemblies"), "*.[Dd][Ll][Ll]", "*.[Ee][Xx][Ee]");
dlg.AddFilter (GettextCatalog.GetString ("Assemblies"), "*.dll", "*.exe");
dlg.CurrentFolder = basePath;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/DefaultPolicyOptionsDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/DefaultPolicyOptionsDialog.cs
index 22ec6051b6..c226b12acd 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/DefaultPolicyOptionsDialog.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/DefaultPolicyOptionsDialog.cs
@@ -37,6 +37,7 @@ using MonoDevelop.Components;
using Gtk;
using System.Linq;
using MonoDevelop.Projects;
+using MonoDevelop.Components.Extensions;
namespace MonoDevelop.Ide.Projects
{
@@ -72,37 +73,44 @@ namespace MonoDevelop.Ide.Projects
exportButton = new MenuButton ();
exportButton.Label = GettextCatalog.GetString ("Export");
- exportButton.MenuCreator = delegate {
- Gtk.Menu menu = new Gtk.Menu ();
- MenuItem mi = new MenuItem (GettextCatalog.GetString ("To file..."));
- mi.Activated += HandleToFile;
- menu.Insert (mi, -1);
- mi = new MenuItem (GettextCatalog.GetString ("To project or solution..."));
- mi.Activated += HandleToProject;
- if (!IdeApp.Workspace.IsOpen)
- mi.Sensitive = false;
- menu.Insert (mi, -1);
- menu.ShowAll ();
+ exportButton.ContextMenuRequested = delegate {
+ ContextMenu menu = new ContextMenu ();
+
+ ContextMenuItem item = new ContextMenuItem (GettextCatalog.GetString ("To file..."));
+ item.Clicked += HandleToFile;
+ menu.Items.Add (item);
+
+ item = new ContextMenuItem (GettextCatalog.GetString ("To project or solution..."));
+ item.Clicked += HandleToProject;
+ if (!IdeApp.Workspace.IsOpen) {
+ item.Sensitive = false;
+ }
+ menu.Items.Add (item);
+
return menu;
};
topBar.PackEnd (exportButton, false, false, 0);
newButton = new MenuButton ();
newButton.Label = GettextCatalog.GetString ("Add Policy");
- newButton.MenuCreator = delegate {
- Gtk.Menu menu = new Gtk.Menu ();
- MenuItem mi = new MenuItem (GettextCatalog.GetString ("New policy..."));
- mi.Activated += HandleNewButtonClicked;
- menu.Insert (mi, -1);
- mi = new MenuItem (GettextCatalog.GetString ("From file..."));
- mi.Activated += HandleFromFile;
- menu.Insert (mi, -1);
- mi = new MenuItem (GettextCatalog.GetString ("From project or solution..."));
- mi.Activated += HandleFromProject;
- if (!IdeApp.Workspace.IsOpen)
- mi.Sensitive = false;
- menu.Insert (mi, -1);
- menu.ShowAll ();
+ newButton.ContextMenuRequested = delegate {
+ ContextMenu menu = new ContextMenu ();
+
+ ContextMenuItem item = new ContextMenuItem (GettextCatalog.GetString ("New policy..."));
+ item.Clicked += HandleNewButtonClicked;
+ menu.Items.Add (item);
+
+ item = new ContextMenuItem (GettextCatalog.GetString ("From file..."));
+ item.Clicked += HandleFromFile;
+ menu.Items.Add (item);
+
+ item = new ContextMenuItem (GettextCatalog.GetString ("From project or solution..."));
+ item.Clicked += HandleFromProject;
+ if (!IdeApp.Workspace.IsOpen) {
+ item.Sensitive = false;
+ }
+ menu.Items.Add (item);
+
return menu;
};
topBar.PackEnd (newButton, false, false, 0);
@@ -214,7 +222,7 @@ namespace MonoDevelop.Ide.Projects
void HandleFromFile (object sender, EventArgs e)
{
OpenFileDialog dlg = new OpenFileDialog (GettextCatalog.GetString ("Select Policy File"));
- dlg.Action = FileChooserAction.Open;
+ dlg.Action = SelectFileDialogAction.Open;
dlg.TransientFor = this;
dlg.AddFilter (BrandingService.BrandApplicationName (GettextCatalog.GetString ("MonoDevelop policy files")), "*.mdpolicy");
dlg.AddAllFilesFilter ();
@@ -273,7 +281,7 @@ namespace MonoDevelop.Ide.Projects
OpenFileDialog dlg = new OpenFileDialog (GettextCatalog.GetString ("Select Policy File"));
dlg.TransientFor = this;
dlg.InitialFileName = currentSet.Name + ".mdpolicy";
- dlg.Action = FileChooserAction.Save;
+ dlg.Action = SelectFileDialogAction.Save;
dlg.AddFilter (BrandingService.BrandApplicationName (GettextCatalog.GetString ("MonoDevelop policy files")), "*.mdpolicy");
dlg.AddAllFilesFilter ();
dlg.CurrentFolder = ExportProjectPolicyDialog.DefaultFileDialogPolicyDir;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ExportProjectPolicyDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ExportProjectPolicyDialog.cs
index 4f51bb1f38..3c6412b68f 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ExportProjectPolicyDialog.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ExportProjectPolicyDialog.cs
@@ -23,11 +23,13 @@
// 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 Gtk;
+
using MonoDevelop.Core;
using MonoDevelop.Projects;
using MonoDevelop.Projects.Policies;
+using MonoDevelop.Components.Extensions;
namespace MonoDevelop.Ide.Projects
{
@@ -41,7 +43,7 @@ namespace MonoDevelop.Ide.Projects
this.Build ();
this.policyProvider = policyProvider;
- fileEntry.Action = FileChooserAction.Save;
+ fileEntry.Action = SelectFileDialogAction.Save;
fileEntry.DefaultPath = DefaultFileDialogPolicyDir;
if (policyProvider is SolutionItem)
fileEntry.Path = ((SolutionItem)policyProvider).Name + ".mdpolicy";
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkNewProjectDialogBackend.UI.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkNewProjectDialogBackend.UI.cs
index 3861ff60df..611343c253 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkNewProjectDialogBackend.UI.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkNewProjectDialogBackend.UI.cs
@@ -29,6 +29,7 @@ using Gtk;
using MonoDevelop.Components;
using MonoDevelop.Core;
using MonoDevelop.Ide.Templates;
+using Mono.TextEditor;
namespace MonoDevelop.Ide.Projects
{
@@ -72,8 +73,8 @@ namespace MonoDevelop.Ide.Projects
void Build ()
{
BorderWidth = 0;
- WidthRequest = 901;
- HeightRequest = 632;
+ WidthRequest = GtkWorkarounds.ConvertToPixelScale (901);
+ HeightRequest = GtkWorkarounds.ConvertToPixelScale (632);
Name = "wizard_dialog";
Title = GettextCatalog.GetString ("New Project");
@@ -84,9 +85,9 @@ namespace MonoDevelop.Ide.Projects
projectConfigurationWidget.Name = "projectConfigurationWidget";
// Top banner of dialog.
- var topLabelEventBox = new EventBox ();
+ var topLabelEventBox = new EventBox ();
topLabelEventBox.Name = "topLabelEventBox";
- topLabelEventBox.HeightRequest = 52;
+ topLabelEventBox.HeightRequest = GtkWorkarounds.ConvertToPixelScale (52);
topLabelEventBox.ModifyBg (StateType.Normal, bannerBackgroundColor);
topLabelEventBox.ModifyFg (StateType.Normal, whiteColor);
topLabelEventBox.BorderWidth = 0;
@@ -130,7 +131,7 @@ namespace MonoDevelop.Ide.Projects
var templateCategoriesVBox = new VBox ();
templateCategoriesVBox.Name = "templateCategoriesVBox";
templateCategoriesVBox.BorderWidth = 0;
- templateCategoriesVBox.WidthRequest = 220;
+ templateCategoriesVBox.WidthRequest = GtkWorkarounds.ConvertToPixelScale (220);
var templateCategoriesScrolledWindow = new ScrolledWindow ();
templateCategoriesScrolledWindow.Name = "templateCategoriesScrolledWindow";
templateCategoriesScrolledWindow.HscrollbarPolicy = PolicyType.Never;
@@ -148,9 +149,9 @@ namespace MonoDevelop.Ide.Projects
templatesHBox.PackStart (templateCategoriesVBox, false, false, 0);
// Templates.
- var templatesVBox = new VBox ();
+ var templatesVBox = new VBox ();
templatesVBox.Name = "templatesVBox";
- templatesVBox.WidthRequest = 400;
+ templatesVBox.WidthRequest = GtkWorkarounds.ConvertToPixelScale (400);
templatesHBox.PackStart (templatesVBox, false, false, 0);
var templatesScrolledWindow = new ScrolledWindow ();
templatesScrolledWindow.Name = "templatesScrolledWindow";
@@ -178,23 +179,23 @@ namespace MonoDevelop.Ide.Projects
templateEventBox.Add (templateVBox);
// Template large image.
- templateImage = new ImageView ();
+ templateImage = new ImageView ();
templateImage.Name = "templateImage";
- templateImage.HeightRequest = 140;
- templateImage.WidthRequest = 240;
+ templateImage.HeightRequest = GtkWorkarounds.ConvertToPixelScale (140);
+ templateImage.WidthRequest = GtkWorkarounds.ConvertToPixelScale (240);
templateVBox.PackStart (templateImage, false, false, 10);
// Template description.
- templateNameLabel = new Label ();
+ templateNameLabel = new Label ();
templateNameLabel.Name = "templateNameLabel";
- templateNameLabel.WidthRequest = 240;
+ templateNameLabel.WidthRequest = GtkWorkarounds.ConvertToPixelScale (240);
templateNameLabel.Wrap = true;
templateNameLabel.Xalign = 0;
templateNameLabel.Markup = MarkupTemplateName ("TemplateName");
templateVBox.PackStart (templateNameLabel, false, false, 0);
- templateDescriptionLabel = new Label ();
+ templateDescriptionLabel = new Label ();
templateDescriptionLabel.Name = "templateDescriptionLabel";
- templateDescriptionLabel.WidthRequest = 240;
+ templateDescriptionLabel.WidthRequest = GtkWorkarounds.ConvertToPixelScale (240);
templateDescriptionLabel.Wrap = true;
templateDescriptionLabel.Xalign = 0;
templateVBox.PackStart (templateDescriptionLabel, false, false, 0);
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkNewProjectDialogBackend.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkNewProjectDialogBackend.cs
index 83c534cd30..c4570c668d 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkNewProjectDialogBackend.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkNewProjectDialogBackend.cs
@@ -380,6 +380,8 @@ namespace MonoDevelop.Ide.Projects
var currentTemplate = templatesListStore.GetValue (iter, TemplateColumn) as SolutionTemplate;
if (currentTemplate == template) {
templatesTreeView.Selection.SelectIter (iter);
+ TreePath path = templatesListStore.GetPath (iter);
+ templatesTreeView.ScrollToCell (path, null, true, 1, 0);
break;
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkTemplateCellRenderer.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkTemplateCellRenderer.cs
index 55f54d1c3e..ed5388bc5a 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkTemplateCellRenderer.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkTemplateCellRenderer.cs
@@ -32,6 +32,7 @@ using Gtk;
using MonoDevelop.Components;
using MonoDevelop.Core;
using MonoDevelop.Ide.Templates;
+using Mono.TextEditor;
namespace MonoDevelop.Ide.Projects
{
@@ -118,7 +119,8 @@ namespace MonoDevelop.Ide.Projects
SetMarkup (layout, GetSelectedLanguage ());
layout.GetPixelSize (out textWidth, out textHeight);
- languageRect = GetLanguageButtonRectangle (window, widget, cell_area, textHeight, textWidth);
+ double scale = GtkWorkarounds.GetPixelScale ();
+ languageRect = GetLanguageButtonRectangle (window, widget, cell_area, textHeight, textWidth, scale);
DrawTemplateNameText (window, widget, cell_area, iconRect, languageRect, flags);
@@ -126,7 +128,7 @@ namespace MonoDevelop.Ide.Projects
SetSourceColor (ctx, LanguageButtonBackgroundColor.ToCairoColor ());
ctx.Fill ();
- int languageTextX = languageRect.X + languageLeftHandPadding;
+ int languageTextX = languageRect.X + GetLanguageLeftHandPadding (scale);
if (!TemplateHasMultipleLanguages ()) {
languageTextX = languageRect.X + (languageRect.Width - textWidth) / 2;
}
@@ -135,14 +137,30 @@ namespace MonoDevelop.Ide.Projects
window.DrawLayout (widget.Style.TextGC (StateType.Normal), languageTextX, languageTextY, layout);
if (TemplateHasMultipleLanguages ()) {
- int triangleX = languageTextX + textWidth + languageRightHandPadding;
- int triangleY = languageRect.Y + (languageRect.Height - dropdownTriangleHeight) / 2;
- DrawTriangle (ctx, triangleX, triangleY);
+ int triangleX = languageTextX + textWidth + GetLanguageRightHandPadding (scale);
+ int triangleY = languageRect.Y + (languageRect.Height - ((int)(scale * dropdownTriangleHeight))) / 2;
+ DrawTriangle (ctx, triangleX, triangleY, scale);
}
}
}
}
+ int GetLanguageLeftHandPadding (double scale)
+ {
+ if (Platform.IsWindows && scale > 1.0) {
+ return (int)(scale * (languageLeftHandPadding + 3));
+ }
+ return languageLeftHandPadding;
+ }
+
+ int GetLanguageRightHandPadding (double scale)
+ {
+ if (Platform.IsWindows && scale > 1.0) {
+ return (int)(scale * languageRightHandPadding);
+ }
+ return languageRightHandPadding;
+ }
+
void DrawTemplateCategoryText (Drawable window, Widget widget, Rectangle cell_area, CellRendererState flags)
{
StateType state = GetState (widget, flags);
@@ -233,7 +251,7 @@ namespace MonoDevelop.Ide.Projects
layout.SetMarkup (markup);
}
- Rectangle GetLanguageButtonRectangle (Drawable window, Widget widget, Rectangle cell_area, int textHeight, int textWidth)
+ Rectangle GetLanguageButtonRectangle (Drawable window, Widget widget, Rectangle cell_area, int textHeight, int textWidth, double scale)
{
int languageRectangleHeight = cell_area.Height - 8;
int languageRectangleWidth = textWidth + languageLeftHandPadding;
@@ -244,6 +262,8 @@ namespace MonoDevelop.Ide.Projects
languageRectangleWidth = Math.Max (languageRectangleWidth, minLanguageRectWidth);
}
+ languageRectangleWidth = (int)(scale * languageRectangleWidth);
+
var dy = (cell_area.Height - languageRectangleHeight) / 2 - 1;
var y = cell_area.Y + dy;
var x = widget.Allocation.Width - languageRectangleWidth - (int)Xpad;
@@ -256,12 +276,15 @@ namespace MonoDevelop.Ide.Projects
return Template.AvailableLanguages.Count > 1;
}
- void DrawTriangle (Cairo.Context ctx, int x, int y)
+ void DrawTriangle (Cairo.Context ctx, int x, int y, double scale)
{
+ int width = (int)(scale * dropdownTriangleWidth);
+ int height = (int)(scale * dropdownTriangleHeight);
+
SetSourceColor (ctx, triangleColor.ToCairoColor ());
ctx.MoveTo (x, y);
- ctx.LineTo (x + dropdownTriangleWidth, y);
- ctx.LineTo (x + (dropdownTriangleWidth / 2), y + dropdownTriangleHeight);
+ ctx.LineTo (x + width, y);
+ ctx.LineTo (x + (width / 2), y + height);
ctx.LineTo (x, y);
ctx.Fill ();
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewProjectController.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewProjectController.cs
index 7bbb3a8fd8..4dafab5fa9 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewProjectController.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewProjectController.cs
@@ -57,7 +57,10 @@ namespace MonoDevelop.Ide.Projects
const string CreateGitIgnoreFilePropertyName = "Dialogs.NewProjectDialog.CreateGitIgnoreFile";
const string CreateProjectSubDirectoryPropertyName = "MonoDevelop.Core.Gui.Dialogs.NewProjectDialog.AutoCreateProjectSubdir";
const string CreateProjectSubDirectoryInExistingSolutionPropertyName = "Dialogs.NewProjectDialog.AutoCreateProjectSubdirInExistingSolution";
- const string LastSelectedCategoryPropertyName = "Dialogs.NewProjectDialog.LastSelectedCategoryPath";
+ const string NewSolutionLastSelectedCategoryPropertyName = "Dialogs.NewProjectDialog.LastSelectedCategoryPath";
+ const string NewSolutionLastSelectedTemplatePropertyName = "Dialogs.NewProjectDialog.LastSelectedTemplate";
+ const string NewProjectLastSelectedCategoryPropertyName = "Dialogs.NewProjectDialog.AddNewProjectLastSelectedCategoryPath";
+ const string NewProjectLastSelectedTemplatePropertyName = "Dialogs.NewProjectDialog.AddNewProjectLastSelectedTemplate";
const string SelectedLanguagePropertyName = "Dialogs.NewProjectDialog.SelectedLanguage";
List<TemplateCategory> templateCategories;
@@ -90,13 +93,56 @@ namespace MonoDevelop.Ide.Projects
string DefaultSelectedCategoryPath {
get {
- return PropertyService.Get<string> (LastSelectedCategoryPropertyName, null);
+ return GetDefaultPropertyValue (NewProjectLastSelectedCategoryPropertyName,
+ NewSolutionLastSelectedCategoryPropertyName);
}
set {
- PropertyService.Set (LastSelectedCategoryPropertyName, value);
+ SetDefaultPropertyValue (NewProjectLastSelectedCategoryPropertyName,
+ NewSolutionLastSelectedCategoryPropertyName,
+ value);
}
}
+ string DefaultSelectedTemplate {
+ get {
+ return GetDefaultPropertyValue (NewProjectLastSelectedTemplatePropertyName,
+ NewSolutionLastSelectedTemplatePropertyName);
+ }
+ set {
+ SetDefaultPropertyValue (NewProjectLastSelectedTemplatePropertyName,
+ NewSolutionLastSelectedTemplatePropertyName,
+ value);
+ }
+ }
+
+ string GetDefaultPropertyValue (string newProjectPropertyName, string newSolutionPropertyName)
+ {
+ if (!IsNewSolution) {
+ string propertyValue = PropertyService.Get<string> (newProjectPropertyName, null);
+ if (!string.IsNullOrEmpty (propertyValue))
+ return propertyValue;
+ }
+ return PropertyService.Get<string> (newSolutionPropertyName, null);
+ }
+
+ void SetDefaultPropertyValue (string newProjectPropertyName, string newSolutionPropertyName, string value)
+ {
+ SolutionTemplateVisibility visibility = GetSelectedTemplateVisibility ();
+ if (IsNewSolution || visibility != SolutionTemplateVisibility.NewProject) {
+ PropertyService.Set (newSolutionPropertyName, value);
+ PropertyService.Set (newProjectPropertyName, null);
+ } else if (visibility == SolutionTemplateVisibility.NewProject) {
+ PropertyService.Set (newProjectPropertyName, value);
+ }
+ }
+
+ SolutionTemplateVisibility GetSelectedTemplateVisibility ()
+ {
+ if (SelectedTemplate != null)
+ return SelectedTemplate.Visibility;
+ return SolutionTemplateVisibility.All;
+ }
+
public bool IsNewSolution {
get { return projectConfiguration.CreateSolution; }
}
@@ -162,8 +208,9 @@ namespace MonoDevelop.Ide.Projects
{
UpdateDefaultGitSettings ();
UpdateDefaultCreateProjectDirectorySetting ();
- PropertyService.Set (SelectedLanguagePropertyName, SelectedLanguage);
+ PropertyService.Set (SelectedLanguagePropertyName, GetLanguageForTemplateProcessing ());
DefaultSelectedCategoryPath = GetSelectedCategoryPath ();
+ DefaultSelectedTemplate = GetDefaultSelectedTemplateId ();
}
string GetSelectedCategoryPath ()
@@ -184,6 +231,14 @@ namespace MonoDevelop.Ide.Projects
return null;
}
+ string GetDefaultSelectedTemplateId ()
+ {
+ if (SelectedTemplate != null) {
+ return SelectedTemplate.Id;
+ }
+ return null;
+ }
+
void UpdateDefaultCreateProjectDirectorySetting ()
{
if (IsNewSolution) {
@@ -272,7 +327,13 @@ namespace MonoDevelop.Ide.Projects
if (SelectedTemplateId != null) {
SelectTemplate (SelectedTemplateId);
} else if (DefaultSelectedCategoryPath != null) {
- SelectFirstTemplateInCategory (DefaultSelectedCategoryPath);
+ if (DefaultSelectedTemplate != null) {
+ SelectTemplateInCategory (DefaultSelectedCategoryPath, DefaultSelectedTemplate);
+ }
+
+ if (SelectedTemplate == null) {
+ SelectFirstTemplateInCategory (DefaultSelectedCategoryPath);
+ }
}
if (SelectedSecondLevelCategory == null) {
@@ -292,6 +353,18 @@ namespace MonoDevelop.Ide.Projects
void SelectFirstTemplateInCategory (string categoryPath)
{
+ SelectTemplateInCategory (categoryPath, template => true);
+ }
+
+ void SelectTemplateInCategory (string categoryPath, string templateId)
+ {
+ SelectTemplateInCategory (categoryPath, parentTemplate => {
+ return parentTemplate.GetTemplate (template => template.Id == templateId) != null;
+ });
+ }
+
+ void SelectTemplateInCategory (string categoryPath, Func<SolutionTemplate, bool> isTemplateMatch)
+ {
List<string> parts = new TemplateCategoryPath (categoryPath).GetParts ().ToList ();
if (parts.Count < 2) {
return;
@@ -300,7 +373,7 @@ namespace MonoDevelop.Ide.Projects
string topLevelCategoryId = parts [0];
string secondLevelCategoryId = parts [1];
SelectTemplate (
- template => true,
+ isTemplateMatch,
category => category.Id == topLevelCategoryId,
category => category.Id == secondLevelCategoryId);
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ProjectTemplateCategorizer.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ProjectTemplateCategorizer.cs
index cb0e0ebf53..1742eb86ec 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ProjectTemplateCategorizer.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ProjectTemplateCategorizer.cs
@@ -37,6 +37,7 @@ namespace MonoDevelop.Ide.Templates
TemplateCategory defaultCategory;
Dictionary<string, TemplateCategory> mappedCategories = new Dictionary<string, TemplateCategory> ();
Predicate<SolutionTemplate> templateMatch;
+ bool removedEmptyCategories;
public static readonly Predicate<SolutionTemplate> MatchNewProjectTemplates = template => template.IsMatch (SolutionTemplateVisibility.NewProject);
public static readonly Predicate<SolutionTemplate> MatchNewSolutionTemplates = template => template.IsMatch (SolutionTemplateVisibility.NewSolution);
@@ -86,6 +87,11 @@ namespace MonoDevelop.Ide.Templates
public IEnumerable<TemplateCategory> GetCategorizedTemplates ()
{
+ if (!removedEmptyCategories) {
+ RemoveEmptyCategories ();
+ removedEmptyCategories = true;
+ }
+
return categories;
}
@@ -99,7 +105,6 @@ namespace MonoDevelop.Ide.Templates
LogNoCategoryMatch (template);
}
}
- RemoveEmptyCategories ();
}
IEnumerable<SolutionTemplate> GetFilteredTemplates (IEnumerable<SolutionTemplate> templates)
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/CodeGenerationService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/CodeGenerationService.cs
index 4c857af7d9..42d8e0116f 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/CodeGenerationService.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/CodeGenerationService.cs
@@ -115,7 +115,7 @@ namespace MonoDevelop.Ide.TypeSystem
var tcs = new TaskCompletionSource<bool>();
if (parentType == null)
return tcs.Task;
- part = part ?? parentType.Parts.FirstOrDefault ();
+ part = part ?? FindCurrentPart (parentType);
if (part == null)
return tcs.Task;
var loadedDocument = IdeApp.Workbench.OpenDocument (part.Region.FileName);
@@ -160,7 +160,24 @@ namespace MonoDevelop.Ide.TypeSystem
return tcs.Task;
}
-
+
+ public static IUnresolvedTypeDefinition FindCurrentPart (ITypeDefinition type)
+ {
+ var active = IdeApp.Workbench.ActiveDocument;
+ if (active != null) {
+ var partsInFile = type.Parts.Where (p => p.Region.FileName == active.FileName).ToList ();
+
+ foreach (var p in partsInFile) {
+ if (p.Region.Contains (active.Editor.Caret.Location))
+ return p;
+ }
+ if (partsInFile.Count > 0)
+ return partsInFile[0];
+ }
+
+ return type.Parts.FirstOrDefault ();
+ }
+
public static Task<bool> InsertMember (
ITypeDefinition parentType, IUnresolvedTypeDefinition part,
IUnresolvedMember newMember, bool implementExplicit = false)
@@ -168,7 +185,7 @@ namespace MonoDevelop.Ide.TypeSystem
var tcs = new TaskCompletionSource<bool>();
if (parentType == null)
return tcs.Task;
- part = part ?? parentType.Parts.FirstOrDefault ();
+ part = part ?? FindCurrentPart (parentType);
if (part == null)
return tcs.Task;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemService.cs
index 62b696292b..d1cc52adfc 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemService.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemService.cs
@@ -160,7 +160,7 @@ namespace MonoDevelop.Ide.TypeSystem
public static class TypeSystemService
{
- const string CurrentVersion = "1.1.8";
+ const string CurrentVersion = "1.1.9";
static readonly List<TypeSystemParserNode> parsers;
static string[] filesSkippedInParseThread = new string[0];
@@ -674,6 +674,11 @@ namespace MonoDevelop.Ide.TypeSystem
throw new Exception ("Too many cache directories");
}
+ static string EscapeToXml (string txt)
+ {
+ return new System.Xml.Linq.XText (txt).ToString ();
+ }
+
static string CreateCacheDirectory (FilePath fileName)
{
CanonicalizePath (ref fileName);
@@ -685,7 +690,7 @@ namespace MonoDevelop.Ide.TypeSystem
File.WriteAllText (
Path.Combine (cacheDir, "data.xml"),
- string.Format ("<DerivedData><File name=\"{0}\" version =\"{1}\"/></DerivedData>", fileName, CurrentVersion)
+ string.Format ("<DerivedData><File name=\"{0}\" version =\"{1}\"/></DerivedData>", EscapeToXml (fileName), CurrentVersion)
);
return cacheDir;
@@ -1129,10 +1134,11 @@ namespace MonoDevelop.Ide.TypeSystem
public bool WasChanged;
[NonSerialized]
ICompilation compilation;
+ object compilationContentLock = new object ();
public ICompilation Compilation {
get {
- lock (updateContentLock) {
+ lock (compilationContentLock) {
if (compilation == null) {
compilation = Content.CreateCompilation ();
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj
index ce400427d9..20a2a4b437 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj
@@ -31,14 +31,14 @@
<Optimize>True</Optimize>
<OutputPath>..\..\..\build\bin</OutputPath>
<ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
+ <WarningLevel>3</WarningLevel>
<Execution>
<Execution clr-version="Net_2_0" />
</Execution>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<DebugSymbols>true</DebugSymbols>
<NoWarn>1591;1573</NoWarn>
- <DocumentationFile>..\..\..\build\AddIns\MonoDevelop.Ide.xml</DocumentationFile>
+ <DocumentationFile>..\..\..\build\bin\MonoDevelop.Ide.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugMac|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -62,8 +62,38 @@
<OutputPath>..\..\..\build\bin</OutputPath>
<DefineConstants>MAC</DefineConstants>
<ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <DocumentationFile>..\..\..\build\AddIns\MonoDevelop.Ide.xml</DocumentationFile>
+ <WarningLevel>3</WarningLevel>
+ <DocumentationFile>..\..\..\build\bin\MonoDevelop.Ide.xml</DocumentationFile>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <Execution>
+ <Execution clr-version="Net_2_0" />
+ </Execution>
+ <NoWarn>1591;1573</NoWarn>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugWin32|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\..\..\build\bin</OutputPath>
+ <DefineConstants>DEBUG,WIN32</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>3</WarningLevel>
+ <DocumentationFile>..\..\..\build\bin\MonoDevelop.Ide.xml</DocumentationFile>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <NoWarn>1591;1573</NoWarn>
+ <Execution>
+ <Execution clr-version="Net_2_0" />
+ </Execution>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseWin32|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\..\..\build\bin</OutputPath>
+ <DefineConstants>WIN32</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>3</WarningLevel>
+ <DocumentationFile>..\..\..\build\bin\MonoDevelop.Ide.xml</DocumentationFile>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Execution>
<Execution clr-version="Net_2_0" />
@@ -104,6 +134,11 @@
<Reference Include="Xamarin.Mac" Condition=" '$(Configuration)' == 'DebugMac' Or '$(Configuration)' == 'ReleaseMac' ">
<HintPath>..\..\..\external\Xamarin.Mac.dll</HintPath>
</Reference>
+ <Reference Include="System.Windows" Condition=" '$(Configuration)' == 'DebugWin32' Or '$(Configuration)' == 'ReleaseWin32' " />
+ <Reference Include="PresentationCore" Condition=" '$(Configuration)' == 'DebugWin32' Or '$(Configuration)' == 'ReleaseWin32' " />
+ <Reference Include="PresentationFramework" Condition=" '$(Configuration)' == 'DebugWin32' Or '$(Configuration)' == 'ReleaseWin32' " />
+ <Reference Include="WindowsBase" Condition=" '$(Configuration)' == 'DebugWin32' Or '$(Configuration)' == 'ReleaseWin32' " />
+ <Reference Include="System.Xaml" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MonoDevelop.Core\MonoDevelop.Core.csproj">
@@ -3379,6 +3414,9 @@
<Compile Include="MonoDevelop.Components.AutoTest\PropertyMetadata.cs" />
<Compile Include="MonoDevelop.Components.AutoTest\ObjectProperties.cs" />
<Compile Include="MonoDevelop.Ide.Templates\TemplateConditionEvaluator.cs" />
+ <Compile Include="MonoDevelop.Components.AutoTest.Operations\SelectedOperation.cs" />
+ <Compile Include="MonoDevelop.Components\Windows\GtkWPFWidget.cs" />
+ <Compile Include="MonoDevelop.Components\Windows\GtkWin32Interop.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Makefile.am" />
@@ -3423,6 +3461,7 @@
<Folder Include="MonoDevelop.Ide.TextEditing\" />
<Folder Include="MonoDevelop.Components.DockNotebook\" />
<Folder Include="icons\mac\" />
+ <Folder Include="MonoDevelop.Components\Windows\" />
</ItemGroup>
<ItemGroup>
<Content Include="gtkrc.win32">
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Ide.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Ide.cs
index 362998e7e6..3a0224a252 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Ide.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Ide.cs
@@ -295,6 +295,8 @@ namespace MonoDevelop.Ide
};
AutoTestService.Start (commandService, Preferences.EnableAutomatedTesting);
AutoTestService.NotifyEvent ("MonoDevelop.Ide.IdeStart");
+
+ Gtk.LinkButton.SetUriHook ((button, uri) => Xwt.Desktop.OpenUrl (uri));
}
static void KeyBindingFailed (object sender, KeyBindingFailedEventArgs e)
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs
index 9aaca48201..9231b18f8a 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs
@@ -219,7 +219,13 @@ namespace MonoDevelop.Ide
Counters.Initialization.Trace ("Loading Icons");
//force initialisation before the workbench so that it can register stock icons for GTK before they get requested
ImageService.Initialize ();
-
+
+ // If we display an error dialog before the main workbench window on OS X then a second application menu is created
+ // which is then replaced with a second empty Apple menu.
+ // XBC #33699
+ Counters.Initialization.Trace ("Initializing IdeApp");
+ IdeApp.Initialize (monitor);
+
if (errorsList.Count > 0) {
using (AddinLoadErrorDialog dlg = new AddinLoadErrorDialog ((AddinError[]) errorsList.ToArray (typeof(AddinError)), false)) {
if (!dlg.Run ())
@@ -234,9 +240,6 @@ namespace MonoDevelop.Ide
// no alternative for Application.ThreadException?
// Application.ThreadException += new ThreadExceptionEventHandler(ShowErrorBox);
- Counters.Initialization.Trace ("Initializing IdeApp");
- IdeApp.Initialize (monitor);
-
// Load requested files
Counters.Initialization.Trace ("Opening Files");
@@ -356,7 +359,10 @@ namespace MonoDevelop.Ide
gtkrc += "-yosemite";
}
}
- Environment.SetEnvironmentVariable ("GTK2_RC_FILES", PropertyService.EntryAssemblyPath.Combine (gtkrc));
+
+ var gtkrcf = PropertyService.EntryAssemblyPath.Combine (gtkrc);
+ LoggingService.LogInfo ("GTK: Using gtkrc from {0}", gtkrcf);
+ Environment.SetEnvironmentVariable ("GTK2_RC_FILES", gtkrcf);
}
}
@@ -731,6 +737,10 @@ namespace MonoDevelop.Ide
Console.WriteLine (BrandingService.ApplicationName + " " + BuildInfo.VersionLabel);
Console.WriteLine ("Options:");
optSet.WriteOptionDescriptions (Console.Out);
+ const string openFileText = " file.ext;line;column";
+ Console.Write (openFileText);
+ Console.Write (new string (' ', 29 - openFileText.Length));
+ Console.WriteLine ("Opens a file at specified integer line and column");
}
return opt;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs
index 7956e16a54..748fcccdcd 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs
@@ -53,6 +53,7 @@ using ICSharpCode.NRefactory.TypeSystem.Implementation;
using System.Text;
using MonoDevelop.Ide.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem;
+using MonoDevelop.Components.Extensions;
namespace MonoDevelop.Ide
{
@@ -622,6 +623,9 @@ namespace MonoDevelop.Ide
public void NewSolution (string defaultTemplate)
{
+ if (!IdeApp.Workbench.SaveAllDirtyFiles ())
+ return;
+
var newProjectDialog = new NewProjectDialogController ();
newProjectDialog.OpenSolution = true;
newProjectDialog.SelectedTemplateId = defaultTemplate;
@@ -653,7 +657,7 @@ namespace MonoDevelop.Ide
WorkspaceItem res = null;
var dlg = new SelectFileDialog () {
- Action = Gtk.FileChooserAction.Open,
+ Action = SelectFileDialogAction.Open,
CurrentFolder = parentWorkspace.BaseDirectory,
SelectMultiple = false,
};
@@ -716,7 +720,7 @@ namespace MonoDevelop.Ide
SolutionItem res = null;
var dlg = new SelectFileDialog () {
- Action = Gtk.FileChooserAction.Open,
+ Action = SelectFileDialogAction.Open,
CurrentFolder = parentFolder.BaseDirectory,
SelectMultiple = false,
};
@@ -1621,7 +1625,7 @@ namespace MonoDevelop.Ide
{
var dlg = new SelectFileDialog () {
SelectMultiple = true,
- Action = Gtk.FileChooserAction.Open,
+ Action = SelectFileDialogAction.Open,
CurrentFolder = folder.BaseDirectory,
TransientFor = MessageService.RootWindow,
};
@@ -1798,7 +1802,9 @@ namespace MonoDevelop.Ide
try {
if (!dialogShown || !applyToAll) {
- if (MessageService.RunCustomDialog (addExternalDialog) == (int) Gtk.ResponseType.Cancel) {
+ int response = MessageService.RunCustomDialog (addExternalDialog);
+ // A dialog emits DeleteEvent rather than Cancel in response to Escape being pressed
+ if (response == (int) Gtk.ResponseType.Cancel || response == (int) Gtk.ResponseType.DeleteEvent) {
project.Files.AddRange (newFileList.Where (f => f != null));
return newFileList;
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/RootWorkspace.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/RootWorkspace.cs
index 7f63bb7925..c18aa74bb2 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/RootWorkspace.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/RootWorkspace.cs
@@ -52,7 +52,6 @@ namespace MonoDevelop.Ide
// IParserDatabase parserDatabase;
string activeConfiguration;
bool useDefaultRuntime;
- string preferredActiveExecutionTarget;
ProjectFileEventHandler fileAddedToProjectHandler;
ProjectFileEventHandler fileRemovedFromProjectHandler;
@@ -153,11 +152,6 @@ namespace MonoDevelop.Ide
ActiveExecutionTargetChanged (this, EventArgs.Empty);
}
- internal string PreferredActiveExecutionTarget {
- get { return ActiveExecutionTarget != null ? ActiveExecutionTarget.Id : preferredActiveExecutionTarget; }
- set { preferredActiveExecutionTarget = value; }
- }
-
public ConfigurationSelector ActiveConfiguration {
get { return new SolutionConfigurationSelector (activeConfiguration); }
}
@@ -693,7 +687,6 @@ namespace MonoDevelop.Ide
try {
WorkspaceUserData data = item.UserProperties.GetValue<WorkspaceUserData> ("MonoDevelop.Ide.Workspace");
if (data != null) {
- PreferredActiveExecutionTarget = data.PreferredExecutionTarget;
ActiveExecutionTarget = null;
if (GetConfigurations ().Contains (data.ActiveConfiguration))
@@ -762,8 +755,6 @@ namespace MonoDevelop.Ide
WorkspaceUserData data = new WorkspaceUserData ();
data.ActiveConfiguration = ActiveConfigurationId;
data.ActiveRuntime = UseDefaultRuntime ? null : ActiveRuntime.Id;
- if (ActiveExecutionTarget != null)
- data.PreferredExecutionTarget = ActiveExecutionTarget.Id;
item.UserProperties.SetValue ("MonoDevelop.Ide.Workspace", data);
// Allow add-ins to fill-up data
@@ -1497,8 +1488,6 @@ namespace MonoDevelop.Ide
public string ActiveConfiguration;
[ItemProperty]
public string ActiveRuntime;
- [ItemProperty]
- public string PreferredExecutionTarget;
}
public class ItemUnloadingEventArgs: EventArgs
diff --git a/main/src/core/MonoDevelop.Projects.Formats.MSBuild/AssemblyInfo.v14.0.cs b/main/src/core/MonoDevelop.Projects.Formats.MSBuild/AssemblyInfo.v14.0.cs
new file mode 100644
index 0000000000..6b3d27577c
--- /dev/null
+++ b/main/src/core/MonoDevelop.Projects.Formats.MSBuild/AssemblyInfo.v14.0.cs
@@ -0,0 +1,9 @@
+[assembly: System.Reflection.AssemblyTitle ("MonoDevelop MSBuild 14.0 Builder")]
+
+namespace MonoDevelop.Projects.Formats.MSBuild
+{
+ static class MSBuildConsts
+ {
+ public const string Version = "14.0";
+ }
+}
diff --git a/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild.csproj b/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild.csproj
index 6e56a94fd8..0d4ccd83d2 100644
--- a/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild.csproj
+++ b/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild.csproj
@@ -28,7 +28,6 @@
<WarningLevel>4</WarningLevel>
<DebugSymbols>true</DebugSymbols>
<NoWarn>1591;1573</NoWarn>
- <DocumentationFile>..\..\..\build\bin\MonoDevelop.Projects.Formats.MSBuild.xml</DocumentationFile>
<DefineConstants>NET_3_5,NET_4_0</DefineConstants>
</PropertyGroup>
<ItemGroup>
diff --git a/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild.dotnet.v14.0.csproj b/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild.dotnet.v14.0.csproj
new file mode 100644
index 0000000000..923f0f38d6
--- /dev/null
+++ b/main/src/core/MonoDevelop.Projects.Formats.MSBuild/MonoDevelop.Projects.Formats.MSBuild.dotnet.v14.0.csproj
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{8EE5A588-9445-48EC-97BD-BF066E7FFD51}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <RootNamespace>MonoDevelop.Projects.Formats.MSBuild</RootNamespace>
+ <AssemblyName>MonoDevelop.Projects.Formats.MSBuild</AssemblyName>
+ <TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
+ <TargetFrameworkProfile />
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\..\..\build\bin\MSBuild\dotnet.14.0\</OutputPath>
+ <DefineConstants>DEBUG;</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ExternalConsole>true</ExternalConsole>
+ <IntermediateOutputPath>obj\Debug</IntermediateOutputPath>
+ <PlatformTarget>x86</PlatformTarget>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <Optimize>true</Optimize>
+ <OutputPath>..\..\..\build\bin\MSBuild\dotnet.14.0\</OutputPath>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ExternalConsole>true</ExternalConsole>
+ <IntermediateOutputPath>obj\Release</IntermediateOutputPath>
+ <PlatformTarget>x86</PlatformTarget>
+ </PropertyGroup>
+ <PropertyGroup>
+ <StartupObject>MonoDevelop.Projects.Formats.MSBuild.MainClass</StartupObject>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Microsoft.Build, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
+ <Reference Include="Microsoft.Build.Framework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
+ <Reference Include="Microsoft.Build.Utilities.Core, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
+ <Reference Include="System" />
+ <Reference Include="System.Runtime.Remoting" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="app.v14.0.config">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ <Link>MonoDevelop.Projects.Formats.MSBuild.exe.config</Link>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="MonoDevelop.Projects.Formats.MSBuild\BuildEngine.v4.0.cs" />
+ <Compile Include="MonoDevelop.Projects.Formats.MSBuild\IBuildEngine.cs" />
+ <Compile Include="MonoDevelop.Projects.Formats.MSBuild\ILogWriter.cs" />
+ <Compile Include="MonoDevelop.Projects.Formats.MSBuild\IProjectBuilder.cs" />
+ <Compile Include="MonoDevelop.Projects.Formats.MSBuild\LocalLogger.cs" />
+ <Compile Include="MonoDevelop.Projects.Formats.MSBuild\MSBuildEvaluatedItem.cs" />
+ <Compile Include="MonoDevelop.Projects.Formats.MSBuild\MSBuildResult.cs" />
+ <Compile Include="MonoDevelop.Projects.Formats.MSBuild\MSBuildTargetResult.cs" />
+ <Compile Include="MonoDevelop.Projects.Formats.MSBuild\ProjectBuilder.Shared.cs" />
+ <Compile Include="MonoDevelop.Projects.Formats.MSBuild\ProjectBuilder.v4.0.cs" />
+ <Compile Include="AssemblyInfo.v14.0.cs" />
+ <Compile Include="Main.cs" />
+ <Compile Include="AssemblyInfo.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+</Project> \ No newline at end of file
diff --git a/main/src/core/MonoDevelop.Projects.Formats.MSBuild/app.v14.0.config b/main/src/core/MonoDevelop.Projects.Formats.MSBuild/app.v14.0.config
new file mode 100644
index 0000000000..a1efcc318e
--- /dev/null
+++ b/main/src/core/MonoDevelop.Projects.Formats.MSBuild/app.v14.0.config
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+ <runtime>
+ <generatePublisherEvidence enabled="false" />
+ <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+ <dependentAssembly>
+ <assemblyIdentity name="Microsoft.Build.Framework" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-100.0.0.0" newVersion="14.0.0.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="Microsoft.Build.Engine" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-100.0.0.0" newVersion="14.0.0.0" />
+ </dependentAssembly>
+ </assemblyBinding>
+ </runtime>
+</configuration>
diff --git a/main/src/core/MonoDevelop.Startup/MonoDevelop.Startup.csproj b/main/src/core/MonoDevelop.Startup/MonoDevelop.Startup.csproj
index 1ce70038af..9a0c8ca36e 100644
--- a/main/src/core/MonoDevelop.Startup/MonoDevelop.Startup.csproj
+++ b/main/src/core/MonoDevelop.Startup/MonoDevelop.Startup.csproj
@@ -37,15 +37,13 @@
<Optimize>true</Optimize>
<OutputPath>..\..\..\build\bin</OutputPath>
<WarningLevel>4</WarningLevel>
- <PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
- <NoWarn>1591;1573</NoWarn>
- <DocumentationFile>..\..\..\build\bin\MonoDevelop.xml</DocumentationFile>
+ <Commandlineparameters>-no-redirect</Commandlineparameters>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>True</DebugSymbols>
<DebugType>full</DebugType>
- <Optimize>True</Optimize>
+ <Optimize>false</Optimize>
<OutputPath>..\..\..\build\bin</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
@@ -69,6 +67,11 @@
<Execution>
<Execution clr-version="Net_2_0" />
</Execution>
+ <DebugSymbols>true</DebugSymbols>
+ <Commandlineparameters>-no-redirect</Commandlineparameters>
+ </PropertyGroup>
+ <PropertyGroup>
+ <ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\MonoDevelop.Core\MonoDevelop.Core.csproj">
@@ -93,6 +96,7 @@
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
+ <None Include="app.manifest" />
</ItemGroup>
<ItemGroup>
<Compile Include="MonoDevelop.Startup\MonoDevelopMain.cs" />
diff --git a/main/src/core/MonoDevelop.Startup/app.config b/main/src/core/MonoDevelop.Startup/app.config
index 187469f353..7a19cb2817 100644
--- a/main/src/core/MonoDevelop.Startup/app.config
+++ b/main/src/core/MonoDevelop.Startup/app.config
@@ -20,9 +20,4 @@
</dependentAssembly>
</assemblyBinding>
</runtime>
-
- <!-- This is required by the subversion add-in for windows, which uses a mixed mode assembly built with .NET 2.0 -->
- <startup useLegacyV2RuntimeActivationPolicy="true">
- <supportedRuntime version="v4.0"/>
- </startup>
</configuration>
diff --git a/main/src/core/MonoDevelop.Startup/app.manifest b/main/src/core/MonoDevelop.Startup/app.manifest
new file mode 100644
index 0000000000..9eccbecb2f
--- /dev/null
+++ b/main/src/core/MonoDevelop.Startup/app.manifest
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
+ <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
+ <security>
+ <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
+ <!-- UAC Manifest Options
+ If you want to change the Windows User Account Control level replace the
+ requestedExecutionLevel node with one of the following.
+
+ <requestedExecutionLevel level="asInvoker" uiAccess="false" />
+ <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
+ <requestedExecutionLevel level="highestAvailable" uiAccess="false" />
+
+ Specifying requestedExecutionLevel element will disable file and registry virtualization.
+ Remove this element if your application requires this virtualization for backwards
+ compatibility.
+ -->
+ <requestedExecutionLevel level="asInvoker" uiAccess="false" />
+ </requestedPrivileges>
+ </security>
+ </trustInfo>
+
+ <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+ <application>
+ <!-- Windows Vista -->
+ <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
+
+ <!-- Windows 7 -->
+ <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
+
+ <!-- Windows 8 -->
+ <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
+
+ <!-- Windows 8.1 -->
+ <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
+
+ <!-- Windows 10 -->
+ <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
+
+ </application>
+ </compatibility>
+
+ <!-- Indicates that the application is DPI-aware and will not be automatically scaled by Windows at higher
+ DPIs. Windows Presentation Foundation (WPF) applications are automatically DPI-aware and do not need
+ to opt in. Windows Forms applications targeting .NET Framework 4.6 that opt into this setting, should
+ also set the 'EnableWindowsFormsHighDpiAutoResizing' setting to 'true' in their app.config. -->
+ <!--
+ <application xmlns="urn:schemas-microsoft-com:asm.v3">
+ <windowsSettings>
+ <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
+ </windowsSettings>
+ </application>
+ -->
+</assembly>
diff --git a/main/src/core/MonoDevelop.TextEditor.Tests/MonoDevelop.TextEditor.Tests.csproj b/main/src/core/MonoDevelop.TextEditor.Tests/MonoDevelop.TextEditor.Tests.csproj
index 12ade68796..e91c85430b 100644
--- a/main/src/core/MonoDevelop.TextEditor.Tests/MonoDevelop.TextEditor.Tests.csproj
+++ b/main/src/core/MonoDevelop.TextEditor.Tests/MonoDevelop.TextEditor.Tests.csproj
@@ -21,6 +21,7 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
+ <DebugType>full</DebugType>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<Optimize>true</Optimize>
diff --git a/main/tests/Makefile.am b/main/tests/Makefile.am
index 611e9180f3..ac6e561003 100644
--- a/main/tests/Makefile.am
+++ b/main/tests/Makefile.am
@@ -46,9 +46,6 @@ if ENABLE_WINDOWSPLATFORM
TEST_ASSEMBLIES += $(TEST_ASSEMBLIES_WINDOWS)
endif
-UITEST_ASSEMBLIES = \
- $(TEST_DIR)/UserInterfaceTests.dll
-
test:
@if test -n "$(assembly)"; then \
for asm in $(TEST_ASSEMBLIES); do \
@@ -75,12 +72,15 @@ test:
uitest:
rm -rf $(TEST_DIR)/TestResults
@if test -n "$(assembly)"; then \
- for asm in $(UITEST_ASSEMBLIES); do \
+ for asm in $(wildcard $(TEST_DIR)/MonoDevelop.UITests*.dll); do \
if test `basename $$asm` = $(assembly); then \
if test -n "$(categories)"; then \
($(RUN_TEST) -xml=TestResult_`basename $$asm`.xml -labels -include=$(categories) $$asm) || exit $?; \
fi; \
- if ! test -n "$(categories)"; then \
+ if test -n "$(tests)"; then \
+ ($(RUN_TEST) -xml=TestResult_`basename $$asm`.xml -labels -run=$(tests) $$asm) || exit $?; \
+ fi; \
+ if ! test -n "$(categories)" && ! test -n "$(tests)"; then \
($(RUN_TEST) -xml=TestResult_`basename $$asm`.xml -labels $$asm) || exit $?; \
fi; \
fi; \
diff --git a/main/tests/TestRunner/TestRunner.csproj b/main/tests/TestRunner/TestRunner.csproj
index 6694451549..8f200a454d 100644
--- a/main/tests/TestRunner/TestRunner.csproj
+++ b/main/tests/TestRunner/TestRunner.csproj
@@ -19,6 +19,7 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
+ <DebugType>full</DebugType>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<Optimize>true</Optimize>
diff --git a/main/tests/UnitTests/MonoDevelop.Core/FilePathTests.cs b/main/tests/UnitTests/MonoDevelop.Core/FilePathTests.cs
index 7bf4aeb53e..c2bcc17281 100644
--- a/main/tests/UnitTests/MonoDevelop.Core/FilePathTests.cs
+++ b/main/tests/UnitTests/MonoDevelop.Core/FilePathTests.cs
@@ -160,8 +160,8 @@ namespace MonoDevelop.Core
public void InvalidCharactersTests ()
{
// Assert compatibility so we know something changed over here.
- Assert.That (FilePath.GetInvalidFileNameChars (), Is.EquivalentTo (Path.GetInvalidFileNameChars ().Concat ("#%&")));
- Assert.That (FilePath.GetInvalidPathChars (), Is.EquivalentTo (Path.GetInvalidPathChars ().Concat ("#%&")));
+ Assert.That (FilePath.GetInvalidFileNameChars (), Is.EquivalentTo (Path.GetInvalidFileNameChars ().Concat ("#%")));
+ Assert.That (FilePath.GetInvalidPathChars (), Is.EquivalentTo (Path.GetInvalidPathChars ().Concat ("#%")));
}
[Test]
diff --git a/main/tests/UnitTests/MonoDevelop.Core/LoggingServiceTests.cs b/main/tests/UnitTests/MonoDevelop.Core/LoggingServiceTests.cs
new file mode 100644
index 0000000000..2216a0dd76
--- /dev/null
+++ b/main/tests/UnitTests/MonoDevelop.Core/LoggingServiceTests.cs
@@ -0,0 +1,223 @@
+//
+// LoggingServiceTests.cs
+//
+// Author:
+// Marius Ungureanu <marius.ungureanu@xamarin.com>
+//
+// Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com)
+//
+// 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.Linq;
+using MonoDevelop.Core.Logging;
+using MonoDevelop.Core.LogReporting;
+using NUnit.Framework;
+
+namespace MonoDevelop.Core
+{
+ [TestFixture]
+ public class LoggingServiceTests
+ {
+ readonly LoggingServiceTestsLogger logger = new LoggingServiceTestsLogger ();
+ LoggingServiceTestsCrashReporter reporter;
+
+ const string message = "This is a log message";
+ const string format = "{0}";
+ string[] exceptionMessage = new[] {
+ "This is a log message",
+ "System.Exception: Exception of type 'System.Exception' was thrown.",
+ "at MonoDevelop.Core.LoggingServiceTests.TestSimpleLogging", // This line is different on .NET and Mono, so use least common denominator.
+ "Exception Data:",
+ "key: value",
+ "key2: value2"
+ };
+
+ [SetUp]
+ public void SetUp ()
+ {
+ logger.EnabledLevel = EnabledLoggingLevel.All;
+ LoggingService.AddLogger (logger);
+ LoggingService.RegisterCrashReporter (reporter = new LoggingServiceTestsCrashReporter ());
+ }
+
+ [TearDown]
+ public void TearDown ()
+ {
+ LoggingService.RemoveLogger (logger.Name);
+ LoggingService.UnregisterCrashReporter (reporter);
+ }
+
+ void AssertLastMessageEqual (string message, LogLevel level)
+ {
+ Assert.AreEqual (level, logger.Messages [logger.Messages.Count - 1].Item1);
+ AssertLastMessageEqual (message);
+ }
+
+ void AssertLastMessageEqual (string message)
+ {
+ Assert.AreEqual (message, logger.Messages [logger.Messages.Count - 1].Item2);
+ }
+
+ [Test]
+ public void CheckWeGotDefaultLoggers ()
+ {
+ Assert.NotNull (LoggingService.GetLogger ("ConsoleLogger"));
+ Assert.NotNull (LoggingService.GetLogger ("Instrumentation logger"));
+ }
+
+ [Test]
+ public void CheckWeGotOurLogger ()
+ {
+ Assert.AreSame (logger, LoggingService.GetLogger (logger.Name));
+ }
+
+ /*
+ * Find a way to get only this logger.
+ [TestCase (EnabledLoggingLevel.None, false, false, false, false, false)]
+ [TestCase (EnabledLoggingLevel.Fatal, true, false, false, false, false)]
+ [TestCase (EnabledLoggingLevel.Error, false, true, false, true, false)]
+ [TestCase (EnabledLoggingLevel.Warn, false, false, true, false, false)]
+ [TestCase (EnabledLoggingLevel.Info, false, false, false, true, false)]
+ [TestCase (EnabledLoggingLevel.Debug, false, false, false, false, true)]
+ [TestCase (EnabledLoggingLevel.All, true, true, true, true, true)]
+ public void TestLoggingLevels (EnabledLoggingLevel levelToSet, bool fatalEnabled, bool errorEnabled, bool warnEnabled, bool infoEnabled, bool debugEnabled)
+ {
+ logger.EnabledLevel = levelToSet;
+
+ Assert.AreEqual (fatalEnabled, LoggingService.IsLevelEnabled (LogLevel.Fatal));
+ Assert.AreEqual (errorEnabled, LoggingService.IsLevelEnabled (LogLevel.Error));
+ Assert.AreEqual (warnEnabled, LoggingService.IsLevelEnabled (LogLevel.Warn));
+ Assert.AreEqual (infoEnabled, LoggingService.IsLevelEnabled (LogLevel.Info));
+ Assert.AreEqual (debugEnabled, LoggingService.IsLevelEnabled (LogLevel.Debug));
+ }
+ */
+
+ [TestCase (LogLevel.Fatal, "LogFatalError")]
+ [TestCase (LogLevel.Error, "LogError")]
+ [TestCase (LogLevel.Warn, "LogWarning")]
+ [TestCase (LogLevel.Info, "LogInfo")]
+ [TestCase (LogLevel.Debug, "LogDebug")]
+ public void TestSimpleLogging (LogLevel level, string methodName)
+ {
+ var logMethod = typeof(LoggingService).GetMethod (methodName, new[] { typeof(string) });
+ logMethod.Invoke (null, new[] { message });
+ AssertLastMessageEqual (message, level);
+
+ var logFormat = typeof(LoggingService).GetMethod (methodName, new[] { typeof(string), typeof(object[]) });
+ logFormat.Invoke (null, new object[] { format, new object[] { message } });
+ AssertLastMessageEqual (message, level);
+
+ try {
+ var e = new Exception ();
+ e.Data["key"] = "value";
+ e.Data["key2"] = "value2";
+ throw e;
+ } catch (Exception e) {
+ // Test exception logging.
+ var logException = typeof(LoggingService).GetMethod (methodName, new[] { typeof(string), typeof(Exception) });
+ logException.Invoke (null, new object[] { message, e });
+
+ var levelMessage = logger.Messages [logger.Messages.Count - 1];
+ var actualMessage = levelMessage.Item2.Split (new[] { Environment.NewLine }, StringSplitOptions.None);
+ var actualLevel = levelMessage.Item1;
+
+ Assert.AreEqual (level, actualLevel);
+ for (int i = 0; i < actualMessage.Length; ++i)
+ Assert.IsTrue (actualMessage[i].Contains (exceptionMessage[i]), "Line {0} mismatches.{1}Expected: {2}{3}Actual: {4}", i, Environment.NewLine,
+ exceptionMessage[i], Environment.NewLine, actualMessage[i]);
+
+ // Test that the message is the same when no exception is sent.
+ logException.Invoke (null, new object[] { message, null });
+ Assert.AreSame (message, logger.Messages [logger.Messages.Count - 1].Item2);
+ }
+ }
+
+ [Test]
+ public void TestCrashLogging ()
+ {
+ var oldValue = LoggingService.ReportCrashes;
+ LoggingService.ReportCrashes = true;
+
+ Tuple<Exception, bool, string> message;
+
+ LoggingService.LogInternalError (null);
+ message = reporter.Messages [reporter.Messages.Count - 1];
+ Assert.AreSame (null, message.Item1);
+ Assert.AreEqual (false, message.Item2);
+ Assert.AreEqual ("internal", message.Item3);
+ Assert.AreEqual (1, reporter.Messages.Count);
+
+ LoggingService.LogFatalError (string.Empty, (Exception)null);
+ message = reporter.Messages [reporter.Messages.Count - 1];
+ Assert.AreSame (null, message.Item1);
+ Assert.AreEqual (true, message.Item2);
+ Assert.AreEqual ("fatal", message.Item3);
+ Assert.AreEqual (2, reporter.Messages.Count);
+
+ LoggingService.ReportCrashes = oldValue;
+ }
+
+ class LoggingServiceTestsLogger : ILogger
+ {
+ #region ILogger implementation
+ List<Tuple<LogLevel, string>> messages = new List<Tuple<LogLevel, string>> ();
+
+ public LoggingServiceTestsLogger ()
+ {
+ }
+
+ public IReadOnlyList<Tuple<LogLevel, string>> Messages {
+ get { return messages; }
+ }
+
+ public void Log (LogLevel level, string message)
+ {
+ messages.Add (new Tuple<LogLevel, string> (level, message));
+ }
+
+ EnabledLoggingLevel enabledLevel;
+ public EnabledLoggingLevel EnabledLevel {
+ get { return enabledLevel; }
+ set { enabledLevel = value; }
+ }
+
+ public string Name {
+ get { return "Logging tests logger"; }
+ }
+
+ #endregion
+ }
+
+ class LoggingServiceTestsCrashReporter : CrashReporter
+ {
+ readonly List<Tuple<Exception, bool, string>> messages = new List<Tuple<Exception, bool, string>> ();
+
+ public IReadOnlyList<Tuple<Exception, bool, string>> Messages {
+ get { return messages; }
+ }
+
+ public override void ReportCrash (Exception ex, bool willShutDown, IEnumerable<string> tags)
+ {
+ messages.Add (new Tuple<Exception, bool, string> (ex, willShutDown, tags.First ()));
+ }
+ }
+ }
+}
+
diff --git a/main/tests/UnitTests/MonoDevelop.Ide.Templates/ProjectTemplateCategorizerTests.cs b/main/tests/UnitTests/MonoDevelop.Ide.Templates/ProjectTemplateCategorizerTests.cs
index 970f867cb8..61c75aac1e 100644
--- a/main/tests/UnitTests/MonoDevelop.Ide.Templates/ProjectTemplateCategorizerTests.cs
+++ b/main/tests/UnitTests/MonoDevelop.Ide.Templates/ProjectTemplateCategorizerTests.cs
@@ -525,6 +525,28 @@ namespace MonoDevelop.Ide.Templates
Assert.AreEqual (1, generalCategory.Templates.Count ());
Assert.AreEqual ("template-id2", firstTemplate.Id);
}
+
+ [Test]
+ public void GetCategorizedTemplates_TwoTemplateProvidersEachWithOneTemplateForTwoDifferentThirdLevelCategories_ThirdLevelCategoriresAreNotRemoved ()
+ {
+ TemplateCategory topLevelCategory = AddTemplateCategory ("android");
+ TemplateCategory secondLevelCategory = AddTemplateCategory ("app", topLevelCategory);
+ AddTemplateCategory ("general", secondLevelCategory);
+ AddTemplateCategory ("tests", secondLevelCategory);
+ CreateCategorizer ();
+ SolutionTemplate firstTemplateProviderTemplate = AddTemplate ("first-provider-template-id", "android/app/general");
+ categorizer.CategorizeTemplates (templates);
+ templates.Clear ();
+ SolutionTemplate secondTemplateProviderTemplate = AddTemplate ("second-provider-template-id", "android/app/tests");
+ CategorizeTemplates ();
+
+ TemplateCategory appCategory = categorizedTemplates.First ().Categories.First ();
+ TemplateCategory generalCategory = appCategory.Categories.First (category => category.Id == "general");
+ TemplateCategory testsCategory = appCategory.Categories.First (category => category.Id == "tests");
+ Assert.That (generalCategory.Templates.ToList (), Contains.Item (firstTemplateProviderTemplate));
+ Assert.That (testsCategory.Templates.ToList (), Contains.Item (secondTemplateProviderTemplate));
+ Assert.AreEqual (2, appCategory.Categories.Count ());
+ }
}
}
diff --git a/main/tests/UnitTests/UnitTests.csproj b/main/tests/UnitTests/UnitTests.csproj
index 6cfca4be61..c2bd614ef3 100644
--- a/main/tests/UnitTests/UnitTests.csproj
+++ b/main/tests/UnitTests/UnitTests.csproj
@@ -253,6 +253,7 @@
<Compile Include="MonoDevelop.Core\FilePathTests.cs" />
<Compile Include="MonoDevelop.Core\BaseCredentialsProviderTests.cs" />
<Compile Include="MonoDevelop.Ide.Templates\TemplateConditionEvaluatorTests.cs" />
+ <Compile Include="MonoDevelop.Core\LoggingServiceTests.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\md.targets" />
diff --git a/main/tests/UserInterfaceTests/Controllers/NewFileController.cs b/main/tests/UserInterfaceTests/Controllers/NewFileController.cs
index b87fbdb0ca..b4e8879936 100644
--- a/main/tests/UserInterfaceTests/Controllers/NewFileController.cs
+++ b/main/tests/UserInterfaceTests/Controllers/NewFileController.cs
@@ -37,14 +37,25 @@ namespace UserInterfaceTests
Action<string> takeScreenshot;
+ Func<AppQuery, AppQuery> categoryViewQuery = c => c.TreeView ().Marked ("catView").Model ();
+ Func<AppQuery, AppQuery> fileTypeQuery = c => c.TreeView ().Marked ("newFileTemplateTreeView").Model ("templateStore__Name");
+
public NewFileController (Action<string> takeScreenshot = null)
{
- this.takeScreenshot = takeScreenshot ?? delegate { };
+ this.takeScreenshot = Util.GetNonNullAction (takeScreenshot);
}
- public static void Create (NewFileOptions options, Action<string> takeScreenshot = null)
+ public static void Create (NewFileOptions options, UITestBase testContext = null)
{
- var ctrl = new NewFileController (takeScreenshot);
+ options.PrintData ();
+ Action<string> screenshotAction = (s) => {};
+ if (testContext != null) {
+ testContext.ReproStep (string.Format ("Add a new file of type '{0}' named '{1}'",
+ options.FileType, options.FileName), options);
+ screenshotAction = testContext.TakeScreenShot;
+ }
+
+ var ctrl = new NewFileController (screenshotAction);
ctrl.Open ();
ctrl.ConfigureAddToProject (!string.IsNullOrEmpty (options.AddToProjectName), options.AddToProjectName);
ctrl.SelectFileTypeCategory (options.FileTypeCategory, options.FileTypeCategoryRoot);
@@ -63,16 +74,18 @@ namespace UserInterfaceTests
public bool SelectFileTypeCategory (string fileTypeCategory, string fileTypeCategoryRoot = "C#")
{
- var openChild = Session.ClickElement (c => c.TreeView ().Marked ("catView").Model ().Text (fileTypeCategoryRoot));
- var resultParent = Session.SelectElement (c => c.TreeView ().Marked ("catView").Model ().Text (fileTypeCategoryRoot).Children ().Text (fileTypeCategory));
- var result = Session.SelectElement (c => c.TreeView ().Marked ("catView").Model ().Text (fileTypeCategory));
+ var openChild = Session.ClickElement (c => categoryViewQuery (c).Text (fileTypeCategoryRoot));
+ var resultParent = Session.SelectElement (c => categoryViewQuery (c).Text (fileTypeCategoryRoot).Children ().Text (fileTypeCategory));
+ var result = Session.SelectElement (c => categoryViewQuery (c).Text (fileTypeCategory)) &&
+ Session.WaitForElement (c => categoryViewQuery (c).Text (fileTypeCategory).Selected ()).Length > 0;
takeScreenshot ("FileTypeCategory-Selected");
return resultParent || result;
}
public bool SelectFileType (string fileType)
{
- var result = Session.SelectElement (c => c.TreeView ().Marked ("newFileTemplateTreeView").Model ("templateStore__Name").Contains (fileType));
+ var result = Session.SelectElement (c => fileTypeQuery (c).Contains (fileType)) &&
+ Session.WaitForElement (c => fileTypeQuery (c).Contains (fileType).Selected ()).Length > 0;
takeScreenshot ("FileType-Selected");
return result;
}
diff --git a/main/tests/UserInterfaceTests/Controllers/NewProjectController.cs b/main/tests/UserInterfaceTests/Controllers/NewProjectController.cs
index 1b9c517323..05719054c0 100644
--- a/main/tests/UserInterfaceTests/Controllers/NewProjectController.cs
+++ b/main/tests/UserInterfaceTests/Controllers/NewProjectController.cs
@@ -28,6 +28,7 @@ using MonoDevelop.Components.AutoTest;
using MonoDevelop.Ide.Commands;
using NUnit.Framework;
using System.Threading;
+using System.Linq;
namespace UserInterfaceTests
{
@@ -37,27 +38,74 @@ namespace UserInterfaceTests
get { return TestService.Session; }
}
- Func<AppQuery, AppQuery> previewTree = (c) => c.TreeView ().Marked ("folderTreeView").Model ("folderTreeStore__NodeName");
+ Func<AppQuery, AppQuery> templateCategoriesTreeViewQuery = c => c.TreeView ().Marked ("templateCategoriesTreeView");
+ Func<AppQuery, AppQuery> templatesTreeViewQuery = c => c.TreeView ().Marked ("templatesTreeView");
+
+ Func<AppQuery, AppQuery> previewTree = c => c.TreeView ().Marked ("folderTreeView").Model ("folderTreeStore__NodeName");
+ Func<AppQuery, AppQuery> templateCategoriesQuery = c => c.TreeView ().Marked ("templateCategoriesTreeView").Model ("templateCategoriesListStore__Name");
+ Func<AppQuery, AppQuery> templatesQuery = c => c.TreeView ().Marked ("templatesTreeView").Model ("templateListStore__Name");
public void Open ()
{
Session.ExecuteCommand (FileCommands.NewProject);
+ WaitForOpen ();
+ }
+
+ public void Open (string addToSolutionName)
+ {
+ SolutionExplorerController.SelectSolution (addToSolutionName);
+ Session.ExecuteCommand (ProjectCommands.AddNewProject);
+ WaitForOpen ();
+ }
+
+ public void WaitForOpen ()
+ {
Session.WaitForElement (c => c.Window ().Marked ("MonoDevelop.Ide.Projects.GtkNewProjectDialogBackend"));
}
+ public void Select (TemplateSelectionOptions templateOptions)
+ {
+ SelectTemplateType (templateOptions.CategoryRoot, templateOptions.Category);
+ SelectTemplate (templateOptions.TemplateKindRoot, templateOptions.TemplateKind);
+ }
+
+ public bool IsSelected (TemplateSelectionOptions templateOptions)
+ {
+ return true;
+// return Session.SelectElement (templateCategoriesTreeViewQuery) && IsTemplateTypeSelected (templateOptions.CategoryRoot, templateOptions.Category)
+// && Session.SelectElement (templatesTreeViewQuery) && IsTemplateSelected (templateOptions.TemplateKindRoot, templateOptions.TemplateKind);
+ }
+
public bool SelectTemplateType (string categoryRoot, string category)
{
- return Session.SelectElement (c => c.TreeView ().Marked ("templateCategoriesTreeView").Model ("templateCategoriesListStore__Name").Contains (categoryRoot).NextSiblings ().Text (category));
+ return Session.SelectElement (c => templateCategoriesQuery (c).Contains (categoryRoot).NextSiblings ().Text (category))
+ && IsTemplateTypeSelected (categoryRoot, category);
}
public bool SelectTemplate (string kindRoot, string kind)
{
- return Session.SelectElement (c => c.TreeView ().Marked ("templatesTreeView").Model ("templateListStore__Name").Contains (kindRoot).NextSiblings ().Text (kind));
+ return Session.SelectElement (c => templatesQuery (c).Contains (kindRoot).NextSiblings ().Text (kind))
+ && IsTemplateSelected (kindRoot, kind);
+ }
+
+ public bool IsTemplateTypeSelected (string categoryRoot, string category)
+ {
+ return Session.WaitForElement (c => templateCategoriesQuery (c).Contains (categoryRoot).NextSiblings ().Text (category).Selected ()).Any ();
+ }
+
+ public bool IsTemplateSelected (string kindRoot, string kind)
+ {
+ return Session.WaitForElement (c => templatesQuery (c).Contains (kindRoot).NextSiblings ().Text (kind).Selected ()).Any ();
}
public bool Next ()
{
- return Session.ClickElement (c => c.Button ().Marked ("nextButton"));
+ return Session.ClickElement (c => c.Button ().Text ("Next"));
+ }
+
+ public bool Create ()
+ {
+ return Session.ClickElement (c => c.Button ().Text ("Create"));
}
public bool Previous ()
@@ -70,14 +118,23 @@ namespace UserInterfaceTests
return Session.ClickElement (c => c.Button ().Marked ("cancelButton"));
}
- public bool SetProjectName (string projectName)
+ public bool SetProjectName (string projectName, bool addToExistingSolution)
{
- return Session.EnterText (c => c.Textfield ().Marked ("projectNameTextBox"), projectName);
+ Func<AppQuery, AppQuery> projectNameTextBox = c => c.Textfield ().Marked ("projectNameTextBox");
+ if (addToExistingSolution && Session.Query (c => projectNameTextBox (c).Sensitivity (false)).Length > 0) {
+ return Session.Query (c => projectNameTextBox (c).Text (projectName)).Length > 0;
+ }
+ return Session.EnterText (projectNameTextBox, projectName);
}
- public bool SetSolutionName (string solutionName)
+ public bool SetSolutionName (string solutionName, bool addToExistingSolution)
{
- return Session.EnterText (c => c.Textfield ().Marked ("solutionNameTextBox"), solutionName);
+ Func<AppQuery, AppQuery> solutionNameTextBox = c => c.Textfield ().Marked ("solutionNameTextBox");
+ if (addToExistingSolution) {
+ return Session.Query (c => solutionNameTextBox (c).Sensitivity (false)).Length > 0 &&
+ Session.Query (c => solutionNameTextBox (c).Text (solutionName)).Length > 0;
+ }
+ return Session.EnterText (solutionNameTextBox, solutionName);
}
public bool SetSolutionLocation (string solutionLocation)
diff --git a/main/tests/UserInterfaceTests/Controllers/NuGetController.cs b/main/tests/UserInterfaceTests/Controllers/NuGetController.cs
index 92cf57a4ad..3425a7b31c 100644
--- a/main/tests/UserInterfaceTests/Controllers/NuGetController.cs
+++ b/main/tests/UserInterfaceTests/Controllers/NuGetController.cs
@@ -25,21 +25,11 @@
// THE SOFTWARE.
using System;
using MonoDevelop.Components.AutoTest;
-using UserInterfaceTests;
using MonoDevelop.Components.Commands;
using NUnit.Framework;
namespace UserInterfaceTests
{
- public class NuGetPackageOptions
- {
- public string PackageName { get; set;}
-
- public string Version { get; set;}
-
- public bool IsPreRelease { get; set;}
- }
-
public class NuGetController
{
static AutoTestClientSession Session {
@@ -48,31 +38,76 @@ namespace UserInterfaceTests
Action<string> takeScreenshot;
- readonly Func<AppQuery,AppQuery> nugetWindow;
+ bool isUpdate;
+
+ static readonly Func<AppQuery,AppQuery> nugetWindow = c => c.Window ().Marked ("Add Packages");
readonly Func<AppQuery,AppQuery> addPackageButton;
+ readonly Func<AppQuery,AppQuery> updatePackageButton;
readonly Func<AppQuery,AppQuery> resultList;
readonly Func<AppQuery,AppQuery> includePreRelease;
- public static void AddPackage (NuGetPackageOptions packageOptions, Action<string> takeScreenshot = null)
+ public static void AddPackage (NuGetPackageOptions packageOptions, UITestBase testContext = null)
+ {
+ Action<string> screenshotAction = delegate { };
+ if (testContext != null) {
+ testContext.ReproStep (string.Format ("Add NuGet package '{0}'", packageOptions.PackageName), packageOptions);
+ screenshotAction = testContext.TakeScreenShot;
+ }
+ AddUpdatePackage (packageOptions, screenshotAction, false);
+ }
+
+ public static void UpdatePackage (NuGetPackageOptions packageOptions, UITestBase testContext = null)
{
- var nuget = new NuGetController (takeScreenshot);
+ Action<string> screenshotAction = delegate { };
+ if (testContext != null) {
+ testContext.ReproStep (string.Format ("Update NuGet package '{0}'", packageOptions.PackageName), packageOptions);
+ screenshotAction = testContext.TakeScreenShot;
+ }
+ AddUpdatePackage (packageOptions, screenshotAction, true);
+ }
+
+ public static void UpdateAllNuGetPackages (UITestBase testContext = null)
+ {
+ Session.ExecuteCommand ("MonoDevelop.PackageManagement.Commands.UpdateAllPackagesInSolution");
+ WaitForNuGet.UpdateSuccess (string.Empty);
+ if (testContext != null)
+ testContext.TakeScreenShot ("All-NuGet-Packages-Updated");
+ }
+
+ static void AddUpdatePackage (NuGetPackageOptions packageOptions, Action<string> takeScreenshot, bool isUpdate = false)
+ {
+ packageOptions.PrintData ();
+ var nuget = new NuGetController (takeScreenshot, isUpdate);
nuget.Open ();
nuget.EnterSearchText (packageOptions.PackageName, packageOptions.Version, packageOptions.IsPreRelease);
- nuget.SelectResultByPackageName (packageOptions.PackageName, packageOptions.Version);
+ for (int i = 0; i < packageOptions.RetryCount; i++) {
+ try {
+ nuget.SelectResultByPackageName (packageOptions.PackageName, packageOptions.Version);
+ break;
+ } catch (NuGetException e) {
+ if (i == packageOptions.RetryCount - 1)
+ Assert.Inconclusive ("Unable to find NuGet package, could be network related.", e);
+ }
+ }
nuget.ClickAdd ();
- Ide.WaitForStatusMessage (new [] {
- string.Format ("{0} successfully added.", packageOptions.PackageName)
- });
- if (takeScreenshot != null)
- takeScreenshot ("Package-Added");
+ Session.WaitForNoElement (nugetWindow);
+ takeScreenshot ("NuGet-Update-Is-"+isUpdate);
+ try {
+ WaitForNuGet.Success (packageOptions.PackageName, isUpdate ? NuGetOperations.Update : NuGetOperations.Add);
+ } catch (TimeoutException e) {
+ takeScreenshot ("Wait-For-NuGet-Operation-Failed");
+ throw;
+ }
+ takeScreenshot ("NuGet-Operation-Finished");
}
- public NuGetController (Action<string> takeScreenshot = null)
+ public NuGetController (Action<string> takeScreenshot = null, bool isUpdate = false)
{
this.takeScreenshot = takeScreenshot ?? delegate { };
+ this.isUpdate = isUpdate;
- nugetWindow = c => c.Window ().Marked ("Add Packages");
addPackageButton = c => nugetWindow (c).Children ().Button ().Text ("Add Package");
+ updatePackageButton = c => nugetWindow (c).Children ().Button ().Text ("Update Package");
resultList = c => nugetWindow (c).Children ().TreeView ().Model ();
includePreRelease = c => nugetWindow (c).Children ().CheckButton ().Text ("Show pre-release packages");
}
@@ -112,18 +147,18 @@ namespace UserInterfaceTests
var found = Session.Query (c => nugetWindow (c).Children ().CheckType (typeof(Gtk.Label)).Text (packageName)).Length > 0;
if (version != null) {
found = found && (Session.Query (c => nugetWindow (c).Children ().CheckType (typeof(Gtk.Label)).Text (version)).Length > 0);
- if (found)
- return;
}
+ if (found)
+ return;
}
takeScreenshot ("Package-Failed-To-Be-Found");
- Assert.Fail ("No package '{0}' with version: '{1}' found", packageName, version);
+ throw new NuGetException (string.Format ("No package '{0}' with version: '{1}' found", packageName, version));
}
public void ClickAdd ()
{
WaitForAddButton (true);
- Assert.IsTrue (Session.ClickElement (addPackageButton));
+ Assert.IsTrue (Session.ClickElement (isUpdate ? updatePackageButton : addPackageButton));
Session.WaitForElement (IdeQuery.TextArea);
}
@@ -138,7 +173,7 @@ namespace UserInterfaceTests
if (enabled == null)
Session.WaitForElement (addPackageButton);
else
- Session.WaitForElement (c => addPackageButton (c).Sensitivity (enabled.Value), 10000);
+ Session.WaitForElement (c => (isUpdate? updatePackageButton(c) : addPackageButton (c)).Sensitivity (enabled.Value), 30000);
}
}
}
diff --git a/main/tests/UserInterfaceTests/Controllers/NuGetOptions.cs b/main/tests/UserInterfaceTests/Controllers/NuGetOptions.cs
new file mode 100644
index 0000000000..9fb53d57cb
--- /dev/null
+++ b/main/tests/UserInterfaceTests/Controllers/NuGetOptions.cs
@@ -0,0 +1,179 @@
+//
+// NuGetOptions.cs
+//
+// Author:
+// Manish Sinha <manish.sinha@xamarin.com>
+//
+// Copyright (c) 2015 Xamarin Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Collections.Generic;
+
+namespace UserInterfaceTests
+{
+ public class NuGetPackageOptions
+ {
+ public NuGetPackageOptions ()
+ {
+ RetryCount = 3;
+ }
+
+ public string PackageName { get; set;}
+
+ public string Version { get; set;}
+
+ public bool IsPreRelease { get; set;}
+
+ public int RetryCount { get; set;}
+
+ public override string ToString ()
+ {
+ return string.Format ("PackageName={0}, Version={1}, IsPreRelease={2}, RetryCount={3}",
+ PackageName, Version, IsPreRelease, RetryCount);
+ }
+ }
+
+ public enum NuGetOperations
+ {
+ Add,
+ Remove,
+ Update
+ }
+
+ public class WaitForNuGet
+ {
+ public WaitForNuGet ()
+ {
+ TimeOutSeconds = 180;
+ PollStepSeconds = 1;
+ }
+
+ public NuGetOperations Operation { get; set;}
+
+ public string PackageName { get; set;}
+
+ public bool WaitForSuccess { get; set;}
+
+ public bool WaitForWarning { get; set;}
+
+ public bool WaitForError { get; set;}
+
+ public int TimeOutSeconds { get; set;}
+
+ public int PollStepSeconds { get; set;}
+
+ public override string ToString ()
+ {
+ return string.Format ("Operation={0}, PackageName={1}, WaitForSuccess={2}, WaitForWarning={3}, WaitForError={4}, TimeOutSeconds={5}, PollStepSeconds={6}",
+ Operation, PackageName, WaitForSuccess, WaitForWarning, WaitForError, TimeOutSeconds, PollStepSeconds);
+ }
+
+ public static void UpdateSuccess (string packageName, bool waitForWarning = true, UITestBase testContext = null)
+ {
+ Success (packageName, NuGetOperations.Update, waitForWarning, testContext);
+ }
+
+ public static void AddSuccess (string packageName, bool waitForWarning = true, UITestBase testContext = null)
+ {
+ Success (packageName, NuGetOperations.Add, waitForWarning, testContext);
+ }
+
+ public static void Success (string packageName, NuGetOperations operation, bool waitForWarning = true, UITestBase testContext = null)
+ {
+ var waitPackage = new WaitForNuGet {
+ Operation = operation,
+ PackageName = packageName,
+ WaitForSuccess = true,
+ WaitForWarning = waitForWarning
+ };
+ if (testContext != null) {
+ testContext.ReproStep (string.Format ("Wait for one of these messages:\n\t{0}",
+ string.Join ("\t\n", waitPackage.ToMessages ())));
+ }
+ waitPackage.Wait ();
+ }
+
+ public void Wait ()
+ {
+ Ide.WaitForStatusMessage (ToMessages (), TimeOutSeconds, PollStepSeconds);
+ }
+
+ public string [] ToMessages ()
+ {
+ if ((WaitForSuccess | WaitForWarning | WaitForError) == false)
+ throw new ArgumentException ("Atleast one of the 'WaitForSuccess', 'WaitForWarning', 'WaitForError' needs to be true");
+
+ List<string> waitForMessages = new List<string> ();
+
+ if (WaitForSuccess) {
+ if (Operation == NuGetOperations.Add) {
+ waitForMessages.Add (string.Format ("{0} successfully added.", PackageName));
+ waitForMessages.Add ("Packages successfully added.");
+ waitForMessages.Add ("packages successfully added.");
+ }
+ if (Operation == NuGetOperations.Update) {
+ waitForMessages.Add (string.Format ("{0} is up to date.", PackageName));
+ waitForMessages.Add (string.Format ("{0} successfully updated.", PackageName));
+ waitForMessages.Add ("Packages successfully updated.");
+ waitForMessages.Add ("packages successfully updated.");
+ waitForMessages.Add ("successfully updated.");
+ waitForMessages.Add ("Packages are up to date.");
+ }
+ if (Operation == NuGetOperations.Remove) {
+ waitForMessages.Add (string.Format ("{0} successfully removed.", PackageName));
+ }
+ }
+
+ if (WaitForWarning) {
+ if (Operation == NuGetOperations.Add) {
+ waitForMessages.Add (string.Format ("{0} added with warnings.", PackageName));
+ waitForMessages.Add ("Packages added with warnings.");
+ waitForMessages.Add ("packages added with warnings.");
+ }
+ if (Operation == NuGetOperations.Update) {
+ waitForMessages.Add (string.Format ("{0} updated with warnings.", PackageName));
+ waitForMessages.Add ("Packages updated with warnings.");
+ waitForMessages.Add ("packages updated with warnings.");
+ waitForMessages.Add ("No update found but warnings were reported.");
+ waitForMessages.Add ("No updates found but warnings were reported.");
+ }
+ if (Operation == NuGetOperations.Remove) {
+ waitForMessages.Add (string.Format ("{0} removed with warnings.", PackageName));
+ }
+ }
+
+ if (WaitForError) {
+ if (Operation == NuGetOperations.Add) {
+ waitForMessages.Add (string.Format ("Could not add {0}.", PackageName));
+ waitForMessages.Add ("Could not add packages.");
+ }
+ if (Operation == NuGetOperations.Update) {
+ waitForMessages.Add (string.Format ("Could not update {0}.", PackageName));
+ waitForMessages.Add ("Could not update packages.");
+ }
+ if (Operation == NuGetOperations.Remove) {
+ waitForMessages.Add (string.Format ("Could not remove {0}.", PackageName));
+ }
+ }
+ return waitForMessages.ToArray ();
+ }
+ }
+}
+
diff --git a/main/tests/UserInterfaceTests/Controllers/OptionsController.cs b/main/tests/UserInterfaceTests/Controllers/OptionsController.cs
new file mode 100644
index 0000000000..7a3c9cc0eb
--- /dev/null
+++ b/main/tests/UserInterfaceTests/Controllers/OptionsController.cs
@@ -0,0 +1,148 @@
+//
+// ProjectOptionsController.cs
+//
+// Author:
+// Manish Sinha <manish.sinha@xamarin.com>
+//
+// Copyright (c) 2015 Xamarin Inc.
+//
+// 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 MonoDevelop.Components.AutoTest;
+using MonoDevelop.Ide.Commands;
+
+namespace UserInterfaceTests
+{
+ public class ProjectOptionsController : OptionsController
+ {
+ readonly static Func<AppQuery, AppQuery> windowQuery = c => c.Window ().Marked ("MonoDevelop.Ide.Projects.ProjectOptionsDialog");
+
+ readonly string solutionName;
+ readonly string projectName;
+
+ public ProjectOptionsController (string solutionName, string projectName, UITestBase testContext = null) : base (windowQuery,testContext)
+ {
+ this.solutionName = solutionName;
+ this.projectName = projectName;
+ }
+
+ public ProjectOptionsController (UITestBase testContext = null) : base (windowQuery, testContext) { }
+
+ public void OpenProjectOptions ()
+ {
+ ReproStep (string.Format ("In Solution Explorer, right click '{0}' and select 'Options'", projectName));
+ SolutionExplorerController.SelectProject (solutionName, projectName);
+
+ Session.Query (IdeQuery.TextArea);
+ Session.ExecuteCommand (ProjectCommands.ProjectOptions);
+ Session.WaitForElement (windowQuery);
+ TakeScreenshot ("Opened-ProjectOptionsDialog");
+ }
+ }
+
+ public class PreferencesController : OptionsController
+ {
+ readonly static Func<AppQuery, AppQuery> windowQuery = c => c.Window ().Marked ("Preferences");
+
+ public PreferencesController (Action<string> takeScreenshot = null) : base (windowQuery, takeScreenshot) {}
+
+ public void Open ()
+ {
+ Session.ExecuteCommand (EditCommands.MonodevelopPreferences);
+ Session.WaitForElement (windowQuery);
+ TakeScreenshot ("Opened-Preferences-Window");
+ }
+
+ public static void SetAuthorInformation (string name = null, string email = null , string copyright = null,
+ string company = null, string trademark = null, Action<string> takeScreenshot = null)
+ {
+ takeScreenshot = takeScreenshot ?? new Action<string> (delegate {});
+
+ if (name == null && email == null && copyright == null && company == null && trademark == null)
+ throw new ArgumentNullException ("Atleast one of these arguments need to be not null: name, email, copyright, company, trademark");
+
+ var prefs = new PreferencesController ();
+ prefs.Open ();
+ prefs.SelectPane ("Author Information");
+ prefs.SetEntry ("nameEntry", name, "Name", takeScreenshot);
+ prefs.SetEntry ("emailEntry", email, "Email", takeScreenshot);
+ prefs.SetEntry ("copyrightEntry", copyright, "Copyright", takeScreenshot);
+ prefs.SetEntry ("companyEntry", company, "Company", takeScreenshot);
+ prefs.SetEntry ("trademarkEntry", trademark, "Trademark", takeScreenshot);
+ prefs.ClickOK ();
+ }
+ }
+
+ public abstract class OptionsController
+ {
+ protected static AutoTestClientSession Session {
+ get { return TestService.Session; }
+ }
+
+ protected Action<string> TakeScreenshot;
+ readonly UITestBase testContext;
+ readonly Func<AppQuery, AppQuery> windowQuery;
+
+ protected OptionsController (Func<AppQuery, AppQuery> windowQuery, UITestBase testContext) : this (windowQuery, testContext.TakeScreenShot)
+ {
+ this.testContext = testContext;
+ }
+
+ protected OptionsController (Func<AppQuery, AppQuery> windowQuery, Action<string> takeScreenshot = null)
+ {
+ this.windowQuery = windowQuery;
+ TakeScreenshot = Util.GetNonNullAction (takeScreenshot);
+ }
+
+ protected void ReproStep (string stepDescription, params object[] info)
+ {
+ testContext.ReproStep (stepDescription, info);
+ }
+
+ public void SelectPane (string name)
+ {
+ ReproStep (string.Format ("Select pane: '{0}'", name));
+ string.Format ("Selected Pane :{0}", name).PrintData ();
+ Session.SelectElement (c => windowQuery (c).Children ().Marked (
+ "MonoDevelop.Components.HeaderBox").Children ().TreeView ().Model ().Children ().Property ("Label", name));
+ }
+
+ protected void SetEntry (string entryName, string entryValue, string stepName, Action<string> takeScreenshot)
+ {
+ if (entryValue != null) {
+ Session.EnterText (c => c.Marked (entryName), entryValue);
+ Session.WaitForElement (c => c.Marked (entryName).Text (entryValue));
+ takeScreenshot (string.Format("{0}-Entry-Set", stepName));
+ }
+ }
+
+ public void ClickOK ()
+ {
+ ReproStep ("Click OK");
+ Session.ClickElement (c => windowQuery (c).Children ().Button ().Text ("OK"));
+ }
+
+ public void ClickCancel ()
+ {
+ ReproStep ("Click Cancel");
+ Session.ClickElement (c => windowQuery (c).Children ().Button ().Text ("Cancel"));
+ }
+ }
+}
+
diff --git a/main/tests/UserInterfaceTests/Controllers/SolutionExplorerController.cs b/main/tests/UserInterfaceTests/Controllers/SolutionExplorerController.cs
index 0afd044380..abd0a1f69b 100644
--- a/main/tests/UserInterfaceTests/Controllers/SolutionExplorerController.cs
+++ b/main/tests/UserInterfaceTests/Controllers/SolutionExplorerController.cs
@@ -24,7 +24,9 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
+using System.Linq;
using MonoDevelop.Components.AutoTest;
+using System.Collections.Generic;
namespace UserInterfaceTests
{
@@ -39,12 +41,68 @@ namespace UserInterfaceTests
public static Func<AppQuery, AppQuery> GetSolutionQuery (string solutionLabel)
{
- return c => topLevel (c).Children().Property ("Label", solutionLabel).Index (0);
+ return c => topLevel (c).Children (false).Index (0).Property ("Label", solutionLabel);
}
public static Func<AppQuery, AppQuery> GetProjectQuery (string solutionLabel, string projectLabel)
{
- return c => topLevel (c).Children().Property ("Label", solutionLabel).Children ().Property ("Label", projectLabel).Index (0);
+ return c => topLevel (c).Children (false).Index (0).Property ("Label", solutionLabel).Children (false).Property ("Label", projectLabel).Index (0);
+ }
+
+ public static bool Select (params string[] selectionTree)
+ {
+ string.Join (" > ", selectionTree).PrintData ();
+ Func<AppQuery, AppQuery> query = GetNodeQuery (selectionTree);
+ return Session.SelectElement (GetNodeQuery (selectionTree)) && Session.WaitForElement (c => query (c).Selected ()).Any ();
+ }
+
+ public static Func<AppQuery, AppQuery> GetNodeQuery (params string[] selectionTree)
+ {
+ var funcs = new List<Func<AppQuery, AppQuery>> ();
+ funcs.Add (topLevel);
+ foreach (var nodeName in selectionTree) {
+ var lastFunc = funcs.Last ();
+ funcs.Add (c => lastFunc (c).Children (false).Property ("Label", nodeName).Index (0));
+ }
+ return funcs.Last ();
+ }
+
+ public static bool SelectSolution (string solutionName, UITestBase testContext = null)
+ {
+ LogReproSteps (testContext, string.Format ("Under Solution Explorer, select Solution '{0}'", solutionName.StripBold ()));
+ return Select (solutionName);
+ }
+
+ public static bool SelectProject (string solutionName, string projectName, UITestBase testContext = null)
+ {
+ LogReproSteps (testContext, string.Format ("Under Solution Explorer, select Project '{0}' under '{1}'", projectName.StripBold (), solutionName.StripBold ()));
+ return Select (solutionName, projectName);
+ }
+
+ public static bool SelectReferenceFolder (string solutionName, string projectName, UITestBase testContext = null)
+ {
+ LogReproSteps (testContext, string.Format ("Under Solution Explorer, expand References node under '{0}'> '{1}'", projectName.StripBold (), solutionName.StripBold ()));
+ return Select (solutionName, projectName, "References");
+ }
+
+ public static bool SelectSingleReference (string solutionName, string projectName, string referenceName, bool fromPackage = false, UITestBase testContext = null)
+ {
+ LogReproSteps (testContext, string.Format ("Under Solution Explorer, select NuGet package '{0}' under '{1}' > '{2}' > From Packages",
+ referenceName, projectName.StripBold (), solutionName.StripBold ()));
+ return fromPackage ? Select (solutionName, projectName, "From Packages", referenceName) : Select (solutionName, projectName, referenceName);
+ }
+
+ public static bool SelectPackage (string solutionName, string projectName, string package, UITestBase testContext = null)
+ {
+ LogReproSteps (testContext, string.Format ("Under Solution Explorer, select package '{0}' under '{1}' > '{2}' > 'Packages'", package, projectName.StripBold (), solutionName.StripBold ()));
+ return Select (solutionName, projectName, "Packages", package);
+ }
+
+ static void LogReproSteps (UITestBase testContext, string message, params object[] info)
+ {
+ if (testContext != null) {
+ testContext.ReproStep (message, info);
+ }
}
}
}
diff --git a/main/tests/UserInterfaceTests/CreateBuildTemplatesTestBase.cs b/main/tests/UserInterfaceTests/CreateBuildTemplatesTestBase.cs
index 806cad1800..914d78b0da 100644
--- a/main/tests/UserInterfaceTests/CreateBuildTemplatesTestBase.cs
+++ b/main/tests/UserInterfaceTests/CreateBuildTemplatesTestBase.cs
@@ -1,8 +1,9 @@
-//
-// SimpleTest.cs
+//
+// CreateBuildTemplatesTestBase.cs
//
// Author:
// Lluis Sanchez Gual <lluis@novell.com>
+// Manish Sinha <manish.sinha@xamarin.com>
//
// Copyright (c) 2010 Novell, Inc (http://www.novell.com)
//
@@ -29,8 +30,7 @@ using System.Diagnostics;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading;
-
-using MonoDevelop.Core;
+using MonoDevelop.Components.AutoTest;
using NUnit.Framework;
namespace UserInterfaceTests
@@ -92,8 +92,7 @@ namespace UserInterfaceTests
TakeScreenShot ("BeforeBuildActionFailed");
Assert.Fail (e.ToString ());
}
-
- OnBuildTemplate ();
+ OnBuildTemplate ((int)projectDetails.BuildTimeout.TotalSeconds);
} catch (Exception e) {
TakeScreenShot ("TestFailedWithGenericException");
Assert.Fail (e.ToString ());
@@ -105,26 +104,44 @@ namespace UserInterfaceTests
public void CreateProject (TemplateSelectionOptions templateOptions,
ProjectDetails projectDetails, GitOptions gitOptions = null, object miscOptions = null)
{
+ PrintToTestRunner (templateOptions, projectDetails, gitOptions, miscOptions);
+ ReproStep ("Create a new project", templateOptions, projectDetails, gitOptions, miscOptions);
var newProject = new NewProjectController ();
- newProject.Open ();
+
+ if (projectDetails.AddProjectToExistingSolution)
+ newProject.Open (projectDetails.SolutionName);
+ else
+ newProject.Open ();
TakeScreenShot ("Open");
OnSelectTemplate (newProject, templateOptions);
OnEnterTemplateSpecificOptions (newProject, projectDetails.ProjectName, miscOptions);
-
+
OnEnterProjectDetails (newProject, projectDetails, gitOptions, miscOptions);
- OnClickCreate (newProject);
+ OnClickCreate (newProject, projectDetails);
+
+ FoldersToClean.Add (projectDetails.SolutionLocation);
}
protected virtual void OnSelectTemplate (NewProjectController newProject, TemplateSelectionOptions templateOptions)
{
- Assert.IsTrue (newProject.SelectTemplateType (templateOptions.CategoryRoot, templateOptions.Category));
+ if (!newProject.SelectTemplateType (templateOptions.CategoryRoot, templateOptions.Category)) {
+ throw new TemplateSelectionException (string.Format ("Failed to select Category '{0}' under '{1}'",
+ templateOptions.Category, templateOptions.CategoryRoot));
+ }
TakeScreenShot ("TemplateCategorySelected");
- Assert.IsTrue (newProject.SelectTemplate (templateOptions.TemplateKindRoot, templateOptions.TemplateKind));
+
+ if (!newProject.SelectTemplate (templateOptions.TemplateKindRoot, templateOptions.TemplateKind)) {
+ throw new TemplateSelectionException (string.Format ("Failed to select Template '{0}' under '{1}'",
+ templateOptions.TemplateKind, templateOptions.TemplateKindRoot));
+ }
TakeScreenShot ("TemplateSelected");
- Assert.IsTrue (newProject.Next ());
+
+ if (!newProject.Next ()) {
+ throw new TemplateSelectionException ("Clicking Next failed after selecting template");
+ }
TakeScreenShot ("NextAfterTemplateSelected");
}
@@ -133,38 +150,98 @@ namespace UserInterfaceTests
protected virtual void OnEnterProjectDetails (NewProjectController newProject, ProjectDetails projectDetails,
GitOptions gitOptions = null, object miscOptions = null)
{
- Assert.IsTrue (newProject.SetProjectName (projectDetails.ProjectName));
+ if (!newProject.SetProjectName (projectDetails.ProjectName, projectDetails.AddProjectToExistingSolution)) {
+ throw new CreateProjectException (string.Format ("Failed at entering ProjectName as '{0}'", projectDetails.ProjectName));
+ }
if (!string.IsNullOrEmpty (projectDetails.SolutionName)) {
- Assert.IsTrue (newProject.SetSolutionName (projectDetails.SolutionName));
+ if (!newProject.SetSolutionName (projectDetails.SolutionName, projectDetails.AddProjectToExistingSolution)) {
+ throw new CreateProjectException (string.Format ("Failed at entering SolutionName as '{0}'", projectDetails.SolutionName));
+ }
}
if (!string.IsNullOrEmpty (projectDetails.SolutionLocation)) {
- Assert.IsTrue (newProject.SetSolutionLocation (projectDetails.SolutionLocation));
+ if (!newProject.SetSolutionLocation (projectDetails.SolutionLocation)) {
+ throw new CreateProjectException (string.Format ("Failed at entering SolutionLocation as '{0}'", projectDetails.SolutionLocation));
+ }
}
- Assert.IsTrue (newProject.CreateProjectInSolutionDirectory (projectDetails.ProjectInSolution));
+ if (!newProject.CreateProjectInSolutionDirectory (projectDetails.ProjectInSolution)) {
+ throw new CreateProjectException (string.Format ("Failed at entering ProjectInSolution as '{0}'", projectDetails.ProjectInSolution));
+ }
- if (gitOptions != null)
- Assert.IsTrue (newProject.UseGit (gitOptions));
+ if (gitOptions != null && !projectDetails.AddProjectToExistingSolution) {
+ if (!newProject.UseGit (gitOptions)) {
+ throw new CreateProjectException (string.Format ("Failed at setting Git as - '{0}'", gitOptions));
+ }
+ }
TakeScreenShot ("AfterProjectDetailsFilled");
}
- protected virtual void OnClickCreate (NewProjectController newProject)
+ protected virtual void OnClickCreate (NewProjectController newProject, ProjectDetails projectDetails)
{
- Session.RunAndWaitForTimer (() => newProject.Next(), "Ide.Shell.SolutionOpened");
+ if (projectDetails.AddProjectToExistingSolution)
+ newProject.Create ();
+ else
+ Session.RunAndWaitForTimer (() => newProject.Create (), "Ide.Shell.SolutionOpened");
}
protected virtual void OnBuildTemplate (int buildTimeoutInSecs = 180)
{
+ ReproStep ("Build solution");
try {
- Assert.IsTrue (Ide.BuildSolution (timeoutInSecs : buildTimeoutInSecs));
+ Assert.IsTrue (Ide.BuildSolution (timeoutInSecs : buildTimeoutInSecs), "Build Failed");
TakeScreenShot ("AfterBuildFinishedSuccessfully");
} catch (TimeoutException e) {
+ Session.DebugObject.Debug ("Build Failed");
+ ReproStep (string.Format ("Expected: Build should finish within '{0}' seconds\nActual: Build timed out", buildTimeoutInSecs));
TakeScreenShot ("AfterBuildFailed");
Assert.Fail (e.ToString ());
}
}
+
+ protected void IsTemplateSelected (TemplateSelectionOptions templateOptions, string addToExistingSolution = null)
+ {
+// var newProject = new NewProjectController ();
+// try {
+// newProject.WaitForOpen ();
+// } catch (TimeoutException) {
+// if (!string.IsNullOrEmpty (addToExistingSolution))
+// newProject.Open (addToExistingSolution);
+// else
+// newProject.Open ();
+// }
+// newProject.IsSelected (templateOptions);
+ }
+
+ protected void WaitForElement (Func<AppQuery, AppQuery> query, string expected, string actual, int timeoutInSecs = 5)
+ {
+ try {
+ Session.WaitForElement (query, timeoutInSecs * 1000);
+ } catch (TimeoutException) {
+ ReproStep (expected, actual);
+ throw;
+ }
+ }
+
+ protected void WaitForElement (Action action, string expected, string actual)
+ {
+ try {
+ action ();
+ } catch (TimeoutException) {
+ ReproStep (string.Format ("Expected: {0}\nActual:{1}", expected, actual));
+ throw;
+ }
+ }
+
+ void PrintToTestRunner (TemplateSelectionOptions templateOptions,
+ ProjectDetails projectDetails, GitOptions gitOptions, object miscOptions)
+ {
+ templateOptions.PrintData ();
+ projectDetails.PrintData ();
+ gitOptions.PrintData ();
+ miscOptions.PrintData ();
+ }
}
}
diff --git a/main/tests/UserInterfaceTests/DialogTests/NewProjectDialogTests.cs b/main/tests/UserInterfaceTests/DialogTests/NewProjectDialogTests.cs
index 96f7edf3f0..26253e1ea8 100644
--- a/main/tests/UserInterfaceTests/DialogTests/NewProjectDialogTests.cs
+++ b/main/tests/UserInterfaceTests/DialogTests/NewProjectDialogTests.cs
@@ -28,7 +28,7 @@ using NUnit.Framework;
namespace UserInterfaceTests
{
- [TestFixture]
+ [TestFixture, Timeout(60000)]
[Category ("Dialog")]
[Category ("ProjectDialog")]
public class NewProjectDialogTests : CreateBuildTemplatesTestBase
@@ -48,6 +48,7 @@ namespace UserInterfaceTests
readonly string solutionLocation = Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments);
[Test]
+ [Category ("Cycle6")]
[TestCase (true, true, true, TestName = "WithGit--WithGitIgnore--WithProjectWithinSolution")]
[TestCase (true, true, false, TestName = "WithGit--WithGitIgnore--WithoutProjectWithinSolution")]
[TestCase (true, true, true, TestName = "WithGit--WithGitIgnore--WithProjectWithinSolution")]
diff --git a/main/tests/UserInterfaceTests/DialogTests/NuGetDialogTests.cs b/main/tests/UserInterfaceTests/DialogTests/NuGetDialogTests.cs
index bd97ab3c39..f27c95b8c0 100644
--- a/main/tests/UserInterfaceTests/DialogTests/NuGetDialogTests.cs
+++ b/main/tests/UserInterfaceTests/DialogTests/NuGetDialogTests.cs
@@ -25,26 +25,36 @@
// THE SOFTWARE.
using NUnit.Framework;
+using MonoDevelop.Ide.Commands;
+using MonoDevelop.Core;
+using System.IO;
+using System.Xml;
+using System;
+using System.Collections.Generic;
namespace UserInterfaceTests
{
- [TestFixture]
+ [TestFixture, Timeout(60000)]
[Category ("Dialog")]
+ [Category ("NuGet")]
[Category ("PackagesDialog")]
public class NuGetDialogTests : CreateBuildTemplatesTestBase
{
- [Test]
+ [Test, Category("Smoke")]
+ [Description ("Add a single NuGet Package")]
public void AddPackagesTest ()
{
CreateProject ();
NuGetController.AddPackage (new NuGetPackageOptions {
PackageName = "CommandLineParser",
- Version = "2.0.1-pre",
+ Version = "2.0.257-beta",
IsPreRelease = true
- });
+ }, this);
}
- ProjectDetails CreateProject ()
+ [Test, Timeout(300000), Category ("Cycle6")]
+ [Description ("When a solution is opened and package updates are available, don't show in status bar")]
+ public void DontShowPackageUpdatesAvailable ()
{
var templateOptions = new TemplateSelectionOptions {
CategoryRoot = OtherCategoryRoot,
@@ -53,6 +63,201 @@ namespace UserInterfaceTests
TemplateKind = "Console Project"
};
var projectDetails = new ProjectDetails (templateOptions);
+ CreateProject (templateOptions, projectDetails);
+ NuGetController.AddPackage (new NuGetPackageOptions {
+ PackageName = "CommandLineParser",
+ Version = "1.9.3.34",
+ IsPreRelease = false
+ }, this);
+
+ string solutionFolder = GetSolutionDirectory ();
+ string solutionPath = Path.Combine (solutionFolder, projectDetails.SolutionName+".sln");
+ var projectPath = Path.Combine (solutionFolder, projectDetails.ProjectName, projectDetails.ProjectName + ".csproj");
+ Assert.IsTrue (File.Exists (projectPath));
+
+ Workbench.CloseWorkspace (this);
+
+ Workbench.OpenWorkspace (solutionPath, this);
+ try {
+ const string expected = "When a solution is opened and package updates are available, it don't show in status bar";
+ ReproStep (expected);
+ Ide.WaitForPackageUpdate ();
+ var failureMessage = string.Format ("Expected: {0}\nActual: {1}",
+ expected, "When a solution is opened and package updates are available, it shows in status bar");
+ ReproStep (failureMessage);
+ Assert.Fail (failureMessage);
+ } catch (TimeoutException) {
+ Session.DebugObject.Debug ("WaitForPackageUpdate throws TimeoutException as expected");
+ }
+ Ide.WaitForSolutionLoaded ();
+ TakeScreenShot ("Solution-Ready");
+ }
+
+ [Test, Category("Smoke")]
+ [Description ("Add a single NuGet Package and check if it's readme.txt opens")]
+ public void TestReadmeTxtOpens ()
+ {
+ CreateProject ();
+ NuGetController.AddPackage (new NuGetPackageOptions {
+ PackageName = "RestSharp",
+ Version = "105.2.3",
+ IsPreRelease = true
+ }, this);
+ WaitForNuGetReadmeOpened ();
+ }
+
+ [Test, Category ("Cycle6")]
+ [Description ("Add a single NuGet Package. Check if readme.txt opens even when updating")]
+ public void TestReadmeTxtUpgradeOpens ()
+ {
+ CreateProject ();
+ NuGetController.AddPackage (new NuGetPackageOptions {
+ PackageName = "RestSharp",
+ Version = "105.2.2",
+ IsPreRelease = true
+ }, this);
+ WaitForNuGetReadmeOpened ();
+
+ Session.ExecuteCommand (FileCommands.CloseFile);
+ Session.WaitForElement (IdeQuery.TextArea);
+ TakeScreenShot ("About-To-Update-Package");
+ NuGetController.UpdatePackage (new NuGetPackageOptions {
+ PackageName = "RestSharp",
+ Version = "105.2.3",
+ IsPreRelease = true
+ }, this);
+ WaitForNuGetReadmeOpened ();
+ }
+
+ [Test, Category("Smoke"), Category ("Cycle6")]
+ [Timeout (90000)]
+ [Description ("When readme.txt from a package has already been opened, adding same package to another project should not open readme.txt")]
+ public void TestDontOpenReadmeOpenedInOther ()
+ {
+ var packageInfo = new NuGetPackageOptions {
+ PackageName = "RestSharp",
+ Version = "105.2.3",
+ IsPreRelease = true
+ };
+
+ var projectDetails = CreateProject ();
+ NuGetController.AddPackage (packageInfo, this);
+ WaitForNuGetReadmeOpened ();
+ Session.ExecuteCommand (FileCommands.CloseFile);
+
+ var pclTemplateOptions = new TemplateSelectionOptions {
+ CategoryRoot = "Other",
+ Category = ".NET",
+ TemplateKindRoot = "General",
+ TemplateKind = "Library"
+ };
+ var pclProjectDetails = ProjectDetails.ToExistingSolution (projectDetails.SolutionName,
+ GenerateProjectName (pclTemplateOptions.TemplateKind));
+ CreateProject (pclTemplateOptions, pclProjectDetails);
+ Ide.WaitForIdeIdle (30);
+
+ SolutionExplorerController.SelectProject (projectDetails.SolutionName, pclProjectDetails.ProjectName);
+ NuGetController.AddPackage (packageInfo, this);
+ try {
+ WaitForNuGetReadmeOpened (false);
+ var failureMessage = string.Format ("Expected: {0}\nActual:{1}",
+ "readme.txt tab should not open", "readme.txt tab opens");
+ ReproStep (failureMessage);
+ Assert.Fail (failureMessage);
+ } catch (TimeoutException) {
+ Session.DebugObject.Debug ("readme.txt tab failed to open as expected");
+ }
+ }
+
+ [Test, Category ("Cycle6")]
+ [Description ("Add a package with powershell scripts and assert that Xamarin Studio doesn't report warnings "+
+ "when trying to add powershell scripts to Xamarin Studio")]
+ public void TestDontShowWarningWithPowerShellScripts ()
+ {
+ CreateProject ();
+ NuGetController.AddPackage (new NuGetPackageOptions {
+ PackageName = "Newtonsoft.Json",
+ }, this);
+ WaitForNuGet.Success ("Newtonsoft.Json", NuGetOperations.Add, false, this);
+ TakeScreenShot ("NewtonSoftJson-Package-Added-Without-Warning");
+ }
+
+ [Test, Timeout (300000), Category ("Cycle6")]
+ [Description ("When a NuGet package is updated, the 'Local Copy' value should be preserved")]
+ public void TestLocalCopyPreservedUpdate ()
+ {
+ var templateOptions = new TemplateSelectionOptions {
+ CategoryRoot = OtherCategoryRoot,
+ Category = ".NET",
+ TemplateKindRoot = GeneralKindRoot,
+ TemplateKind = "Console Project"
+ };
+ var projectDetails = new ProjectDetails (templateOptions);
+ CreateProject (templateOptions, projectDetails);
+ NuGetController.AddPackage (new NuGetPackageOptions {
+ PackageName = "CommandLineParser",
+ Version = "1.9.71",
+ IsPreRelease = false
+ }, this);
+
+ string solutionFolder = GetSolutionDirectory ();
+ string solutionPath = Path.Combine (solutionFolder, projectDetails.SolutionName+".sln");
+ var projectPath = Path.Combine (solutionFolder, projectDetails.ProjectName, projectDetails.ProjectName + ".csproj");
+ Assert.IsTrue (File.Exists (projectPath));
+
+ ReproStep ("Check 'Local Copy' on CommandLine package under References");
+
+ Workbench.CloseWorkspace (this);
+
+ AddOrCheckLocalCopy (projectPath, true);
+
+ Workbench.OpenWorkspace (solutionPath, this);
+
+ NuGetController.UpdateAllNuGetPackages (this);
+
+ ReproStep ("Check if CommandLine package under References has 'Local Copy' checked");
+ AddOrCheckLocalCopy (projectPath, false);
+ }
+
+ void AddOrCheckLocalCopy (string projectPath, bool addLocalCopy)
+ {
+ using (var stream = new FileStream (projectPath, FileMode.Open, FileAccess.ReadWrite)) {
+ var xmlDoc = new XmlDocument();
+ xmlDoc.Load(stream);
+ var ns = "http://schemas.microsoft.com/developer/msbuild/2003";
+ XmlNamespaceManager xnManager = new XmlNamespaceManager(xmlDoc.NameTable);
+ xnManager.AddNamespace("ui", ns);
+ XmlNode root = xmlDoc.DocumentElement;
+ var uitest = root.SelectSingleNode ("//ui:Reference[@Include=\"CommandLine\"]", xnManager);
+ Assert.IsNotNull (uitest, "Cannot find CommandLine package reference in file: "+projectPath);
+ var privateUITestNode = uitest.SelectSingleNode ("./ui:Private", xnManager);
+
+ if (addLocalCopy) {
+ Assert.IsNull (privateUITestNode, uitest.InnerXml, "CommandLine package is already set to 'No Local Copy'");
+ var privateNode = xmlDoc.CreateElement ("Private", ns);
+ privateNode.InnerText = "False";
+ uitest.AppendChild (privateNode);
+ stream.SetLength (0);
+ xmlDoc.Save (stream);
+ stream.Flush ();
+ } else {
+ Assert.IsNotNull (privateUITestNode, "Cannot find CommandLine package with 'No Local Copy' set");
+ Assert.AreEqual (privateUITestNode.InnerText, "False");
+ }
+ stream.Close ();
+ }
+ }
+
+
+ ProjectDetails CreateProject (TemplateSelectionOptions templateOptions = null, ProjectDetails projectDetails = null)
+ {
+ templateOptions = templateOptions ?? new TemplateSelectionOptions {
+ CategoryRoot = OtherCategoryRoot,
+ Category = ".NET",
+ TemplateKindRoot = GeneralKindRoot,
+ TemplateKind = "Console Project"
+ };
+ projectDetails = projectDetails ?? new ProjectDetails (templateOptions);
CreateProject (templateOptions,
projectDetails,
new GitOptions { UseGit = true, UseGitIgnore = true});
@@ -60,6 +265,20 @@ namespace UserInterfaceTests
FoldersToClean.Add (projectDetails.SolutionLocation);
return projectDetails;
}
+
+ void WaitForNuGetReadmeOpened (bool expectSuccess = true)
+ {
+ ReproStep ("Wait for tab with readme.txt to be opened");
+ try {
+ Session.WaitForElement (c => c.Window ().Marked ("MonoDevelop.Ide.Gui.DefaultWorkbench").Property ("TabControl.CurrentTab.Text", "readme.txt"));
+ } catch (TimeoutException) {
+ if (expectSuccess) {
+ ReproStep (string.Format ("Expected: {0}\nActual: {1}",
+ "readme.txt tab should open", "readm.txt tab did not open"));
+ }
+ throw;
+ }
+ }
}
}
diff --git a/main/tests/UserInterfaceTests/Exceptions/CreateProjectException.cs b/main/tests/UserInterfaceTests/Exceptions/CreateProjectException.cs
new file mode 100644
index 0000000000..0e91464f13
--- /dev/null
+++ b/main/tests/UserInterfaceTests/Exceptions/CreateProjectException.cs
@@ -0,0 +1,37 @@
+//
+// CreateProjectException.cs
+//
+// Author:
+// Manish Sinha <manish.sinha@xamarin.com>
+//
+// Copyright (c) 2015 Xamarin Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+
+namespace UserInterfaceTests
+{
+ public class CreateProjectException : Exception
+ {
+ public CreateProjectException (string message): base (message)
+ {
+ }
+ }
+}
+
diff --git a/main/tests/UserInterfaceTests/Exceptions/NuGetException.cs b/main/tests/UserInterfaceTests/Exceptions/NuGetException.cs
new file mode 100644
index 0000000000..935dc6d3b4
--- /dev/null
+++ b/main/tests/UserInterfaceTests/Exceptions/NuGetException.cs
@@ -0,0 +1,41 @@
+//
+// NuGetException.cs
+//
+// Author:
+// Manish Sinha <manish.sinha@xamarin.com>
+//
+// Copyright (c) 2015 Xamarin Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+
+namespace UserInterfaceTests
+{
+ public class NuGetException : Exception
+ {
+ public NuGetException (string message) : base (message)
+ {
+ }
+
+ public NuGetException (string message, Exception innerExceotion) : base (message, innerExceotion)
+ {
+ }
+ }
+}
+
diff --git a/main/tests/UserInterfaceTests/Exceptions/TemplateSelectionException.cs b/main/tests/UserInterfaceTests/Exceptions/TemplateSelectionException.cs
new file mode 100644
index 0000000000..041f4bb5e5
--- /dev/null
+++ b/main/tests/UserInterfaceTests/Exceptions/TemplateSelectionException.cs
@@ -0,0 +1,37 @@
+//
+// TemplateSelectionException.cs
+//
+// Author:
+// Manish Sinha <manish.sinha@xamarin.com>
+//
+// Copyright (c) 2015 Xamarin Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+
+namespace UserInterfaceTests
+{
+ public class TemplateSelectionException : Exception
+ {
+ public TemplateSelectionException (string message) : base (message)
+ {
+ }
+ }
+}
+
diff --git a/main/tests/UserInterfaceTests/Ide.cs b/main/tests/UserInterfaceTests/Ide.cs
index 14a4b86857..37af208fa8 100644
--- a/main/tests/UserInterfaceTests/Ide.cs
+++ b/main/tests/UserInterfaceTests/Ide.cs
@@ -1,5 +1,5 @@
//
-// IdeApi.cs
+// Ide.cs
//
// Author:
// Lluis Sanchez Gual <lluis@novell.com>
@@ -26,6 +26,7 @@
using System;
using System.Threading;
+using System.Linq;
using MonoDevelop.Core;
using MonoDevelop.Core.Instrumentation;
@@ -33,11 +34,8 @@ using MonoDevelop.Ide.Commands;
using MonoDevelop.Components.AutoTest;
using NUnit.Framework;
-
-using Gdk;
-using System.Linq;
-
-
+using System.Collections.Generic;
+
namespace UserInterfaceTests
{
public static class Ide
@@ -48,12 +46,13 @@ namespace UserInterfaceTests
public static void OpenFile (FilePath file)
{
- Session.GlobalInvoke ("MonoDevelop.Ide.IdeApp.Workbench.OpenDocument", (string) file, true);
+ Session.RunAndWaitForTimer (() => Session.GlobalInvoke ("MonoDevelop.Ide.IdeApp.Workbench.OpenDocument", (string)file, true), "Ide.Shell.DocumentOpened");
Assert.AreEqual (file, GetActiveDocumentFilename ());
}
public static void CloseAll ()
{
+ Session.ExecuteCommand (FileCommands.SaveAll);
Session.ExecuteCommand (FileCommands.CloseWorkspace);
Session.ExitApp ();
}
@@ -63,15 +62,13 @@ namespace UserInterfaceTests
return Session.GetGlobalValue<FilePath> ("MonoDevelop.Ide.IdeApp.Workbench.ActiveDocument.FileName");
}
- public static bool BuildSolution (bool isPass = true, int timeoutInSecs = 180)
+ public static bool BuildSolution (bool isPass = true, int timeoutInSecs = 360)
{
- Session.RunAndWaitForTimer (() => Session.ExecuteCommand (ProjectCommands.BuildSolution),
- "Ide.Shell.ProjectBuilt", timeout: timeoutInSecs * 1000);
- var status = IsBuildSuccessful ();
- return isPass == status;
+ Session.RunAndWaitForTimer (() => Session.ExecuteCommand (ProjectCommands.BuildSolution), "Ide.Shell.ProjectBuilt", timeoutInSecs * 1000);
+ return isPass == Workbench.IsBuildSuccessful (timeoutInSecs);
}
- public static void WaitUntil (Func<bool> done, int timeout = 20000, int pollStep = 200)
+ public static void WaitUntil (Func<bool> done, int timeout = 20000, int pollStep = 200, Func<string> timeoutMessage = null)
{
do {
if (done ())
@@ -80,30 +77,22 @@ namespace UserInterfaceTests
Thread.Sleep (pollStep);
} while (timeout > 0);
- throw new TimeoutException ("Timed out waiting for Function: "+done.Method.Name);
+ if (timeoutMessage != null) {
+ throw new TimeoutException ("Timed out waiting for Function: " + done.Method.Name + " Message: " + timeoutMessage ());
+ } else {
+ throw new TimeoutException ("Timed out waiting for Function: " + done.Method.Name);
+ }
}
- //no saner way to do this
- public static string GetStatusMessage (int timeout = 20000)
+ public static bool ClickButtonAlertDialog (string buttonText)
{
if (Platform.IsMac) {
- WaitUntil (
- () => Session.GetGlobalValue<string> ("MonoDevelop.Ide.IdeApp.Workbench.RootWindow.StatusBar.text") != string.Empty,
- timeout
- );
- return (string)Session.GetGlobalValue ("MonoDevelop.Ide.IdeApp.Workbench.RootWindow.StatusBar.text");
+ Ide.WaitUntil (() => Session.Query (c => c.Marked ("Xamarin Studio").Marked ("AppKit.NSPanel")).Any ());
+ return Session.ClickElement (c => c.Marked ("AppKit.NSButton").Text (buttonText));
+ } else {
+ Ide.WaitUntil (() => Session.Query (c => c.Window ().Marked ("MonoDevelop.Ide.Gui.Dialogs.GtkAlertDialog")).Any ());
+ return Session.ClickElement (c => c.Window ().Marked ("MonoDevelop.Ide.Gui.Dialogs.GtkAlertDialog").Children ().Button ().Text (buttonText));
}
-
- WaitUntil (
- () => Session.GetGlobalValue<int> ("MonoDevelop.Ide.IdeApp.Workbench.RootWindow.StatusBar.messageQueue.Count") == 0,
- timeout
- );
- return (string) Session.GetGlobalValue ("MonoDevelop.Ide.IdeApp.Workbench.RootWindow.StatusBar.renderArg.CurrentText");
- }
-
- public static bool IsBuildSuccessful ()
- {
- return Session.ErrorCount (MonoDevelop.Ide.Tasks.TaskSeverity.Error) == 0;
}
public static void RunAndWaitForTimer (Action action, string counter, int timeout = 20000)
@@ -113,32 +102,51 @@ namespace UserInterfaceTests
action ();
- WaitUntil (() => c.TotalTime > tt, timeout);
+ WaitUntil (() => c.TotalTime > tt, timeout,
+ timeoutMessage: () => "Counter:" + counter + " T1:" + c.TotalTime + " T2:" + tt + " Timeout:" + timeout);
}
+
+ public readonly static Action WaitForPackageUpdateOrSaved = delegate {
+ try {
+ WaitForPackageUpdate ();
+ } catch (TimeoutException e1) {
+ try {
+ WaitForSolutionLoaded ();
+ } catch (TimeoutException e2) {
+ throw new TimeoutException (string.Format ("{0}\n{1}", e1.Message, e2.Message), e1);
+ }
+ }
+ };
+
public readonly static Action EmptyAction = delegate { };
+ static string[] waitForNuGetMessages = {
+ "Package updates are available.",
+ "Packages are up to date.",
+ "No updates found but warnings were reported.",
+ "Packages successfully added.",
+ "Packages successfully updated.",
+ "Packages added with warnings.",
+ "Packages updated with warnings."};
+
public readonly static Action WaitForPackageUpdate = delegate {
- WaitForStatusMessage (new [] {
- "Package updates are available.",
- "Packages are up to date.",
- "No updates found but warnings were reported.",
- "Packages successfully updated.",
- "Packages updated with warnings."},
- timeoutInSecs: 360, pollStepInSecs: 5);
+ WaitForStatusMessage (waitForNuGetMessages, timeoutInSecs: 180, pollStepInSecs: 5);
};
+ public static void WaitForPackageUpdateExtra (List<string> otherMessages)
+ {
+ otherMessages.AddRange (waitForNuGetMessages);
+ WaitForStatusMessage (otherMessages.ToArray (), timeoutInSecs: 180, pollStepInSecs: 5);
+ }
+
public readonly static Action WaitForSolutionCheckedOut = delegate {
WaitForStatusMessage (new [] {"Solution checked out", "Solution Loaded."}, timeoutInSecs: 360, pollStepInSecs: 5);
};
- public static void WaitForSolutionLoaded (Action<string> afterEachStep)
- {
- WaitForStatusMessage (new [] {"Loading..."});
- afterEachStep ("Loading-Solution");
- WaitForNoStatusMessage (new [] {"Loading..."});
- afterEachStep ("Solution-Loaded");
- }
+ public readonly static Action WaitForSolutionLoaded = delegate {
+ WaitForStatusMessage (new [] {"Project saved.", "Solution loaded."}, timeoutInSecs: 120, pollStepInSecs: 5);
+ };
public static void WaitForStatusMessage (string[] statusMessage, int timeoutInSecs = 240, int pollStepInSecs = 1)
{
@@ -153,10 +161,71 @@ namespace UserInterfaceTests
static void PollStatusMessage (string[] statusMessage, int timeoutInSecs, int pollStepInSecs, bool waitForMessage = true)
{
Ide.WaitUntil (() => {
- var actualStatusMessage = Ide.GetStatusMessage ();
- return waitForMessage == (statusMessage.Contains (actualStatusMessage, StringComparer.OrdinalIgnoreCase));
- }, pollStep: pollStepInSecs * 1000, timeout: timeoutInSecs * 1000);
+ string actualStatusMessage = string.Empty;
+ try {
+ actualStatusMessage = Workbench.GetStatusMessage ();
+ return waitForMessage == (statusMessage.Contains (actualStatusMessage, StringComparer.OrdinalIgnoreCase));
+ } catch (TimeoutException e) {
+ throw new TimeoutException (
+ string.Format ("Timed out. Found status message '{0}'\nand expected one of these:\n\t {1}",
+ actualStatusMessage, string.Join ("\n\t", statusMessage)), e);
+ }
+ },
+ pollStep: pollStepInSecs * 1000,
+ timeout: timeoutInSecs * 1000,
+ timeoutMessage: () => "GetStatusMessage=" + Workbench.GetStatusMessage ());
+ }
+
+ static readonly List<string> ignoreStatusMessgaes = new List<string> {
+ "Saving...",
+ "Restoring packages for solution...",
+ "Restoring packages before update...",
+ "Restoring packages for project...",
+ "Updating packages in solution...",
+ "Updating packages in project..."
+ };
+
+ public static void WaitForIdeIdle (uint totalTimeoutInSecs = 100, uint idlePeriodInSecs = 10, string[] ignoreMessages = null)
+ {
+ uint retriesLeft = (uint)Math.Ceiling ((double)totalTimeoutInSecs/(double)idlePeriodInSecs);
+ ManualResetEvent resetEvent = new ManualResetEvent (false);
+ if (ignoreMessages != null)
+ ignoreStatusMessgaes.AddRange (ignoreMessages);
+
+ var timer = new System.Timers.Timer {
+ Interval = idlePeriodInSecs * 1000,
+ AutoReset = true
+ };
+ bool didTimeout = false;
+
+ var initialStatusMessage = Workbench.GetStatusMessage (waitForNonEmpty: false);
+ timer.Elapsed += (sender, e) => {
+ if (retriesLeft == 0) {
+ didTimeout = true;
+ resetEvent.Set ();
+ }
+
+ var finalStatusMessage = Workbench.GetStatusMessage (waitForNonEmpty: false);
+ var isIdle = string.Equals (initialStatusMessage, finalStatusMessage) && !ignoreStatusMessgaes.Contains (finalStatusMessage);
+
+ if (!isIdle) {
+ retriesLeft--;
+ initialStatusMessage = finalStatusMessage;
+ }
+ if (isIdle) {
+ resetEvent.Set ();
+ }
+ };
+
+ timer.Start ();
+ resetEvent.WaitOne ();
+ timer.Stop ();
+ timer.AutoReset = false;
+ timer.Dispose ();
+
+ if (didTimeout)
+ throw new TimeoutException ("Timeout waiting for IDE to be ready and idle");
}
}
-} \ No newline at end of file
+}
diff --git a/main/tests/UserInterfaceTests/IdeQuery.cs b/main/tests/UserInterfaceTests/IdeQuery.cs
index c47068d6ed..69fda74e57 100644
--- a/main/tests/UserInterfaceTests/IdeQuery.cs
+++ b/main/tests/UserInterfaceTests/IdeQuery.cs
@@ -25,6 +25,7 @@
// THE SOFTWARE.
using System;
using MonoDevelop.Components.AutoTest;
+using MonoDevelop.Core;
namespace UserInterfaceTests
{
@@ -36,6 +37,18 @@ namespace UserInterfaceTests
readonly static Func<AppQuery, AppQuery> _editRemoteDialog = c => c.Window ().Marked ("MonoDevelop.VersionControl.Git.EditRemoteDialog");
readonly static Func<AppQuery, AppQuery> _editBranchDialog = c => c.Window ().Marked ("MonoDevelop.VersionControl.Git.EditBranchDialog");
readonly static Func<AppQuery, AppQuery> _textArea = c => c.Window ().Children ().Marked ("Mono.TextEditor.TextArea");
+ readonly static Func<AppQuery, AppQuery> _xamarinUpdate = c => c.Marked ("Xamarin Update");
+
+ readonly static Func<AppQuery, AppQuery> _macRunButton = c => c.Marked ("MonoDevelop.MacIntegration.MainToolbar.RunButton");
+
+ public static Func<AppQuery, AppQuery> RunButton
+ {
+ get {
+ if (Platform.IsMac)
+ return _macRunButton;
+ throw new NotImplementedException ("Run Button is not implemented for Windows");
+ }
+ }
public static Func<AppQuery, AppQuery> DefaultWorkbench
{
@@ -78,6 +91,13 @@ namespace UserInterfaceTests
return _textArea;
}
}
+
+ public static Func<AppQuery, AppQuery> XamarinUpdate
+ {
+ get {
+ return _xamarinUpdate;
+ }
+ }
}
}
diff --git a/main/tests/UserInterfaceTests/LogMessageValidator.cs b/main/tests/UserInterfaceTests/LogMessageValidator.cs
new file mode 100644
index 0000000000..fc2f875f14
--- /dev/null
+++ b/main/tests/UserInterfaceTests/LogMessageValidator.cs
@@ -0,0 +1,56 @@
+//
+// LogMessageValidator.cs
+//
+// Author:
+// Manish Sinha <manish.sinha@xamarin.com>
+//
+// Copyright (c) 2015 Xamarin Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.IO;
+using NUnit.Framework;
+using System.Collections.Generic;
+
+namespace UserInterfaceTests
+{
+ public class LogMessageValidator
+ {
+ static List<string> invalidLogStrings = new List<string> {
+ "Gtk-Critical: void gtk_container_remove(GtkContainer , GtkWidget )"
+ };
+
+ public static void Validate (string fileName)
+ {
+ string readIdeLog = string.Empty;
+ using (FileStream fileStream = new FileStream (fileName, FileMode.Open,
+ FileAccess.Read, FileShare.ReadWrite)) {
+ using (StreamReader streamReader = new StreamReader (fileStream)) {
+ readIdeLog = streamReader.ReadToEnd ();
+ }
+ }
+
+ foreach (var error in invalidLogStrings) {
+ Assert.IsFalse (readIdeLog.Contains (error),
+ string.Format ("GTK Error detected in Ide.log file:\n\t{0}",error));
+ }
+ }
+ }
+}
+
diff --git a/main/tests/UserInterfaceTests/TemplateTestOptions.cs b/main/tests/UserInterfaceTests/TemplateTestOptions.cs
index 6385b9928b..370f4237ce 100644
--- a/main/tests/UserInterfaceTests/TemplateTestOptions.cs
+++ b/main/tests/UserInterfaceTests/TemplateTestOptions.cs
@@ -23,6 +23,7 @@
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
+
using System;
namespace UserInterfaceTests
@@ -57,6 +58,12 @@ namespace UserInterfaceTests
public string TemplateKindRoot { get; set; }
public string TemplateKind { get; set; }
+
+ public override string ToString ()
+ {
+ return string.Format ("CategoryRoot={0}, Category={1}, TemplateKindRoot={2}, TemplateKind={3}",
+ CategoryRoot, Category, TemplateKindRoot, TemplateKind);
+ }
}
public class GitOptions
@@ -70,6 +77,11 @@ namespace UserInterfaceTests
public bool UseGit { get; set; }
public bool UseGitIgnore { get; set; }
+
+ public override string ToString ()
+ {
+ return string.Format ("UseGit={0}, UseGitIgnore={1}", UseGit, UseGitIgnore);
+ }
}
public class ProjectDetails
@@ -78,6 +90,7 @@ namespace UserInterfaceTests
{
SolutionLocation = Util.CreateTmpDir ();
ProjectInSolution = true;
+ BuildTimeout = TimeSpan.FromSeconds (180);
}
public ProjectDetails (TemplateSelectionOptions templateData) : this ()
@@ -86,6 +99,16 @@ namespace UserInterfaceTests
SolutionName = ProjectName;
}
+ public static ProjectDetails ToExistingSolution (string solutionName, string projectName)
+ {
+ return new ProjectDetails {
+ ProjectName = projectName,
+ SolutionName = solutionName,
+ AddProjectToExistingSolution = true,
+ SolutionLocation = null
+ };
+ }
+
public string ProjectName { get; set; }
public string SolutionName { get; set; }
@@ -93,6 +116,16 @@ namespace UserInterfaceTests
public string SolutionLocation { get; set; }
public bool ProjectInSolution { get; set; }
+
+ public bool AddProjectToExistingSolution { get; set; }
+
+ public TimeSpan BuildTimeout { get; set; }
+
+ public override string ToString ()
+ {
+ return string.Format ("ProjectName={0}, SolutionName={1}, SolutionLocation={2}, ProjectInSolution={3}, AddProjectToExistingSolution={4}",
+ ProjectName, SolutionName, SolutionLocation, ProjectInSolution, AddProjectToExistingSolution);
+ }
}
public class NewFileOptions
@@ -106,6 +139,12 @@ namespace UserInterfaceTests
public string FileTypeCategoryRoot { get; set; }
public string AddToProjectName { get; set; }
+
+ public override string ToString ()
+ {
+ return string.Format ("FileName={0}, FileType={1}, FileTypeCategory={2}, FileTypeCategoryRoot={3}, AddToProjectName={4}",
+ FileName, FileType, FileTypeCategory, FileTypeCategoryRoot, AddToProjectName);
+ }
}
}
diff --git a/main/tests/UserInterfaceTests/TemplateTests/ASPNETTemplateTests.cs b/main/tests/UserInterfaceTests/TemplateTests/ASPNETTemplateTests.cs
index 0ab34f71b6..904726c71d 100644
--- a/main/tests/UserInterfaceTests/TemplateTests/ASPNETTemplateTests.cs
+++ b/main/tests/UserInterfaceTests/TemplateTests/ASPNETTemplateTests.cs
@@ -35,15 +35,22 @@ namespace UserInterfaceTests
{
readonly string aspCategory = "ASP.NET";
- [Test]
- [TestCase ("Empty ASP.NET MVC Project", BeforeBuildAction.WaitForPackageUpdate, TestName = "TestEmptyASPMVCProject")]
- [TestCase ("Empty ASP.NET Project", BeforeBuildAction.None, TestName = "TestEmptyASPProject")]
- [TestCase ("ASP.NET MVC Project", BeforeBuildAction.WaitForPackageUpdate, TestName = "TestASPMVCProject")]
- [TestCase ("ASP.NET MVC Project with Unit Tests", BeforeBuildAction.WaitForPackageUpdate, TestName = "TestASPMVCProjectWithUnitTests")]
- [TestCase ("ASP.NET MVC Razor Project", BeforeBuildAction.WaitForPackageUpdate, TestName = "TestASPMVCMazorProject")]
- [TestCase ("ASP.NET MVC Razor Project with Unit Tests", BeforeBuildAction.WaitForPackageUpdate, TestName = "TestASPMVCMazorProjectWithUnitTests")]
- [TestCase ("ASP.NET Project", BeforeBuildAction.None, TestName = "TestASPProject")]
- public void RunASPTest (string templateName, BeforeBuildAction beforeBuild)
+ [Test, Timeout (90000)]
+ [TestCase ("Empty ASP.NET MVC Project", TestName = "TestEmptyASPMVCProject",
+ Description = "Create and build Empty ASP.NET MVC Project")]
+ [TestCase ("Empty ASP.NET Project", TestName = "TestEmptyASPProject",
+ Description = "Create and build Empty ASP.NET MVC Project")]
+ [TestCase ("ASP.NET MVC Project", TestName = "TestASPMVCProject",
+ Description = "Create and build ASP.NET MVC Project")]
+ [TestCase ("ASP.NET MVC Project with Unit Tests", TestName = "TestASPMVCProjectWithUnitTests",
+ Description = "Create and build ASP.NET MVC Project with Unit Tests")]
+ [TestCase ("ASP.NET MVC Razor Project", TestName = "TestASPMVCMazorProject",
+ Description = "Create and build ASP.NET MVC Razor Project")]
+ [TestCase ("ASP.NET MVC Razor Project with Unit Tests", TestName = "TestASPMVCMazorProjectWithUnitTests",
+ Description = "Create and build ASP.NET MVC Razor Project with Unit Tests", Category="Smoke")]
+ [TestCase ("ASP.NET Project", TestName = "TestASPProject",
+ Description = "Create and build ASP.NET Project")]
+ public void RunASPTest (string templateName)
{
var templateOptions = new TemplateSelectionOptions {
CategoryRoot = OtherCategoryRoot,
@@ -51,7 +58,8 @@ namespace UserInterfaceTests
TemplateKindRoot = GeneralKindRoot,
TemplateKind = templateName
};
- CreateBuildProject (templateOptions, beforeBuild.GetAction ());
+
+ CreateBuildProject (templateOptions, () => Ide.WaitForIdeIdle (totalTimeoutInSecs: 50));
}
}
}
diff --git a/main/tests/UserInterfaceTests/TemplateTests/DotNetTemplatesTest.cs b/main/tests/UserInterfaceTests/TemplateTests/DotNetTemplatesTest.cs
index 53abdb7d70..48eb89b26b 100644
--- a/main/tests/UserInterfaceTests/TemplateTests/DotNetTemplatesTest.cs
+++ b/main/tests/UserInterfaceTests/TemplateTests/DotNetTemplatesTest.cs
@@ -34,12 +34,13 @@ namespace UserInterfaceTests
{
readonly string dotNetCategory = ".NET";
- [Test]
- [TestCase ("Console Project", BeforeBuildAction.None, TestName = "TestCreateBuildConsoleProject")]
- [TestCase ("Gtk# 2.0 Project", BeforeBuildAction.None, TestName = "TestCreateBuildGtkSharp20Project")]
- [TestCase ("Library", BeforeBuildAction.None, TestName = "TestCreateBuildLibrary")]
- [TestCase ("NUnit Library Project", BeforeBuildAction.WaitForPackageUpdate, TestName = "TestCreateBuildNUnitLibraryProject")]
- public void RunDotNetTests (string templateName, BeforeBuildAction beforeBuild)
+ [Test, Timeout (90000)]
+ [TestCase ("Console Project", 30, TestName = "TestCreateBuildConsoleProject", Description = "Create and build C# Console Project", Category="Smoke")]
+ [TestCase ("Gtk# 2.0 Project", 30, TestName = "TestCreateBuildGtkSharp20Project", Description = "Create and build a GTK#2 Project")]
+ [TestCase ("Library", 30, TestName = "TestCreateBuildLibrary", Description = "Create and build a Library Project")]
+ [TestCase ("NUnit Library Project", 50, TestName = "TestCreateBuildNUnitLibraryProject",
+ Description = "Create and build NUnit Library Project", Category="Smoke")]
+ public void RunDotNetTests (string templateName, int totalTimeoutInSecs)
{
var templateOptions = new TemplateSelectionOptions {
CategoryRoot = OtherCategoryRoot,
@@ -47,7 +48,7 @@ namespace UserInterfaceTests
TemplateKindRoot = GeneralKindRoot,
TemplateKind = templateName
};
- CreateBuildProject (templateOptions, beforeBuild.GetAction ());
+ CreateBuildProject (templateOptions, () => Ide.WaitForIdeIdle ((uint)totalTimeoutInSecs));
}
}
}
diff --git a/main/tests/UserInterfaceTests/TemplateTests/MiscTemplatesTest.cs b/main/tests/UserInterfaceTests/TemplateTests/MiscTemplatesTest.cs
index 196e3392db..8a041ac129 100644
--- a/main/tests/UserInterfaceTests/TemplateTests/MiscTemplatesTest.cs
+++ b/main/tests/UserInterfaceTests/TemplateTests/MiscTemplatesTest.cs
@@ -28,18 +28,25 @@ using NUnit.Framework;
namespace UserInterfaceTests
{
- [TestFixture]
- [Category("Misc")]
+ [TestFixture, Timeout (60000), Category ("Misc")]
public class MiscTemplatesTest : CreateBuildTemplatesTestBase
{
readonly string miscCategory = "Miscellaneous";
[Test]
- [TestCase ("Generic Project", "Generic", TestName = "TestMiscGenericProject")]
- [TestCase ("Packaging project", "Generic", TestName = "TestMiscPackagingProject")]
- [TestCase ("Shared Library", "C/C++", TestName = "TestMiscCCPlusSharedLibrary")]
- [TestCase ("Static Library", "C/C++", TestName = "TestMiscCCPlusStaticLibrary")]
- [TestCase ("Console Project", "C/C++", TestName = "TestMiscCCPlusConsoleProject")]
+ [Platform (Exclude="Win")]
+ [TestCase ("Shared Library", "C/C++", TestName = "TestMiscCCPlusSharedLibrary", Description = "Create and build Shared C/C++ Library")]
+ [TestCase ("Static Library", "C/C++", TestName = "TestMiscCCPlusStaticLibrary", Description = "Create and build Static C/C++ Library")]
+ [TestCase ("Console Project", "C/C++", TestName = "TestMiscCCPlusConsoleProject", Description = "Create and build Console C/C++ Project")]
+ public void RunMiscCPlusPlusTemplatesTest (string templateName, string templateKind)
+ {
+ RunMiscTemplatesTest (templateName, templateKind);
+ }
+
+ [Test]
+ [TestCase ("Generic Project", "Generic", TestName = "TestMiscGenericProject", Description = "Create and build Generic Project")]
+ [TestCase ("Packaging project", "Generic", TestName = "TestMiscPackagingProject", Description = "Create and build Packaging Project")]
+
public void RunMiscTemplatesTest (string templateName, string templateKind)
{
var templateOptions = new TemplateSelectionOptions {
@@ -48,7 +55,8 @@ namespace UserInterfaceTests
TemplateKindRoot = templateKind,
TemplateKind = templateName
};
- CreateBuildProject (templateOptions, EmptyAction);
+ CreateBuildProject (templateOptions, () => Ide.WaitForIdeIdle ());
+ IsTemplateSelected (templateOptions);
}
}
}
diff --git a/main/tests/UserInterfaceTests/TestService.cs b/main/tests/UserInterfaceTests/TestService.cs
index ba24222dee..a66d0c374c 100644
--- a/main/tests/UserInterfaceTests/TestService.cs
+++ b/main/tests/UserInterfaceTests/TestService.cs
@@ -38,8 +38,6 @@ namespace UserInterfaceTests
{
Session = new AutoTestClientSession ();
- //TODO: support for testing the installed app
-
Session.StartApplication (file: monoDevelopBinPath, environment: new Dictionary<string,string> {
{ "MONODEVELOP_TEST_PROFILE", profilePath ?? Util.CreateTmpDir ("profile") }
});
diff --git a/main/tests/UserInterfaceTests/UITestBase.cs b/main/tests/UserInterfaceTests/UITestBase.cs
index f446223ff0..5ca0da478d 100644
--- a/main/tests/UserInterfaceTests/UITestBase.cs
+++ b/main/tests/UserInterfaceTests/UITestBase.cs
@@ -30,6 +30,9 @@ using MonoDevelop.Components.AutoTest;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
+using System.Linq;
+using MonoDevelop.Core.Logging;
+using MonoDevelop.Core;
namespace UserInterfaceTests
{
@@ -38,12 +41,13 @@ namespace UserInterfaceTests
{
string currentWorkingDirectory;
string testResultFolder;
- string memoryUsageFolder;
string currentTestResultFolder;
+ string currentTestResultScreenshotFolder;
- int testScreenshotIndex;
+ int testScreenshotIndex, reproStepIndex;
protected readonly List<string> FoldersToClean = new List<string> ();
+ protected FileLogger Logger;
public AutoTestClientSession Session {
get { return TestService.Session; }
@@ -55,7 +59,23 @@ namespace UserInterfaceTests
protected UITestBase (string mdBinPath)
{
- MonoDevelopBinPath = mdBinPath;
+ var installedXS = Environment.GetEnvironmentVariable ("USE_INSTALLED_XS");
+ if (!string.IsNullOrWhiteSpace(installedXS)) {
+ if (Platform.IsMac)
+ installedXS = Path.Combine(installedXS, "Contents/MacOS/XamarinStudio");
+ else if (Platform.IsWindows)
+ installedXS = Path.Combine(installedXS, @"bin\XamarinStudio.exe");
+ }
+
+ if (File.Exists (installedXS)) {
+ MonoDevelopBinPath = installedXS;
+ Console.WriteLine ("[UITEST] Using installed Xamarin Studio from this location: " + installedXS);
+ }
+ else {
+ Console.WriteLine ("[UITEST] Installed Xamarin Studio not found. Falling back to default behavior.");
+ MonoDevelopBinPath = mdBinPath;
+ }
+
currentWorkingDirectory = Directory.GetCurrentDirectory ();
}
@@ -63,58 +83,143 @@ namespace UserInterfaceTests
public virtual void FixtureSetup ()
{
testResultFolder = Path.Combine (currentWorkingDirectory, "TestResults");
- memoryUsageFolder = Path.Combine (testResultFolder, "MemoryUsage");
- if (!Directory.Exists (memoryUsageFolder))
- Directory.CreateDirectory (memoryUsageFolder);
}
[SetUp]
public virtual void SetUp ()
{
- SetupTestResultFolder (TestContext.CurrentContext.Test.FullName);
- var currentXSIdeLog = Path.Combine (currentTestResultFolder,string.Format ("{0}.Ide.log", TestContext.CurrentContext.Test.FullName) );
- Environment.SetEnvironmentVariable ("MONODEVELOP_LOG_FILE", currentXSIdeLog);
- Environment.SetEnvironmentVariable ("MONODEVELOP_FILE_LOG_LEVEL", "UpToInfo");
+ SetupTestResultFolder ();
+ SetupTestLogger ();
+ SetupScreenshotsFolder ();
+ SetupIdeLogFolder ();
var mdProfile = Util.CreateTmpDir ();
TestService.StartSession (MonoDevelopBinPath, mdProfile);
TestService.Session.DebugObject = new UITestDebug ();
FoldersToClean.Add (mdProfile);
+
+ Session.WaitForElement (IdeQuery.DefaultWorkbench);
+ TakeScreenShot ("Application-Started");
+ CloseIfXamarinUpdateOpen ();
+ TakeScreenShot ("Application-Ready");
}
[TearDown]
public virtual void Teardown ()
{
- File.WriteAllText (Path.Combine (memoryUsageFolder, TestContext.CurrentContext.Test.FullName),
- JsonConvert.SerializeObject (Session.MemoryStats, Formatting.Indented));
+ try {
+ bool isInconclusive = false;
+ var testStatus = TestContext.CurrentContext.Result.Status;
+ if (testStatus != TestStatus.Passed) {
+ try {
+ var updateOpened = Session.Query (IdeQuery.XamarinUpdate);
+ if (updateOpened != null && updateOpened.Any ())
+ isInconclusive = true;
+ TakeScreenShot (string.Format ("{0}-Test-Failed", TestContext.CurrentContext.Test.Name));
+ } catch (Exception e) {
+ Session.DebugObject.Debug ("Final Screenshot failed");
+ Session.DebugObject.Debug (e.ToString ());
+ }
+ }
+
+ File.WriteAllText (Path.Combine (currentTestResultFolder, "MemoryUsage.json"),
+ JsonConvert.SerializeObject (Session.MemoryStats, Formatting.Indented));
- Ide.CloseAll ();
- TestService.EndSession ();
+ Ide.CloseAll ();
+ TestService.EndSession ();
- OnCleanUp ();
- if (TestContext.CurrentContext.Result.Status == TestStatus.Passed) {
- if (Directory.Exists (currentTestResultFolder))
- Directory.Delete (currentTestResultFolder, true);
+ ValidateIdeLogMessages ();
+
+ OnCleanUp ();
+ if (testStatus == TestStatus.Passed) {
+ if (Directory.Exists (currentTestResultScreenshotFolder))
+ Directory.Delete (currentTestResultScreenshotFolder, true);
+ }
+
+ if (isInconclusive)
+ Assert.Inconclusive ("Xamarin Update is blocking the application focus");
+ } finally {
+ LoggingService.RemoveLogger (Logger.Name);
+ Logger.Dispose ();
}
}
- void SetupTestResultFolder (string testName)
+ static void ValidateIdeLogMessages ()
{
- testScreenshotIndex = 1;
- currentTestResultFolder = Path.Combine (testResultFolder, testName);
+ LogMessageValidator.Validate (Environment.GetEnvironmentVariable ("MONODEVELOP_LOG_FILE"));
+ }
+
+ protected void CloseIfXamarinUpdateOpen ()
+ {
+ try {
+ Session.WaitForElement (IdeQuery.XamarinUpdate, 10 * 1000);
+ TakeScreenShot ("Xamarin-Update-Opened");
+ Session.ClickElement (c => IdeQuery.XamarinUpdate (c).Children ().Button ().Text ("Close"));
+ }
+ catch (TimeoutException) {
+ TestService.Session.DebugObject.Debug ("Xamarin Update did not open");
+ }
+ }
+
+ void SetupTestResultFolder ()
+ {
+ currentTestResultFolder = Path.Combine (testResultFolder, TestContext.CurrentContext.Test.Name);
if (Directory.Exists (currentTestResultFolder))
Directory.Delete (currentTestResultFolder, true);
Directory.CreateDirectory (currentTestResultFolder);
}
- protected void TakeScreenShot (string stepName)
+ void SetupTestLogger ()
+ {
+ reproStepIndex = 0;
+ var currentTestLog = Path.Combine (currentTestResultFolder, string.Format ("{0}.Test.log.txt", TestContext.CurrentContext.Test.Name.ToPathSafeString ()));
+ Logger = new FileLogger (currentTestLog) {
+ Name = TestContext.CurrentContext.Test.Name,
+ EnabledLevel = EnabledLoggingLevel.All,
+ };
+ LoggingService.AddLogger (Logger);
+ }
+
+ void SetupScreenshotsFolder ()
{
- stepName = string.Format ("{0:D3}-{1}", testScreenshotIndex++, stepName);
- var screenshotPath = Path.Combine (currentTestResultFolder, stepName) + ".png";
+ testScreenshotIndex = 1;
+ currentTestResultScreenshotFolder = Path.Combine (currentTestResultFolder, "Screenshots");
+ if (Directory.Exists (currentTestResultScreenshotFolder))
+ Directory.Delete (currentTestResultScreenshotFolder, true);
+ Directory.CreateDirectory (currentTestResultScreenshotFolder);
+ }
+
+ void SetupIdeLogFolder ()
+ {
+ var currentXSIdeLog = Path.Combine (currentTestResultFolder, string.Format ("{0}.Ide.log", TestContext.CurrentContext.Test.Name.ToPathSafeString ()));
+ Environment.SetEnvironmentVariable ("MONODEVELOP_LOG_FILE", currentXSIdeLog);
+ Environment.SetEnvironmentVariable ("MONODEVELOP_FILE_LOG_LEVEL", "UpToInfo");
+ }
+
+ public void TakeScreenShot (string stepName)
+ {
+ stepName = string.Format ("{0:D3}-{1}", testScreenshotIndex++, stepName).ToPathSafeString ();
+ var screenshotPath = Path.Combine (currentTestResultScreenshotFolder, stepName) + ".png";
Session.TakeScreenshot (screenshotPath);
}
+ public void ReproStep (string stepDescription, params object[] info)
+ {
+ reproStepIndex++;
+ stepDescription = string.Format ("@Repro-Step-{0:D2}: {1}", reproStepIndex, stepDescription);
+ LoggingService.LogInfo (stepDescription);
+ foreach (var obj in info) {
+ if (obj != null)
+ LoggingService.LogInfo (string.Format("@Repro-Info-{0:D2}: {1}", reproStepIndex, obj.ToString ()));
+ }
+ }
+
+ public void ReproFailedStep (string expected, string actual, params object [] info)
+ {
+ ReproStep (string.Format ("Expected: {0}\nActual: {1}", expected, actual), info);
+ }
+
protected virtual void OnCleanUp ()
{
foreach (var folder in FoldersToClean) {
@@ -122,7 +227,9 @@ namespace UserInterfaceTests
if (folder != null && Directory.Exists (folder))
Directory.Delete (folder, true);
} catch (IOException e) {
- Console.WriteLine ("Cleanup failed\n" +e.ToString ());
+ TestService.Session.DebugObject.Debug ("Cleanup failed\n" +e);
+ } catch (UnauthorizedAccessException e) {
+ TestService.Session.DebugObject.Debug (string.Format ("Unable to clean directory: {0}\n", folder) + e);
}
}
}
@@ -133,6 +240,7 @@ namespace UserInterfaceTests
var dirObj = Session.GetGlobalValue ("MonoDevelop.Ide.IdeApp.ProjectOperations.CurrentSelectedSolution.RootFolder.BaseDirectory");
return dirObj != null ? dirObj.ToString () : null;
} catch (Exception) {
+ TestService.Session.DebugObject.Debug ("GetSolutionDirectory () returns null");
return null;
}
}
diff --git a/main/tests/UserInterfaceTests/UserInterfaceTests.csproj b/main/tests/UserInterfaceTests/UserInterfaceTests.csproj
index 42facba4c7..63d7d1963f 100644
--- a/main/tests/UserInterfaceTests/UserInterfaceTests.csproj
+++ b/main/tests/UserInterfaceTests/UserInterfaceTests.csproj
@@ -8,7 +8,7 @@
<ProjectGuid>{07F55155-51A8-4072-9F80-FA473666F086}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>UserInterfaceTests</RootNamespace>
- <AssemblyName>UserInterfaceTests</AssemblyName>
+ <AssemblyName>MonoDevelop.UITests</AssemblyName>
<TestRunnerCommand>..\..\build\bin\mdtool.exe</TestRunnerCommand>
<TestRunnerArgs>run-md-tests</TestRunnerArgs>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
@@ -30,6 +30,20 @@
<WarningLevel>4</WarningLevel>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugMac|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <Optimize>false</Optimize>
+ <OutputPath>..\..\build\tests</OutputPath>
+ <DefineConstants>DEBUG,MAC</DefineConstants>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseMac|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\..\build\tests</OutputPath>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
@@ -53,6 +67,7 @@
<Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
<Reference Include="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
<Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
+ <Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="UITestBase.cs" />
@@ -66,10 +81,8 @@
<Compile Include="TemplateTests\ASPNETTemplateTests.cs" />
<Compile Include="TemplateTests\DotNetTemplatesTest.cs" />
<Compile Include="TemplateTests\MiscTemplatesTest.cs" />
- <Compile Include="VersionControlTests\GitTests.cs" />
<Compile Include="VersionControlTests\VCSBase.cs" />
<Compile Include="VersionControlTests\SvnTests.cs" />
- <Compile Include="VersionControlTests\GitRepositoryConfigurationTests.cs" />
<Compile Include="DialogTests\NewProjectDialogTests.cs" />
<Compile Include="IdeQuery.cs" />
<Compile Include="Controllers\NewFileController.cs" />
@@ -77,6 +90,17 @@
<Compile Include="Controllers\SolutionExplorerController.cs" />
<Compile Include="Controllers\NuGetController.cs" />
<Compile Include="DialogTests\NuGetDialogTests.cs" />
+ <Compile Include="Exceptions\TemplateSelectionException.cs" />
+ <Compile Include="Exceptions\CreateProjectException.cs" />
+ <Compile Include="Workbench.cs" />
+ <Compile Include="VersionControlTests\Git\GitBase.cs" />
+ <Compile Include="VersionControlTests\Git\GitRepositoryConfigurationTests.cs" />
+ <Compile Include="VersionControlTests\Git\GitStashManagerTests.cs" />
+ <Compile Include="VersionControlTests\Git\GitTests.cs" />
+ <Compile Include="Controllers\NuGetOptions.cs" />
+ <Compile Include="Controllers\OptionsController.cs" />
+ <Compile Include="Exceptions\NuGetException.cs" />
+ <Compile Include="LogMessageValidator.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
@@ -107,10 +131,12 @@
<NuGet>$(SolutionDir)\external\nuget-binary\NuGet.exe</NuGet>
<NuGet Condition="$(OS)=='Unix'">mono $(NuGet)</NuGet>
</PropertyGroup>
- <Exec Command="$(NuGet) restore -SolutionDirectory $(SolutionDir)" />
+ <Exec Condition="Exists('$(SolutionDir)\..\.git')" Command="$(NuGet) restore -SolutionDirectory $(SolutionDir)" />
</Target>
<ItemGroup>
<Folder Include="DialogTests\" />
<Folder Include="Controllers\" />
+ <Folder Include="Exceptions\" />
+ <Folder Include="VersionControlTests\Git\" />
</ItemGroup>
-</Project> \ No newline at end of file
+</Project>
diff --git a/main/tests/UserInterfaceTests/Util.cs b/main/tests/UserInterfaceTests/Util.cs
index a983c16adb..8658e5f179 100644
--- a/main/tests/UserInterfaceTests/Util.cs
+++ b/main/tests/UserInterfaceTests/Util.cs
@@ -28,11 +28,29 @@ using System;
using System.IO;
using MonoDevelop.Core;
using System.Reflection;
+using System.Linq;
namespace UserInterfaceTests
{
public static class Util
{
+ public static void PrintData (this object data)
+ {
+ if (data != null)
+ TestService.Session.DebugObject.Debug (data.ToString ());
+ }
+
+ public static string ToPathSafeString (this string str, char replaceWith = '-')
+ {
+ var invalids = Path.GetInvalidFileNameChars ().Concat (Path.GetInvalidPathChars ()).Distinct ().ToArray ();
+ return new string (str.Select (c => invalids.Contains (c) ? replaceWith : c).ToArray ());
+ }
+
+ public static string ToBoldText (this string str)
+ {
+ return str != null ? string.Format ("<b>{0}</b>", str) : null;
+ }
+
public static FilePath CreateTmpDir (string hint = null)
{
var cwd = new FileInfo (Assembly.GetExecutingAssembly ().Location).DirectoryName;
@@ -57,5 +75,15 @@ namespace UserInterfaceTests
return Ide.EmptyAction;
}
}
+
+ public static Action<string> GetNonNullAction (Action<string> action)
+ {
+ return action ?? delegate { };
+ }
+
+ public static string StripBold (this string value)
+ {
+ return value != null ? value.Replace ("<b>", string.Empty).Replace ("</b>", string.Empty) : null;
+ }
}
}
diff --git a/main/tests/UserInterfaceTests/VersionControlTests/Git/GitBase.cs b/main/tests/UserInterfaceTests/VersionControlTests/Git/GitBase.cs
new file mode 100644
index 0000000000..293015c5f9
--- /dev/null
+++ b/main/tests/UserInterfaceTests/VersionControlTests/Git/GitBase.cs
@@ -0,0 +1,478 @@
+//
+// GitBase.cs
+//
+// Author:
+// Manish Sinha <manish.sinha@xamarin.com>
+//
+// Copyright (c) 2015 Xamarin Inc.
+//
+// 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 MonoDevelop.Components.AutoTest;
+using NUnit.Framework;
+
+namespace UserInterfaceTests
+{
+ public abstract class GitBase : VCSBase
+ {
+ static string notString = "not";
+
+ #region Git Repository Configuration
+
+ #region Remotes
+
+ Func<AppQuery, AppQuery> remoteTreeName = c => c.TreeView ().Marked ("treeRemotes").Model ("storeRemotes__Name");
+ Func<AppQuery, AppQuery> remoteTreeUrl = c => c.TreeView ().Marked ("treeRemotes").Model ("storeRemotes__Url");
+ Func<AppQuery, AppQuery> remoteTreeFullName = c => c.TreeView ().Marked ("treeRemotes").Model ("storeRemotes__FullName");
+
+ protected void AssertRemotesButtonSensitivity (bool editSensitivity, bool removeSensitivity, bool trackSensitivity, bool fetchSensitivity)
+ {
+ AssertButtonSensitivity ("Add", true);
+ AssertButtonSensitivity ("Edit", editSensitivity);
+ AssertButtonSensitivity ("Remove", removeSensitivity);
+ AssertButtonSensitivity ("Track in Local Branch", trackSensitivity);
+ AssertButtonSensitivity ("Fetch", fetchSensitivity);
+ }
+
+ protected void SelectRemote (string remoteName, string remoteUrl = null)
+ {
+ ReproStep (string.Format ("Select a remote named '{0}' {1}", remoteName,
+ remoteUrl != null ? string.Format (" and Remote URL '{0}'", remoteUrl) : string.Empty));
+ Session.WaitForElement (c => remoteTreeName (c).Contains (remoteName));
+
+ try {
+ Assert.IsTrue (Session.SelectElement (c => remoteTreeName (c).Contains (remoteName)));
+ } catch (AssertionException) {
+ ReproFailedStep (string.Format ("Remote Name '{0}' exists", remoteName), string.Format ("Remote Name '{0}' does not exists", remoteName));
+ throw;
+ }
+ if (remoteUrl != null) {
+ try {
+ Assert.IsTrue (Session.SelectElement (c => remoteTreeUrl (c).Contains (remoteUrl)));
+ } catch (AssertionException) {
+ ReproFailedStep (string.Format ("Remote URL '{0}' with Name '{1}' exists", remoteUrl, remoteName),
+ string.Format ("Remote URL '{0}' with Name '{1}' does not exist", remoteUrl, remoteName));
+ throw;
+ }
+ }
+ TakeScreenShot (string.Format ("{0}-Remote-Selected", remoteName));
+ }
+
+ protected void EditRemote (string newRemoteName, string remoteUrl, string remotePushUrl = null)
+ {
+ ReproStep ("Click on Edit");
+ AddEditRemote ("buttonEditRemote", newRemoteName, remoteUrl, remotePushUrl);
+ }
+
+ protected void AddRemote (string newRemoteName, string remoteUrl, string remotePushUrl = null)
+ {
+ ReproStep ("Click on Add");
+ AddEditRemote ("buttonAddRemote", newRemoteName, remoteUrl, remotePushUrl);
+ }
+
+ protected void FetchRemoteBranch (string remoteName)
+ {
+ SelectRemote (remoteName);
+
+ Assert.IsEmpty (Session.Query (c => remoteTreeFullName (c).Contains (remoteName+"/")));
+ Assert.IsTrue (Session.ClickElement (c => IdeQuery.GitConfigurationDialog (c).Children ().Button ().Text ("Fetch")));
+ TakeScreenShot ("Fetch-Remote");
+
+ SelectRemoteBranch (remoteName);
+ }
+
+ protected void SelectRemoteBranch (string remoteName, string remoteBranchName = null)
+ {
+ Session.ClickElement (c => remoteTreeName (c).Contains (remoteName));
+ Assert.IsNotEmpty (Session.Query (c => remoteTreeFullName (c).Contains (remoteName+"/"+remoteBranchName)));
+
+ var expected = string.Format ("Select the Remote with Name '{0}' and Remote Branch Name '{1}'", remoteName, remoteBranchName);
+ try {
+ ReproStep (expected);
+ Assert.IsTrue (Session.SelectElement (c => remoteTreeFullName (c).Contains (remoteName + "/" + remoteBranchName).Index (0)));
+ } catch (AssertionException) {
+ ReproFailedStep (expected, "Could not "+expected);
+ throw;
+ }
+ TakeScreenShot (string.Format ("{0}-Remote-Branch-Selected", remoteBranchName ?? "First"));
+ }
+
+ void AddEditRemote (string buttonName, string newRemoteName, string remoteUrl, string remotePushUrl)
+ {
+ Assert.IsNotEmpty (Session.Query (c => IdeQuery.GitConfigurationDialog (c).Children ().Button ().Marked (buttonName)));
+ Session.ClickElement (c => IdeQuery.GitConfigurationDialog (c).Children ().Button ().Marked (buttonName), false);
+ Session.WaitForElement (IdeQuery.EditRemoteDialog);
+
+ ReproStep (string.Format ("Enter Remote name as '{0}'", newRemoteName));
+ Func<AppQuery, AppQuery> EditRemoteDialogChildren = c => IdeQuery.EditRemoteDialog (c).Children ();
+ Assert.IsTrue (Session.EnterText (c => EditRemoteDialogChildren (c).Textfield ().Marked ("entryName"), newRemoteName));
+ Session.WaitForElement (c => EditRemoteDialogChildren (c).Textfield ().Marked ("entryName").Text (newRemoteName));
+
+ ReproStep (string.Format ("Enter Remote URL as '{0}'", remoteUrl));
+ Assert.IsTrue (Session.EnterText (c => EditRemoteDialogChildren (c).Textfield ().Marked ("entryUrl"), remoteUrl));
+ Session.WaitForElement (c => EditRemoteDialogChildren (c).Marked ("entryUrl").Text (remoteUrl));
+
+ ReproStep (string.Format ("Enter Remote Push URL as '{0}'", remotePushUrl ?? remoteUrl));
+ Assert.IsTrue (Session.EnterText (c => EditRemoteDialogChildren (c).Textfield ().Marked ("entryPushUrl"), remotePushUrl ?? remoteUrl));
+ Session.WaitForElement (c => EditRemoteDialogChildren (c).Textfield ().Marked ("entryPushUrl").Text (remotePushUrl ?? remoteUrl));
+ TakeScreenShot ("Remote-Details-Filled");
+
+ ReproStep ("Click on OK");
+ Assert.IsTrue (Session.ClickElement (c => EditRemoteDialogChildren (c).Button ().Marked ("buttonOk")));
+ Session.WaitForNoElement (IdeQuery.EditRemoteDialog);
+ Session.WaitForElement (IdeQuery.GitConfigurationDialog);
+ TakeScreenShot ("Remote-Edit-Dialog-Closed");
+ }
+
+ protected void DeleteRemote (string remoteName)
+ {
+ Session.WaitForElement (c => remoteTreeName (c).Contains (remoteName));
+ ReproStep ("Click on Remove");
+ Session.ClickElement (c => IdeQuery.GitConfigurationDialog(c).Children ().Button ().Text ("Remove"), false);
+ TakeScreenShot (string.Format ("Remove-Remote-{0}", remoteName));
+
+ ReproStep ("When prompted to confirm, click Delete");
+ Ide.ClickButtonAlertDialog ("Delete");
+ Session.WaitForElement (IdeQuery.GitConfigurationDialog);
+ }
+
+ #endregion
+
+ #region Tags
+
+ Func<AppQuery, AppQuery> tagTreeName = c => c.TreeView ().Marked ("listTags").Model ("storeTags__Name");
+
+ protected void AssertTagsButtonSensitivity (bool pushSensitivity, bool deleteSensitivity)
+ {
+ AssertButtonSensitivity ("New", true);
+ AssertButtonSensitivity ("Push", pushSensitivity);
+ AssertButtonSensitivity ("Delete", deleteSensitivity);
+ }
+
+ protected void SelectTag (string tagName)
+ {
+ WaitForElement (c => tagTreeName (c).Text (tagName),
+ string.Format ("Tag '{0}' should be available", tagName),
+ string.Format ("Tag '{0}' it not available", tagName));
+ try {
+ Assert.IsTrue (Session.SelectElement (c => tagTreeName (c).Text (tagName)), "Failed to select tag: " + tagName);
+ } catch (AssertionException) {
+ ReproFailedStep (string.Format ("Tag '{0}' should be selected", tagName),
+ string.Format ("Tag '{0}' cannot be selected", tagName));
+ throw;
+ }
+ TakeScreenShot (string.Format ("{0}-Tag-Selected", tagName));
+ }
+
+ protected void DeleteTag (string tagName)
+ {
+ SelectTag (tagName);
+ ReproStep ("Click Delete");
+ try {
+ Assert.IsTrue ((Session.ClickElement (c => IdeQuery.GitConfigurationDialog (c).Children ().Button ().Marked ("buttonRemoveTag"))));
+ } catch (AssertionException) {
+ ReproFailedStep (string.Format ("Tag '{0}' should be removed", tagName), string.Format ("Tag '{0}' could not be removed", tagName));
+ throw;
+ }
+ Session.WaitForNoElement (c => tagTreeName (c).Text (tagName));
+ }
+
+ protected void AddNewTag (string tagName, string tagMessage = null, string commitMsg = null)
+ {
+ ReproStep ("Click on New");
+ Session.ClickElement (c => IdeQuery.GitConfigurationDialog (c).Children ().Button ().Marked ("buttonAddTag"), false);
+
+ ReproStep ("Wait for 'Select a Revision' dialog to open");
+ try {
+ Session.WaitForElement (c => c.Window ().Marked ("Select a revision"));
+ } catch (AssertionException) {
+ ReproFailedStep ("'Select a Revision' dialog should open", "'Select a Revision' dialog did not open");
+ throw;
+ }
+
+ ReproStep ("Enter the Tag Name");
+ Session.EnterText (c => c.Window ().Marked ("Select a revision").Children ().Textfield ().Index (0), tagName);
+ Session.WaitForElement (c => c.Window ().Marked ("Select a revision").Children ().Textfield ().Index (0).Text (tagName));
+ TakeScreenShot ("Tag-Name-Entered");
+
+ if (!string.IsNullOrEmpty (tagMessage)) {
+ ReproStep ("Enter a Tag Message");
+ Session.EnterText (c => c.Window ().Marked ("Select a revision").Children ().Textfield ().Index (1), tagMessage);
+ Session.WaitForElement (c => c.Window ().Marked ("Select a revision").Children ().Textfield ().Index (1).Text (tagMessage));
+ TakeScreenShot ("Tag-Message-Entered");
+ }
+
+ Func<AppQuery, AppQuery> revisionsTreeView = c => c.Window ().Marked ("Select a revision").Children ().TreeView ().Index (0).Model ().Children ();
+ if (!string.IsNullOrEmpty (commitMsg)) {
+ ReproStep (string.Format ("Select the commit with message '{0}'", commitMsg));
+ Session.SelectElement (c => revisionsTreeView (c).Text (commitMsg));
+ } else {
+ ReproStep ("Select the first commit");
+ Session.SelectElement (c => revisionsTreeView (c).Index (0));
+ }
+ TakeScreenShot ("Commit-Message-Selected");
+
+ ReproStep ("Click OK");
+ Session.ClickElement (c => c.Window ().Marked ("Select a revision").Children ().Button ().Text ("Ok"));
+ try {
+ Session.WaitForElement (IdeQuery.GitConfigurationDialog);
+ TakeScreenShot ("Git-User-Not-Configured");
+ EnterGitUserConfig ("John Doe", "john.doe@example.com");
+ } catch (TimeoutException e) { }
+ Session.WaitForElement (c => IdeQuery.GitConfigurationDialog (c));
+ TakeScreenShot ("Ok-Clicked");
+ }
+
+ #endregion
+
+ #region Branches
+
+ Func<AppQuery, AppQuery> branchDisplayName = c => c.TreeView ().Marked ("listBranches").Model ("storeBranches__DisplayName");
+
+ protected void AssertBranchesButtonSensitivity (bool editSensitivity, bool deleteSensitivity, bool switchSensitivity)
+ {
+ AssertButtonSensitivity ("New", true);
+ AssertButtonSensitivity ("Edit", editSensitivity);
+ AssertButtonSensitivity ("Delete", deleteSensitivity);
+ AssertButtonSensitivity ("Switch to Branch", switchSensitivity);
+ }
+
+ protected void CreateNewBranch (string newBranchName)
+ {
+ ReproStep ("Click New");
+ CreateEditBranch ("buttonAddBranch", newBranchName);
+ }
+
+ protected void EditBranch (string oldBranchName, string newBranchName)
+ {
+ SelectBranch (oldBranchName);
+ ReproStep ("Click Edit");
+ CreateEditBranch ("buttonEditBranch", newBranchName);
+ }
+
+ protected void CreateEditBranch (string buttonName, string newBranchName)
+ {
+ Session.ClickElement (c => IdeQuery.GitConfigurationDialog(c).Children ().Button ().Marked (buttonName), false);
+
+ ReproStep ("Wait for Branch Properties dialog");
+ WaitForElement (IdeQuery.EditBranchDialog, "Branch Properties dialog opens", "Branch Properties dialog does not open");
+ TakeScreenShot ("Edit-Branch-Dialog-Opened");
+
+ EnterBranchName (newBranchName);
+ Session.WaitForElement (IdeQuery.GitConfigurationDialog);
+ TakeScreenShot ("Edit-Branch-Dialog-Opened-Closed");
+ }
+
+ protected void EnterBranchName (string newBranchName)
+ {
+ ReproStep ("Enter branch name");
+ Session.EnterText (c => IdeQuery.EditBranchDialog (c).Children ().Textfield ().Marked ("entryName"), newBranchName);
+ Session.WaitForElement (c => IdeQuery.EditBranchDialog (c).Children ().Textfield ().Marked ("entryName").Text (newBranchName));
+ TakeScreenShot ("Branch-Name-Entered");
+
+ ReproStep ("Click OK");
+ Assert.IsTrue (Session.ClickElement (c => IdeQuery.EditBranchDialog (c).Children ().Button ().Marked ("buttonOk")));
+ }
+
+ protected void SwitchToBranch (string branchName)
+ {
+ SelectBranch (branchName);
+ TakeScreenShot (string.Format ("{0}-Branch-Selected", branchName));
+
+ ReproStep ("Click on 'Switch to Branch'");
+ Session.ClickElement (c => IdeQuery.GitConfigurationDialog(c).Children ().Button ().Text ("Switch to Branch"), false);
+ CheckIfNameEmailNeeded ();
+ CheckIfUserConflict ();
+ ReproStep ("Check if the selected branch is bold");
+ try {
+ Assert.IsTrue (IsBranchSwitched (branchName));
+ } catch (AssertionException) {
+ ReproFailedStep ("The selected branch should be bold", "The selected branch is not bold");
+ throw;
+ }
+ TakeScreenShot (string.Format ("Switched-To-{0}", branchName));
+ }
+
+ protected void SwitchTab (string tabName)
+ {
+ ReproStep (string.Format ("Select the '{0}' tab", tabName));
+ try {
+ Assert.IsTrue (Session.SelectElement (c => IdeQuery.GitConfigurationDialog (c).Children ().Notebook ().Marked ("notebook1").Text (tabName)));
+ } catch (AssertionException) {
+ ReproFailedStep (string.Format ("Tab '{0}' is selected", tabName), string.Format ("Tab '{0}' is not selected", tabName));
+ throw;
+ }
+ TakeScreenShot (string.Format ("Tab-Changed-{0}", GenerateProjectName (tabName)));
+ }
+
+ protected void SelectBranch (string branchName)
+ {
+ ReproStep (string.Format ("Select the '{0}' branch", branchName));
+ try {
+ Assert.IsTrue (Session.SelectElement (c => branchDisplayName (c).Contains (branchName)));
+ } catch (AssertionException) {
+ ReproFailedStep (string.Format ("Branch '{0}' is selected", branchName), string.Format ("Branch '{0}' is not selected", branchName));
+ throw;
+ }
+ TakeScreenShot (string.Format ("Selected-Branch-{0}", branchName.ToPathSafeString ()));
+ }
+
+ protected void DeleteBranch (string branchName)
+ {
+ SelectBranch (branchName);
+ ReproStep ("Press Delete");
+ Session.ClickElement (c => IdeQuery.GitConfigurationDialog (c).Children ().Button ().Text ("Delete"), false);
+ TakeScreenShot (string.Format ("Delete-Branch-{0}", branchName));
+ ReproStep ("If prompted for confirmation, press Delete");
+ Ide.ClickButtonAlertDialog ("Delete");
+ Session.WaitForElement (IdeQuery.GitConfigurationDialog);
+ }
+
+ protected bool IsBranchSwitched (string branchName)
+ {
+ try {
+ WaitForElement (c => branchDisplayName (c).Text ("<b>" + branchName + "</b>"),
+ string.Format ("Branch '{0}' is checked out", branchName),
+ string.Format ("Branch '{0}' is not checked out", branchName));
+ return true;
+ } catch (TimeoutException) {
+ return false;
+ }
+ }
+
+ #endregion
+
+ protected void OpenRepositoryConfiguration (string selectTab = null)
+ {
+ ReproStep ("Click Version Control > Manage Branches and Remotes");
+ Session.ExecuteCommand (MonoDevelop.VersionControl.Git.Commands.ManageBranches);
+
+ WaitForElement (IdeQuery.GitConfigurationDialog,
+ "Git Repository Configuration Dialog should open",
+ "Git Repository Configuration Dialog did not open");
+ TakeScreenShot ("Repository-Configuration-Opened");
+
+ if (selectTab != null)
+ SwitchTab (selectTab);
+ }
+
+ protected void CloseRepositoryConfiguration ()
+ {
+ ReproStep ("Click on Close button of Git Repository Configuration Dialog");
+ Session.ClickElement (c => IdeQuery.GitConfigurationDialog(c).Children ().Button ().Marked ("buttonOk"));
+ TakeScreenShot ("Git-Repository-Configuration-Closed");
+ Session.WaitForNoElement (IdeQuery.GitConfigurationDialog);
+ }
+
+ protected void AssertButtonSensitivity (string buttonLabel, bool sensitivity)
+ {
+ var expected = string.Format ("{0} button is {1} enabled", buttonLabel, !sensitivity ? notString : string.Empty);
+ var actual = string.Format ("{0} button is {1} enabled", buttonLabel, sensitivity ? notString : string.Empty);
+ try {
+ Assert.IsNotEmpty (Session.Query (c => c.Button ().Text (buttonLabel).Sensitivity (sensitivity)), actual);
+ } catch (AssertionException) {
+ ReproFailedStep (expected, actual);
+ throw;
+ }
+ }
+
+ #endregion
+
+ #region Stash Manager
+
+ protected Func<AppQuery, AppQuery> StashEntries = c => c.Window ().Marked (
+ "Stash Manager").Children ().TreeView ().Marked ("list").Model ().Children ();
+
+ protected void OpenStashManager ()
+ {
+ ReproStep ("Click on Version Control > Manage Stashes");
+ Session.ExecuteCommand ("MonoDevelop.VersionControl.Git.Commands.ManageStashes");
+ WaitForElement (c => c.Window ().Marked ("Stash Manager"), "Stash Manager dialog should open", "Stash Manager dialog did not open");
+ TakeScreenShot ("StashManager-Opened");
+ }
+
+ protected void CloseStashManager ()
+ {
+ ReproStep ("On Stash Manager, click Close button");
+ Session.ClickElement (c => c.Window ().Marked ("Stash Manager").Children ().Text ("Close"));
+ Session.WaitForElement (IdeQuery.TextArea);
+ TakeScreenShot ("StashManager-Closed");
+ }
+
+ protected void SelectStashEntry (int index = 0)
+ {
+ ReproStep ("Select the stash entry #{0}", index+1);
+ WaitForElement (c => StashEntries (c).Index (index), "Select stash entry: "+index+1, "Could not select that stash entry");
+ Session.SelectElement (c => StashEntries (c).Index (index));
+ }
+
+ protected void RemoveStash (int index)
+ {
+ SelectStashEntry (index);
+ TakeScreenShot ("About-To-Click-Remove");
+ try {
+ ReproStep ("Click on Remove");
+ Assert.IsTrue (Session.ClickElement (c => c.Window ().Marked ("Stash Manager").Children ().Button ().Text ("Remove")));
+ } catch (AssertionException) {
+ ReproFailedStep ("Stash should be removed", "Stash failed to remove");
+ throw;
+ }
+ Session.WaitForElement (c => c.Window ().Marked ("Stash Manager"));
+ }
+
+ protected void ApplyAndRemoveStash (int index)
+ {
+ SelectStashEntry (index);
+ TakeScreenShot ("About-To-Click-Apply-and-Remove");
+ try {
+ ReproStep ("Click on 'Apply and Remove'");
+ Assert.IsTrue (Session.ClickElement (c => c.Window ().Marked ("Stash Manager").Children ().Button ().Text ("Apply and Remove")));
+ } catch (AssertionException) {
+ ReproFailedStep ("Stash should be applied and removed from the list", "Stash failed to applied and removed from the list");
+ throw;
+ }
+ }
+
+ protected void ApplyStash (int index)
+ {
+ SelectStashEntry (index);
+ TakeScreenShot ("About-To-Click-Apply");
+ try {
+ ReproStep ("Click on Apply");
+ Assert.IsTrue (Session.ClickElement (c => c.Window ().Marked ("Stash Manager").Children ().Button ().Text ("Apply")));
+ } catch (AssertionException) {
+ ReproFailedStep ("Stash should be applied", "Stash failed to apply");
+ throw;
+ }
+ }
+
+ protected void ComvertToBranch (int index, string branchName)
+ {
+ SelectStashEntry (index);
+ TakeScreenShot ("About-To-Click-Convert-To-Branch");
+ ReproStep ("Click on 'Convert to Branch'");
+ Session.ClickElement (c => c.Window ().Marked ("Stash Manager").Children ().Button ().Text ("Convert to Branch"), false);
+ EnterBranchName (branchName);
+ Ide.WaitForStatusMessage (new [] { "Stash successfully applied" });
+ }
+
+ #endregion
+ }
+}
+
diff --git a/main/tests/UserInterfaceTests/VersionControlTests/Git/GitRepositoryConfigurationTests.cs b/main/tests/UserInterfaceTests/VersionControlTests/Git/GitRepositoryConfigurationTests.cs
new file mode 100644
index 0000000000..1c5c9eb52a
--- /dev/null
+++ b/main/tests/UserInterfaceTests/VersionControlTests/Git/GitRepositoryConfigurationTests.cs
@@ -0,0 +1,356 @@
+//
+// GitRepositoryConfigurationTests.cs
+//
+// Author:
+// Manish Sinha <manish.sinha@xamarin.com>
+//
+// Copyright (c) 2015 Xamarin Inc.
+//
+// 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 NUnit.Framework;
+
+namespace UserInterfaceTests
+{
+ [TestFixture, Timeout(90000)]
+ [Category ("GitConfig")]
+ public class GitRepositoryConfigurationTests : GitBase
+ {
+ const string gtkSharpUrl = "https://github.com/mono/gtk-sharp.git";
+ const string monoHotdrawUrl = "https://github.com/mono/monocov.git";
+
+ #region Branch Tab
+
+ [Test]
+ [Description ("Check that Edit, Switch, Switch to Branch are enabled only when a branch is selected")]
+ public void CheckBranchButtonsSensitivity ()
+ {
+ TestClone (gtkSharpUrl);
+ Ide.WaitForSolutionCheckedOut ();
+
+ OpenRepositoryConfiguration ("Branches");
+
+ TakeScreenShot ("Asserting-Edit-Delete-Switch-Button-Disabled");
+ AssertBranchesButtonSensitivity (false, false, false);
+ SelectBranch ("<b>master</b>");
+ TakeScreenShot ("Asserting-Edit-Switch-Button-Enabled");
+ AssertBranchesButtonSensitivity (true, false, false);
+ CreateNewBranch ("new-branch");
+ SelectBranch ("new-branch");
+ TakeScreenShot ("Asserting-Edit-Delete-Switch-Button-Enabled");
+ AssertBranchesButtonSensitivity (true, true, true);
+
+ CloseRepositoryConfiguration ();
+ }
+
+ [Test]
+ [Description ("Create a New Branch")]
+ public void CreateNewBranchTest ()
+ {
+ TestClone (gtkSharpUrl);
+ Ide.WaitForSolutionCheckedOut ();
+
+ OpenRepositoryConfiguration ();
+ CreateNewBranch ("new-branch");
+ CloseRepositoryConfiguration ();
+ }
+
+ [Test]
+ [Description ("Create a New Branch and switch to it")]
+ public void GitSwitchBranchTest ()
+ {
+ TestClone (gtkSharpUrl);
+ Ide.WaitForSolutionCheckedOut ();
+
+ OpenRepositoryConfiguration ();
+ CreateNewBranch ("new-branch");
+ SwitchToBranch ("new-branch");
+ CloseRepositoryConfiguration ();
+ }
+
+ [Test]
+ [Description ("Create a New Branch, select it and edit the name and switch to it")]
+ public void GitEditBranchTest ()
+ {
+ TestClone (gtkSharpUrl);
+ Ide.WaitForSolutionCheckedOut ();
+
+ OpenRepositoryConfiguration ();
+ CreateNewBranch ("new-branch");
+ SelectBranch ("new-branch");
+ EditBranch ("new-branch", "new-new-branch");
+ SwitchToBranch ("new-new-branch");
+ CloseRepositoryConfiguration ();
+ }
+
+ [Test]
+ [Description ("Create a new branch, select it and delete it")]
+ public void GitDeleteBranchTest ()
+ {
+ TestClone (gtkSharpUrl);
+ Ide.WaitForSolutionCheckedOut ();
+
+ OpenRepositoryConfiguration ();
+ CreateNewBranch ("new-branch");
+ SelectBranch ("new-branch");
+ DeleteBranch ("new-branch");
+
+ CloseRepositoryConfiguration ();
+ }
+
+ #endregion
+
+ #region Tag
+
+ [Test]
+ [Description ("Check that Push and Delete button are enabled only when a tag is selected")]
+ public void CheckTagButtonsSensitivity ()
+ {
+ TestClone (gtkSharpUrl);
+ Ide.WaitForSolutionCheckedOut ();
+
+ OpenRepositoryConfiguration ("Tags");
+
+ TakeScreenShot ("Asserting-Push-Delete-Button-Disabled");
+ AssertTagsButtonSensitivity (false, false);
+ SelectTag ("1.0.10");
+ TakeScreenShot ("Asserting-Push-Delete-Button-Enabled");
+ AssertTagsButtonSensitivity (true, true);
+
+ CloseRepositoryConfiguration ();
+ }
+
+ [Test]
+ [Description ("Create a new tag with tag name, tag message and by selecting a specific commit message")]
+ public void AddTag ()
+ {
+ TestClone (gtkSharpUrl);
+ Ide.WaitForSolutionCheckedOut ();
+
+ OpenRepositoryConfiguration ("Tags");
+
+ AddNewTag ("bumped", "bumped tag", "build: Bump mono dependency to 3.2.8");
+ SelectTag ("bumped");
+ TakeScreenShot ("New-Tag-Selected");
+
+ CloseRepositoryConfiguration ();
+ }
+
+ [Test]
+ [Description ("Clone a repo, open Tag tab, select a tag by name and delete it")]
+ public void DeleteTag ()
+ {
+ TestClone (gtkSharpUrl);
+ Ide.WaitForSolutionCheckedOut ();
+
+ OpenRepositoryConfiguration ("Tags");
+ DeleteTag ("1.0.10");
+ CloseRepositoryConfiguration ();
+ }
+
+ #endregion
+
+ #region Remotes Tab
+
+ [Test]
+ [Description ("Check that Edit, Remove, Fetch button are enabled only when a remote is selected and 'Track in Local' only when a remote branch is selected")]
+ public void CheckRemoteButtonsSensitivity ()
+ {
+ TestClone (gtkSharpUrl);
+ Ide.WaitForSolutionCheckedOut ();
+
+ OpenRepositoryConfiguration ("Remote Sources");
+
+ TakeScreenShot ("Asserting-Edit-Remove-Track--Fetch-Button-Disabled");
+ AssertRemotesButtonSensitivity (false, false, false, false);
+ SelectRemote ("origin");
+ TakeScreenShot ("Asserting-Edit-Switch-Button-Enabled");
+ AssertRemotesButtonSensitivity (true, true, false, true);
+ SelectRemoteBranch ("origin", "master");
+ TakeScreenShot ("Asserting-Edit-Switch-Button-Track-Enabled");
+ AssertRemotesButtonSensitivity (true, true, true, true);
+
+ CloseRepositoryConfiguration ();
+ }
+
+ [Test]
+ [Description ("Clone a repo and select a remote")]
+ public void SelectRemoteTest ()
+ {
+ TestClone (gtkSharpUrl);
+ Ide.WaitForSolutionCheckedOut ();
+
+ OpenRepositoryConfiguration ("Remote Sources");
+ SelectRemote ("origin");
+ CloseRepositoryConfiguration ();
+ }
+
+ [Test]
+ [Description ("Clone a repo, add a new remote and select that added remote")]
+ public void AddGitRemoteTest ()
+ {
+ TestClone (gtkSharpUrl);
+ Ide.WaitForSolutionCheckedOut ();
+
+ const string newRemoteName = "second";
+ const string newRemoteUrl = monoHotdrawUrl;
+ OpenRepositoryConfiguration ("Remote Sources");
+ AddRemote (newRemoteName, newRemoteUrl);
+ SelectRemote (newRemoteName, newRemoteUrl);
+ CloseRepositoryConfiguration ();
+ }
+
+ [Test]
+ [Description ("Clone a repo, add a new remote, select it and delete it")]
+ public void DeleteGitRemoteTest ()
+ {
+ TestClone (gtkSharpUrl);
+ Ide.WaitForSolutionCheckedOut ();
+
+ const string newRemoteName = "second";
+ const string newRemoteUrl = monoHotdrawUrl;
+ OpenRepositoryConfiguration ("Remote Sources");
+ AddRemote (newRemoteName, newRemoteUrl);
+ SelectRemote (newRemoteName, newRemoteUrl);
+ DeleteRemote (newRemoteName);
+ CloseRepositoryConfiguration ();
+ }
+
+ [Test]
+ [Description ("Edit only Remote Name, don't edit URL or Push URL")]
+ public void EditGitRemoteNameTest ()
+ {
+ TestClone (gtkSharpUrl);
+ Ide.WaitForSolutionCheckedOut ();
+
+ OpenRepositoryConfiguration ("Remote Sources");
+
+ const string newRemoteName = "second";
+ const string newRemoteUrl = monoHotdrawUrl;
+ AddRemote (newRemoteName, newRemoteUrl);
+ SelectRemote (newRemoteName, newRemoteUrl);
+
+ const string updatedRemoteName = "second-origin";
+ const string updatedRemoteUrl = monoHotdrawUrl;
+ EditRemote (updatedRemoteName, updatedRemoteUrl, updatedRemoteUrl);
+ SelectRemote (updatedRemoteName, updatedRemoteUrl);
+ CloseRepositoryConfiguration ();
+ }
+
+ [Test]
+ [Description ("Edit only Remote Name and URL, don't edit Push URL")]
+ public void EditGitRemoteNameAndUrlTest ()
+ {
+ TestClone (gtkSharpUrl);
+ Ide.WaitForSolutionCheckedOut ();
+
+ OpenRepositoryConfiguration ("Remote Sources");
+
+ const string newRemoteName = "second";
+ const string newRemoteUrl = monoHotdrawUrl;
+ AddRemote (newRemoteName, newRemoteUrl);
+ SelectRemote (newRemoteName, newRemoteUrl);
+
+ const string updatedRemoteName = "second-origin";
+ const string updatedRemoteUrl = monoHotdrawUrl;
+ EditRemote (updatedRemoteName, updatedRemoteUrl, newRemoteUrl);
+ SelectRemote (updatedRemoteName, updatedRemoteUrl);
+ CloseRepositoryConfiguration ();
+ }
+
+ [Test]
+ [Description ("Edit only Remote Name and Push URL, don't edit URL")]
+ public void EditGitRemoteNameAndPushUrlTest ()
+ {
+ TestClone (gtkSharpUrl);
+ Ide.WaitForSolutionCheckedOut ();
+
+ OpenRepositoryConfiguration ("Remote Sources");
+
+ const string newRemoteName = "second";
+ const string newRemoteUrl = monoHotdrawUrl;
+ AddRemote (newRemoteName, newRemoteUrl);
+ SelectRemote (newRemoteName, newRemoteUrl);
+
+ const string updatedRemoteName = "second-origin";
+ const string updatedRemoteUrl = monoHotdrawUrl;
+ EditRemote (updatedRemoteName, updatedRemoteUrl, monoHotdrawUrl);
+ SelectRemote (updatedRemoteName, updatedRemoteUrl);
+ CloseRepositoryConfiguration ();
+ }
+
+ [Test]
+ [Description ("Edit only Remote URL and Push URL, don't edit Name")]
+ public void EditGitRemoteUrlTest ()
+ {
+ TestClone (gtkSharpUrl);
+ Ide.WaitForSolutionCheckedOut ();
+
+ OpenRepositoryConfiguration ("Remote Sources");
+
+ const string newRemoteName = "second";
+ const string newRemoteUrl = monoHotdrawUrl;
+ AddRemote (newRemoteName, newRemoteUrl);
+ SelectRemote (newRemoteName, newRemoteUrl);
+
+ const string updatedRemoteUrl = monoHotdrawUrl;
+ EditRemote (newRemoteName, updatedRemoteUrl, updatedRemoteUrl);
+ SelectRemote (newRemoteName, updatedRemoteUrl);
+ CloseRepositoryConfiguration ();
+ }
+
+ [Test]
+ [Description ("Clone a repo, add a new remote and fetch the remote branches for that remote")]
+ public void FetchRemoteBranches ()
+ {
+ TestClone (gtkSharpUrl);
+ Ide.WaitForSolutionCheckedOut ();
+
+ const string newRemoteName = "second";
+ const string newRemoteUrl = monoHotdrawUrl;
+ OpenRepositoryConfiguration ("Remote Sources");
+ AddRemote (newRemoteName, newRemoteUrl);
+ FetchRemoteBranch (newRemoteName);
+ CloseRepositoryConfiguration ();
+ }
+
+ [Test]
+ [Description ("Clone a repo, add a new remote, fetch the remote branch, chose a branch and track it in local. Select that branch in Branches tab")]
+ public void TrackRemoteBranchInLocalTest()
+ {
+ TestClone (gtkSharpUrl);
+ Ide.WaitForSolutionCheckedOut ();
+
+ const string newRemoteName = "second";
+ const string newRemoteUrl = monoHotdrawUrl;
+ OpenRepositoryConfiguration ("Remote Sources");
+ AddRemote (newRemoteName, newRemoteUrl);
+ FetchRemoteBranch (newRemoteName);
+ const string localBranch = "local-branch-random-uitest";
+ CreateEditBranch ("buttonTrackRemote", localBranch);
+ SwitchTab ("Branches");
+ SelectBranch (localBranch);
+ CloseRepositoryConfiguration ();
+ }
+
+ #endregion
+ }
+}
+
diff --git a/main/tests/UserInterfaceTests/VersionControlTests/Git/GitStashManagerTests.cs b/main/tests/UserInterfaceTests/VersionControlTests/Git/GitStashManagerTests.cs
new file mode 100644
index 0000000000..71736ae25e
--- /dev/null
+++ b/main/tests/UserInterfaceTests/VersionControlTests/Git/GitStashManagerTests.cs
@@ -0,0 +1,119 @@
+//
+// GitStashManagerTests.cs
+//
+// Author:
+// Manish Sinha <manish.sinha@xamarin.com>
+//
+// Copyright (c) 2015 Xamarin Inc.
+//
+// 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 NUnit.Framework;
+using System;
+using MonoDevelop.Ide.Commands;
+using MonoDevelop.Components.AutoTest;
+
+namespace UserInterfaceTests
+{
+ [TestFixture, Timeout(60000)]
+ [Category ("Git")]
+ [Category ("StashManager")]
+ public class GitStashManagerTests : GitBase
+ {
+ [Test]
+ [Description ("Create a project with git, commit changes. Make changes and stash. Remove stash from Stash Manager")]
+ public void GitRemoveStashTest ()
+ {
+ CreateProjectAndCommitAndStash ();
+
+ OpenStashManager ();
+ RemoveStash (0);
+ Assert.IsEmpty (Session.Query (StashEntries));
+ CloseStashManager ();
+ }
+
+ [Test]
+ [Description ("Create a project with git, commit changes. Make changes and stash. Apply and Remove stash from Stash Manager")]
+ public void GitApplyAndRemoveStashTest ()
+ {
+ CreateProjectAndCommitAndStash ();
+
+ OpenStashManager ();
+ ApplyAndRemoveStash (0);
+
+ Session.WaitForElement (IdeQuery.TextArea);
+ TakeScreenShot ("Stash-Applied");
+ OpenStashManager ();
+
+ TakeScreenShot ("Asserting-if-Not-Stash-Present");
+ Session.WaitForNoElement (StashEntries);
+ CloseStashManager ();
+ }
+
+ [Test]
+ [Description ("Create a project with git, commit changes. Make changes and stash. Apply stash from Stash Manager")]
+ public void GitApplyStashTest ()
+ {
+ CreateProjectAndCommitAndStash ();
+
+ OpenStashManager ();
+ ApplyStash (0);
+ OpenStashManager ();
+
+ TakeScreenShot ("Asserting-if-Stash-Still-Present");
+ Assert.IsNotEmpty (Session.Query (StashEntries));
+ CloseStashManager ();
+ }
+
+ [Test]
+ [Description ("Create a project with git, commit changes. Make changes and stash. Convert stash to branch from Stash Manager")]
+ public void GitStashConvertToBranchTest ()
+ {
+ CreateProjectAndCommitAndStash ();
+
+ var branchName = "sample-branch";
+ OpenStashManager ();
+ ComvertToBranch (0, branchName);
+ OpenStashManager ();
+ TakeScreenShot ("Asserting-if-Stash-Still-Present");
+ Assert.IsEmpty (Session.Query (StashEntries));
+ CloseStashManager ();
+
+ OpenRepositoryConfiguration ("Branches");
+ IsBranchSwitched (branchName);
+ CloseRepositoryConfiguration ();
+ }
+
+ void CreateProjectAndCommitAndStash ()
+ {
+ var templateOptions = new TemplateSelectionOptions {
+ CategoryRoot = OtherCategoryRoot,
+ Category = ".NET",
+ TemplateKindRoot = GeneralKindRoot,
+ TemplateKind = "Console Project"
+ };
+ GitCreateAndCommit (templateOptions, "First commit");
+ var changeDescription = MakeSomeChangesAndSaveAll ("Program.cs");
+ TestGitStash (changeDescription);
+ Session.WaitForElement (IdeQuery.TextArea, 20000);
+ TakeScreenShot ("After-Stash");
+ }
+ }
+}
+
diff --git a/main/tests/UserInterfaceTests/VersionControlTests/GitTests.cs b/main/tests/UserInterfaceTests/VersionControlTests/Git/GitTests.cs
index 471b8a94ff..2bf26bcb52 100644
--- a/main/tests/UserInterfaceTests/VersionControlTests/GitTests.cs
+++ b/main/tests/UserInterfaceTests/VersionControlTests/Git/GitTests.cs
@@ -30,20 +30,22 @@ using NUnit.Framework;
namespace UserInterfaceTests
{
- [TestFixture]
+ [TestFixture, Timeout(60000)]
[Category ("Git")]
+ [Category ("GitBase")]
public class GitTests : VCSBase
{
- [Test]
- [TestCase ("git@github.com:mono/jurassic.git", TestName = "TestGitSSHClone")]
- [TestCase ("https://github.com/mono/jurassic.git", TestName = "TestGitHTTPSClone")]
+ [Test, Timeout(120000), Category("Smoke")]
+ [TestCase ("git@github.com:mono/gtk-sharp.git", TestName = "TestGitSSHClone", Description = "Clone Git repo over SSH")]
+ [TestCase ("https://github.com/mono/gtk-sharp.git", TestName = "TestGitHTTPSClone", Description = "Clone Git repo over HTTPS")]
public void TestGitClone (string url)
{
TestClone (url);
- Ide.WaitForSolutionCheckedOut ();
+ Ide.WaitForIdeIdle ();
}
- [Test]
+ [Test, Category("Smoke")]
+ [Description ("Create a new project with Git and commit the changes")]
public void TestCommit ()
{
var templateOptions = new TemplateSelectionOptions {
@@ -52,15 +54,11 @@ namespace UserInterfaceTests
TemplateKindRoot = GeneralKindRoot,
TemplateKind = "Console Project"
};
- CreateProject (templateOptions,
- new ProjectDetails (templateOptions),
- new GitOptions { UseGit = true, UseGitIgnore = true});
-
- Session.WaitForElement (IdeQuery.TextArea);
- TestCommit ("First commit");
+ GitCreateAndCommit (templateOptions, "First commit");
}
[Test]
+ [Description ("Create a new project and try to stash without any changes, it should not be allowed")]
public void TestNoChangesStashOperation ()
{
var templateOptions = new TemplateSelectionOptions {
@@ -81,6 +79,7 @@ namespace UserInterfaceTests
}
[Test]
+ [Description ("Create a new project and try to stash without HEAD commit, it should not be allowed")]
public void TestStashWithoutHeadCommit ()
{
var templateOptions = new TemplateSelectionOptions {
@@ -98,7 +97,8 @@ namespace UserInterfaceTests
TakeScreenShot ("Stash-Window-Doesnt-Show");
}
- [Test]
+ [Test, Category("Smoke")]
+ [Description ("Create a new project, make a commit, make changes. Stash and Unstash successfully")]
public void TestStashAndUnstashSuccessful ()
{
var templateOptions = new TemplateSelectionOptions {
@@ -107,23 +107,10 @@ namespace UserInterfaceTests
TemplateKindRoot = GeneralKindRoot,
TemplateKind = "Console Project"
};
- CreateProject (templateOptions,
- new ProjectDetails (templateOptions),
- new GitOptions { UseGit = true, UseGitIgnore = true });
-
- Session.WaitForElement (IdeQuery.TextArea);
- TestCommit ("First commit");
-
- Session.ExecuteCommand (FileCommands.CloseFile);
- Session.WaitForElement (IdeQuery.TextArea);
-
- Session.ExecuteCommand (TextEditorCommands.InsertNewLine);
- TakeScreenShot ("Inserted-Newline-Marked-Dirty");
- Session.ExecuteCommand (FileCommands.SaveAll);
- TakeScreenShot ("Inserted-Newline-SaveAll-Called");
-
- TestGitStash ("Entered new blank line");
+ GitCreateAndCommit (templateOptions, "First commit");
+ var changeDescription = MakeSomeChangesAndSaveAll ("Program.cs");
+ TestGitStash (changeDescription);
Session.WaitForElement (IdeQuery.TextArea);
TakeScreenShot ("After-Stash");
diff --git a/main/tests/UserInterfaceTests/VersionControlTests/GitRepositoryConfigurationTests.cs b/main/tests/UserInterfaceTests/VersionControlTests/GitRepositoryConfigurationTests.cs
deleted file mode 100644
index 166f0ac4ec..0000000000
--- a/main/tests/UserInterfaceTests/VersionControlTests/GitRepositoryConfigurationTests.cs
+++ /dev/null
@@ -1,310 +0,0 @@
-//
-// GitRepositoryConfigurationTests.cs
-//
-// Author:
-// Manish Sinha <manish.sinha@xamarin.com>
-//
-// Copyright (c) 2015 Xamarin Inc.
-//
-// 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 NUnit.Framework;
-using System;
-using MonoDevelop.Ide.Commands;
-using MonoDevelop.Components.AutoTest;
-
-namespace UserInterfaceTests
-{
- [TestFixture]
- [Category ("GitConfig")]
- public class GitRepositoryConfigurationTests : GitRepositoryConfigurationBase
- {
- #region Branch Tab
-
- [Test]
- public void CreateNewBranchTest ()
- {
- TestClone ("git@github.com:mono/jurassic.git");
- Ide.WaitForSolutionCheckedOut ();
-
- OpenRepositoryConfiguration ();
- CreateNewBranch ("new-branch");
- CloseRepositoryConfiguration ();
- }
-
- [Test]
- public void GitSwitchBranchTest ()
- {
- TestClone ("git@github.com:mono/jurassic.git");
- Ide.WaitForSolutionCheckedOut ();
-
- OpenRepositoryConfiguration ();
- CreateNewBranch ("new-branch");
- SwitchToBranch ("new-branch");
- CloseRepositoryConfiguration ();
- }
-
- [Test]
- public void GitEditBranchTest ()
- {
- TestClone ("git@github.com:mono/jurassic.git");
- Ide.WaitForSolutionCheckedOut ();
-
- OpenRepositoryConfiguration ();
- CreateNewBranch ("new-branch");
- SelectBranch ("new-branch");
- EditBranch ("new-branch", "new-new-branch");
- SwitchToBranch ("new-new-branch");
- CloseRepositoryConfiguration ();
- }
-
- #endregion
-
- #region Remotes Tab
-
- [Test]
- public void SelectRemoteTest ()
- {
- TestClone ("git@github.com:mono/jurassic.git");
- Ide.WaitForSolutionCheckedOut ();
-
- OpenRepositoryConfiguration ("Remote Sources");
- SelectRemote ("origin");
- CloseRepositoryConfiguration ();
- }
-
- [Test]
- public void AddGitRemoteTest ()
- {
- TestClone ("git@github.com:mono/jurassic.git");
- Ide.WaitForSolutionCheckedOut ();
-
- const string newRemoteName = "second";
- const string newRemoteUrl = "git@github.com:mono/monohotdraw.git";
- OpenRepositoryConfiguration ("Remote Sources");
- AddRemote (newRemoteName, newRemoteUrl);
- SelectRemote (newRemoteName, newRemoteUrl);
- CloseRepositoryConfiguration ();
- }
-
- [Test]
- [Ignore ("When OK is clicked on EditRemoteDialog, it doesn't update the list")]
- public void EditGitRemoteTest ()
- {
- TestClone ("git@github.com:mono/jurassic.git");
- Ide.WaitForSolutionCheckedOut ();
-
- OpenRepositoryConfiguration ("Remote Sources");
-
- const string newRemoteName = "second";
- const string newRemoteUrl = "git@github.com:mono/monohotdraw.git";
- AddRemote (newRemoteName, newRemoteUrl);
- SelectRemote (newRemoteName, newRemoteUrl);
-
- const string updatedRemoteName = "second-origin";
- const string updatedRemoteUrl = "git@github.com:mono/monohotdraw.git";
- EditRemote (updatedRemoteName, updatedRemoteUrl, "git@github.com:mono/monohotdraw-push.git");
- SelectRemote (updatedRemoteName, updatedRemoteUrl);
- CloseRepositoryConfiguration ();
- }
-
- [Test]
- public void FetchRemoteBranches ()
- {
- TestClone ("git@github.com:mono/jurassic.git");
- Ide.WaitForSolutionCheckedOut ();
-
- const string newRemoteName = "second";
- const string newRemoteUrl = "git@github.com:mono/monohotdraw.git";
- OpenRepositoryConfiguration ("Remote Sources");
- AddRemote (newRemoteName, newRemoteUrl);
- FetchRemoteBranch (newRemoteName);
- CloseRepositoryConfiguration ();
- }
-
- [Test]
- public void TrackRemoteBranchInLocalTest()
- {
- TestClone ("git@github.com:mono/jurassic.git");
- Ide.WaitForSolutionCheckedOut ();
-
- const string newRemoteName = "second";
- const string newRemoteUrl = "git@github.com:mono/monohotdraw.git";
- OpenRepositoryConfiguration ("Remote Sources");
- AddRemote (newRemoteName, newRemoteUrl);
- FetchRemoteBranch (newRemoteName);
- const string localBranch = "local-branch-random-uitest";
- CreateEditBranch ("buttonTrackRemote", localBranch);
- SwitchTab ("Branches");
- SelectBranch (localBranch);
- CloseRepositoryConfiguration ();
- }
-
- #endregion
- }
-
- public abstract class GitRepositoryConfigurationBase : VCSBase
- {
- #region Remotes
-
- Func<AppQuery, AppQuery> remoteTreeName = c => c.TreeView ().Marked ("treeRemotes").Model ("storeRemotes__Name");
- Func<AppQuery, AppQuery> remoteTreeUrl = c => c.TreeView ().Marked ("treeRemotes").Model ("storeRemotes__Url");
- Func<AppQuery, AppQuery> remoteTreeFullName = c => c.TreeView ().Marked ("treeRemotes").Model ("storeRemotes__FullName");
-
- protected void SelectRemote (string remoteName, string remoteUrl = null)
- {
- Session.WaitForElement (c => remoteTreeName (c).Contains (remoteName));
- Assert.IsTrue (Session.SelectElement (c => remoteTreeName (c).Contains (remoteName)));
- if (remoteUrl != null) {
- Assert.IsTrue (Session.SelectElement (c => remoteTreeUrl (c).Contains (remoteUrl)));
- }
- TakeScreenShot (string.Format ("{0}-Remote-Selected", remoteName));
- }
-
- protected void EditRemote (string newRemoteName, string remoteUrl, string remotePushUrl = null)
- {
- AddEditRemote ("buttonEditRemote", newRemoteName, remoteUrl, remotePushUrl);
- }
-
- protected void AddRemote (string newRemoteName, string remoteUrl, string remotePushUrl = null)
- {
- AddEditRemote ("buttonAddRemote", newRemoteName, remoteUrl, remotePushUrl);
- }
-
- protected void FetchRemoteBranch (string remoteName)
- {
- SelectRemote (remoteName);
-
- Assert.IsEmpty (Session.Query (c => remoteTreeFullName (c).Contains (remoteName+"/")));
- Assert.IsTrue (Session.ClickElement (c => IdeQuery.GitConfigurationDialog (c).Children ().Button ().Marked ("buttonFetch")));
- TakeScreenShot ("Fetch-Remote");
-
- Session.ClickElement (c => remoteTreeName (c).Contains (remoteName));
- Assert.IsNotEmpty (Session.Query (c => remoteTreeFullName (c).Contains (remoteName+"/")));
- Assert.IsTrue (Session.SelectElement (c => remoteTreeFullName (c).Contains (remoteName+"/").Index (0)));
- TakeScreenShot ("First-Remote-Branch-Selected");
- }
-
- void AddEditRemote (string buttonName, string newRemoteName, string remoteUrl, string remotePushUrl)
- {
- Assert.IsNotEmpty (Session.Query (c => IdeQuery.GitConfigurationDialog (c).Children ().Button ().Marked (buttonName)));
- Session.ClickElement (c => IdeQuery.GitConfigurationDialog (c).Children ().Button ().Marked (buttonName), false);
- Session.WaitForElement (IdeQuery.EditRemoteDialog);
-
- Func<AppQuery, AppQuery> EditRemoteDialogChildren = c => IdeQuery.EditRemoteDialog (c).Children ();
- Assert.IsTrue (Session.EnterText (c => EditRemoteDialogChildren (c).Textfield ().Marked ("entryName"), newRemoteName));
- Session.WaitForElement (c => EditRemoteDialogChildren (c).Textfield ().Marked ("entryName").Text (newRemoteName));
-
- Assert.IsTrue (Session.EnterText (c => EditRemoteDialogChildren (c).Textfield ().Marked ("entryUrl"), remoteUrl));
- Session.WaitForElement (c => EditRemoteDialogChildren (c).Marked ("entryUrl").Text (remoteUrl));
-
- Assert.IsTrue (Session.EnterText (c => EditRemoteDialogChildren (c).Textfield ().Marked ("entryPushUrl"), remotePushUrl ?? remoteUrl));
- Session.WaitForElement (c => EditRemoteDialogChildren (c).Textfield ().Marked ("entryPushUrl").Text (remotePushUrl ?? remoteUrl));
- TakeScreenShot ("Remote-Details-Filled");
-
- Assert.IsTrue (Session.ClickElement (c => EditRemoteDialogChildren (c).Button ().Marked ("buttonOk")));
- Session.WaitForNoElement (IdeQuery.EditRemoteDialog);
- Session.WaitForElement (IdeQuery.GitConfigurationDialog);
- TakeScreenShot ("Remote-Edit-Dialog-Closed");
- }
-
- #endregion
-
- #region Branches
-
- Func<AppQuery, AppQuery> branchDisplayName = c => c.TreeView ().Marked ("listBranches").Model ("storeBranches__DisplayName");
-
- protected void CreateNewBranch (string newBranchName)
- {
- CreateEditBranch ("buttonAddBranch", newBranchName);
- }
-
- protected void EditBranch (string oldBranchName, string newBranchName)
- {
- SelectBranch (oldBranchName);
- CreateEditBranch ("buttonEditBranch", newBranchName);
- }
-
- protected void CreateEditBranch (string buttonName, string newBranchName)
- {
- Session.ClickElement (c => IdeQuery.GitConfigurationDialog(c).Children ().Button ().Marked (buttonName), false);
- Session.WaitForElement (IdeQuery.EditBranchDialog);
- TakeScreenShot ("Edit-Branch-Dialog-Opened");
-
- Session.EnterText (c => IdeQuery.EditBranchDialog (c).Children ().Textfield ().Marked ("entryName"), newBranchName);
- Session.WaitForElement (c => IdeQuery.EditBranchDialog (c).Children ().Textfield ().Marked ("entryName").Text (newBranchName));
- TakeScreenShot ("Branch-Name-Entered");
-
- Assert.IsTrue (Session.ClickElement (c => IdeQuery.EditBranchDialog (c).Children ().Button ().Marked ("buttonOk")));
- Session.WaitForElement (IdeQuery.GitConfigurationDialog);
- TakeScreenShot ("Edit-Branch-Dialog-Opened-Closed");
- }
-
- protected void SwitchToBranch (string branchName)
- {
- SelectBranch (branchName);
- TakeScreenShot (string.Format ("{0}-Branch-Selected", branchName));
- Session.ClickElement (c => IdeQuery.GitConfigurationDialog(c).Children ().Button ().Marked ("buttonSetDefaultBranch"), false);
-
- try {
- Session.WaitForElement (IdeQuery.GitConfigurationDialog);
- TakeScreenShot ("Git-User-Not-Configured");
- EnterGitUserConfig ("John Doe", "john.doe@example.com");
- } catch (TimeoutException e) { }
-
- Assert.IsTrue (IsBranchSwitched (branchName));
- TakeScreenShot (string.Format ("Switched-To-{0}", branchName));
- }
-
- protected void SwitchTab (string tabName)
- {
- Assert.IsTrue (Session.SelectElement (c => IdeQuery.GitConfigurationDialog(c).Children ().Notebook ().Marked ("notebook1").Text (tabName)));
- TakeScreenShot (string.Format ("Tab-Changed-{0}", GenerateProjectName (tabName)));
- }
-
- protected void SelectBranch (string branchName)
- {
- Assert.IsTrue (Session.SelectElement (c => branchDisplayName (c).Contains (branchName)));
- TakeScreenShot (string.Format ("Selected-Branch-{0}", branchName));
- }
-
- protected bool IsBranchSwitched (string branchName)
- {
- return Session.SelectElement (c => branchDisplayName (c).Text ("<b>" + branchName + "</b>"));
- }
-
- #endregion
-
- protected void OpenRepositoryConfiguration (string selectTab = null)
- {
- Session.ExecuteCommand (MonoDevelop.VersionControl.Git.Commands.ManageBranches);
- Session.WaitForElement (IdeQuery.GitConfigurationDialog);
- TakeScreenShot ("Repository-Configuration-Opened");
- if (selectTab != null)
- SwitchTab (selectTab);
- }
-
- protected void CloseRepositoryConfiguration ()
- {
- Session.ClickElement (c => IdeQuery.GitConfigurationDialog(c).Children ().Button ().Marked ("buttonOk"));
- Session.WaitForNoElement (IdeQuery.GitConfigurationDialog);
- }
- }
-}
-
diff --git a/main/tests/UserInterfaceTests/VersionControlTests/VCSBase.cs b/main/tests/UserInterfaceTests/VersionControlTests/VCSBase.cs
index cf599626fd..e439d46580 100644
--- a/main/tests/UserInterfaceTests/VersionControlTests/VCSBase.cs
+++ b/main/tests/UserInterfaceTests/VersionControlTests/VCSBase.cs
@@ -26,7 +26,7 @@
using System;
using NUnit.Framework;
-using MonoDevelop.Components.AutoTest;
+using MonoDevelop.Ide.Commands;
namespace UserInterfaceTests
{
@@ -41,18 +41,34 @@ namespace UserInterfaceTests
protected string CheckoutOrClone (string repoUrl, string cloneToLocation = null, VersionControlType cvsType = VersionControlType.Git, int cloneTimeoutSecs = 180)
{
cloneToLocation = cloneToLocation ?? Util.CreateTmpDir ("clone");
+ ReproStep ("Click on Version Control > Checkout from Menu Bar");
Session.ExecuteCommand (MonoDevelop.VersionControl.Commands.Checkout);
- Session.WaitForElement (c => c.Window ().Marked ("MonoDevelop.VersionControl.Dialogs.SelectRepositoryDialog"));
+
+ WaitForElement (c => c.Window ().Marked ("MonoDevelop.VersionControl.Dialogs.SelectRepositoryDialog"),
+ "Select Repository window should open",
+ "Select Reprository window did not open");
TakeScreenShot ("Checkout-Window-Ready");
+
+ ReproStep (string.Format ("Select Type to '{0}'", cvsType));
Assert.IsTrue (Session.SelectElement (c => c.Marked ("repCombo").Model ().Text (cvsType.ToString ())));
+
+ ReproStep (string.Format ("Enter URL as '{0}'", repoUrl));
Assert.IsTrue (Session.EnterText (c => c.Textfield ().Marked ("repositoryUrlEntry"), repoUrl));
+
Assert.IsTrue (Session.EnterText (c => c.Textfield ().Marked ("entryFolder"), cloneToLocation));
Session.WaitForElement (c => c.Textfield ().Marked ("entryFolder").Text (cloneToLocation));
+
TakeScreenShot ("Before-Clicking-OK");
+ ReproStep ("Click OK");
Assert.IsTrue (Session.ClickElement (c => c.Window ().Marked ("MonoDevelop.VersionControl.Dialogs.SelectRepositoryDialog").Children ().Button ().Marked ("buttonOk")));
+
Session.WaitForElement (c => c.Window ().Marked ("MonoDevelop.Ide.Gui.Dialogs.ProgressDialog"), 15000);
TakeScreenShot ("CheckoutClone-In-Progress");
- Session.WaitForNoElement (c => c.Window ().Marked ("MonoDevelop.Ide.Gui.Dialogs.ProgressDialog"), cloneTimeoutSecs * 1000);
+ ReproStep ("Wait for Clone to Finish");
+ WaitForElement (c => c.Window ().Marked ("MonoDevelop.Ide.Gui.Dialogs.ProgressDialog"),
+ string.Format ("Clone should finish within {0} seconds", cloneTimeoutSecs),
+ string.Format ("Clone failed to finish within {0} seconds", cloneTimeoutSecs),
+ cloneTimeoutSecs * 1000);
return cloneToLocation;
}
@@ -65,38 +81,103 @@ namespace UserInterfaceTests
protected void TestGitStash (string stashMsg, int timeoutStashSecs = 10)
{
+ ReproStep ("Click on Version Control > Stash");
Session.ExecuteCommand (MonoDevelop.VersionControl.Git.Commands.Stash);
- Session.WaitForElement (c => c.Window ().Marked ("MonoDevelop.VersionControl.Git.NewStashDialog"));
+
+ WaitForElement (c => c.Window ().Marked ("MonoDevelop.VersionControl.Git.NewStashDialog"), "Stash Dialog should open", "Stash Dialog did not open");
TakeScreenShot ("Stash-Dialog-Opened");
+
+ ReproStep ("Enter a stash message");
Session.EnterText (c => c.Window ().Marked ("MonoDevelop.VersionControl.Git.NewStashDialog").Children ().Textfield ().Marked ("entryComment"), stashMsg);
Session.WaitForElement (c => c.Window ().Marked ("MonoDevelop.VersionControl.Git.NewStashDialog").Children ().Textfield ().Marked ("entryComment").Text (stashMsg));
TakeScreenShot ("Stash-Message-Entered");
+
+ ReproStep ("Click on OK");
Session.ClickElement (c => c.Window ().Marked ("MonoDevelop.VersionControl.Git.NewStashDialog").Children ().Button ().Marked ("buttonOk"));
Ide.WaitForStatusMessage (new [] { "Changes successfully stashed" }, timeoutStashSecs);
}
protected void TestGitUnstash ()
{
+ ReproStep ("Click on Version Control > Pop Stash");
Session.ExecuteCommand (MonoDevelop.VersionControl.Git.Commands.StashPop);
- Ide.WaitForStatusMessage (new[] {"Stash successfully applied"}, 10);
+
+ WaitForElement (() => Ide.WaitForStatusMessage (new[] {"Stash successfully applied"}, 10), "Stash should apply successfully", "Stash failed to apply");
}
protected void TestCommit (string commitMsg)
{
+ ReproStep ("Click on Version Control > Review Solution and Commit from Menu Bar");
Session.ExecuteCommand (MonoDevelop.VersionControl.Commands.SolutionStatus);
+
+ ReproStep ("Wait for diff to be available");
+ WaitForElement (c => c.Button ().Marked ("buttonCommit").Sensitivity (true), "Commit button should become enabled", "Commit button was not enabled");
+
+ ReproStep ("Click on Commit Button");
Session.ClickElement (c => c.Button ().Marked ("buttonCommit"), false);
- Session.WaitForElement (c => c.Window ().Marked ("MonoDevelop.VersionControl.Dialogs.CommitDialog"));
+
+ WaitForElement (c => c.Window ().Marked ("MonoDevelop.VersionControl.Dialogs.CommitDialog"), "Commit Dialog should open", "Commit Dialog did not open");
TakeScreenShot ("Commit-Dialog-Opened");
+
+ ReproStep ("Enter commit message and click on Commit");
Session.EnterText (c => c.Window ().Marked ("MonoDevelop.VersionControl.Dialogs.CommitDialog").Children ().TextView ().Marked ("textview"), commitMsg);
TakeScreenShot ("Commit-Msg-Entered");
Session.ClickElement (c => c.Window ().Marked ("MonoDevelop.VersionControl.Dialogs.CommitDialog").Children ().Button ().Marked ("buttonCommit"), false);
+ CheckIfNameEmailNeeded ();
+ CheckIfUserConflict ();
+
+ WaitForElement (() => Ide.WaitForStatusMessage (new [] { "Commit operation completed." }),
+ "Status bar should show 'Commit operation completed.'",
+ "Status bar did not show 'Commit operation completed.'");
+ TakeScreenShot ("Commit-Completed");
+
+ ReproStep ("Close currently commit tab");
+ Session.ExecuteCommand (FileCommands.CloseFile);
+ Session.WaitForElement (IdeQuery.TextArea);
+ }
+
+ protected void GitCreateAndCommit (TemplateSelectionOptions templateOptions, string commitMessage)
+ {
+ CreateProject (templateOptions,
+ new ProjectDetails (templateOptions),
+ new GitOptions { UseGit = true, UseGitIgnore = true });
+
+ Session.WaitForElement (IdeQuery.TextArea);
+ TestCommit (commitMessage);
+ }
+
+ protected string MakeSomeChangesAndSaveAll (string waitForFile = null)
+ {
+ if (waitForFile != null) {
+ WaitForElement (c => c.Window ().Marked ("MonoDevelop.Ide.Gui.DefaultWorkbench").Property ("TabControl.CurrentTab.Text", waitForFile),
+ string.Format ("File '{0}' should open", waitForFile),
+ string.Format ("File {0} did not open", waitForFile));
+ }
+
+ Session.WaitForElement (IdeQuery.TextArea);
+ TakeScreenShot ("Ready-To-Make-Changes");
+ Session.SelectElement (IdeQuery.TextArea);
+ ReproStep ("Make some random changes to the file");
+ for (int i = 0; i < 10; i++) {
+ Session.ExecuteCommand (TextEditorCommands.InsertNewLine);
+ Session.ExecuteCommand (TextEditorCommands.InsertTab);
+ }
+ TakeScreenShot ("Made-Changes-To-Doc");
+
+ ReproStep ("Click on File > Save All from Menu Bar");
+ Session.ExecuteCommand (FileCommands.SaveAll);
+ TakeScreenShot ("Inserted-Newline-SaveAll-Called");
+
+ return "Entered new blank line";
+ }
+
+ protected void CheckIfNameEmailNeeded ()
+ {
try {
Session.WaitForElement (c => c.Window ().Marked ("MonoDevelop.VersionControl.Git.UserGitConfigDialog"));
TakeScreenShot ("Git-User-Not-Configured");
EnterGitUserConfig ("John Doe", "john.doe@example.com");
} catch (TimeoutException e) { }
- Ide.WaitForStatusMessage (new[] {"Commit operation completed."});
- TakeScreenShot ("Commit-Completed");
}
protected void EnterGitUserConfig (string gitUser, string gitEmail)
@@ -119,6 +200,15 @@ namespace UserInterfaceTests
}
}
+ protected void CheckIfUserConflict ()
+ {
+ try {
+ Session.WaitForElement (c => c.Window ().Marked ("User Information Conflict"));
+ Session.ClickElement (c => c.Window ().Marked ("User Information Conflict").Children ().Button ().Text ("OK"));
+ } catch (TimeoutException) {
+ }
+ }
+
protected override void OnBuildTemplate (int buildTimeoutInSecs = 180)
{
}
diff --git a/main/tests/UserInterfaceTests/Workbench.cs b/main/tests/UserInterfaceTests/Workbench.cs
new file mode 100644
index 0000000000..9ddb3bdf1a
--- /dev/null
+++ b/main/tests/UserInterfaceTests/Workbench.cs
@@ -0,0 +1,147 @@
+//
+// Workbench.cs
+//
+// Author:
+// Manish Sinha <manish.sinha@xamarin.com>
+//
+// Copyright (c) 2015 Xamarin Inc.
+//
+// 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 MonoDevelop.Core;
+using MonoDevelop.Components.AutoTest;
+using System.Text.RegularExpressions;
+using MonoDevelop.Ide.Commands;
+using System.Linq;
+
+namespace UserInterfaceTests
+{
+ public static class Workbench
+ {
+ static AutoTestClientSession Session {
+ get { return TestService.Session; }
+ }
+
+ static readonly Regex buildRegex = new Regex (@"Build: (?<errors>\d*) error\D*, (?<warnings>\d*) warning\D*", RegexOptions.Compiled);
+
+ public static string GetStatusMessage (int timeout = 20000, bool waitForNonEmpty = true)
+ {
+ if (Platform.IsMac) {
+ if (waitForNonEmpty) {
+ Ide.WaitUntil (
+ () => Session.GetGlobalValue<string> ("MonoDevelop.Ide.IdeApp.Workbench.RootWindow.StatusBar.text") != string.Empty,
+ timeout
+ );
+ }
+ return (string)Session.GetGlobalValue ("MonoDevelop.Ide.IdeApp.Workbench.RootWindow.StatusBar.text");
+ }
+
+ if (waitForNonEmpty) {
+ Ide.WaitUntil (
+ () => Session.GetGlobalValue<int> ("MonoDevelop.Ide.IdeApp.Workbench.RootWindow.StatusBar.messageQueue.Count") == 0,
+ timeout,
+ timeoutMessage: ()=> "MessageQueue.Count="+Session.GetGlobalValue<int> ("MonoDevelop.Ide.IdeApp.Workbench.RootWindow.StatusBar.messageQueue.Count")
+ );
+ }
+ return (string) Session.GetGlobalValue ("MonoDevelop.Ide.IdeApp.Workbench.RootWindow.StatusBar.renderArg.CurrentText");
+ }
+
+ public static bool IsBuildSuccessful (int timeoutInSecs)
+ {
+ bool isBuildSuccessful = false;
+ Ide.WaitUntil (() => {
+ var actualStatusMessage = Workbench.GetStatusMessage ();
+ if (actualStatusMessage == "Build successful.") {
+ isBuildSuccessful = true;
+ return true;
+ }
+ if (actualStatusMessage == "Build failed.") {
+ isBuildSuccessful = false;
+ return true;
+ }
+ var match = buildRegex.Match (actualStatusMessage);
+ if (match != null && match.Success) {
+ isBuildSuccessful = string.Equals (match.Groups ["errors"].ToString (), "0");
+ return true;
+ }
+ return false;
+ },
+ pollStep: 5 * 1000,
+ timeout: timeoutInSecs * 1000,
+ timeoutMessage: () => "GetStatusMessage=" + Workbench.GetStatusMessage ());
+
+ return isBuildSuccessful;
+ }
+
+ public static bool Run (int timeoutSeconds = 20, int pollStepSecs = 5)
+ {
+ Session.ExecuteCommand (ProjectCommands.Run);
+ try {
+ Ide.WaitUntil (
+ () => !Session.Query (c => IdeQuery.RunButton (c).Property ("Icon", "Stop")).Any (),
+ timeout: timeoutSeconds * 1000, pollStep: pollStepSecs * 1000);
+ return false;
+ } catch (TimeoutException) {
+ return true;
+ }
+ }
+
+ public static void OpenWorkspace (string solutionPath, UITestBase testContext = null)
+ {
+ if (testContext != null)
+ testContext.ReproStep (string.Format ("Open solution path '{0}'", solutionPath));
+ Action<string> takeScreenshot = GetScreenshotAction (testContext);
+ Session.GlobalInvoke ("MonoDevelop.Ide.IdeApp.Workspace.OpenWorkspaceItem", new FilePath (solutionPath), true);
+ Ide.WaitForIdeIdle ();
+ takeScreenshot ("Solution-Opened");
+ }
+
+ public static void CloseWorkspace (UITestBase testContext = null)
+ {
+ if (testContext != null)
+ testContext.ReproStep ("Close current workspace");
+ Action<string> takeScreenshot = GetScreenshotAction (testContext);
+ takeScreenshot ("About-To-Close-Workspace");
+ Session.ExecuteCommand (FileCommands.CloseWorkspace);
+ takeScreenshot ("Closed-Workspace");
+ }
+
+ public static string Configuration
+ {
+ get {
+ var configId = Session.GetGlobalValue ("MonoDevelop.Ide.IdeApp.Workspace.ActiveConfigurationId");
+ return configId != null ? (string)configId : null;
+ }
+ set {
+ Session.SetGlobalValue ("MonoDevelop.Ide.IdeApp.Workspace.ActiveConfigurationId", value);
+ Ide.WaitUntil (() => Workbench.Configuration == value, timeoutMessage: () => "Failed to set Configuration, Configuration=" + Workbench.Configuration + " value=" + value);
+ }
+ }
+
+ public static Action<string> GetScreenshotAction (UITestBase testContext)
+ {
+ Action<string> takeScreenshot = delegate {
+ };
+ if (testContext != null)
+ takeScreenshot = testContext.TakeScreenShot;
+
+ return takeScreenshot;
+ }
+ }
+}
diff --git a/main/winbuild.bat b/main/winbuild.bat
index dec63ce9d9..805ac02907 100644
--- a/main/winbuild.bat
+++ b/main/winbuild.bat
@@ -1 +1,7 @@
-"%WinDir%\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe" Main.sln /m /p:Configuration=DebugWin32 /p:Platform="Any CPU"
+set filename=%ProgramFiles(x86)%\MSBuild\14.0\Bin\MSBuild.exe
+
+if not exist "%filename%" (
+ set filename=%WinDir%\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe
+)
+
+"%filename%" Main.sln /m /p:Configuration=DebugWin32 /p:Platform="Any CPU"
diff --git a/main/xbuild.include b/main/xbuild.include
index 1ac24dbb3c..493d09a0de 100644
--- a/main/xbuild.include
+++ b/main/xbuild.include
@@ -2,16 +2,28 @@ ALL_CSPROJ=$(wildcard *.csproj)
MAIN_SLN=$(top_builddir)/Main.sln
if ENABLE_MACPLATFORM
+if RELEASE_BUILDS
+PROFILE_NAME=ReleaseMac
+else
PROFILE_NAME=DebugMac
endif
+endif
if ENABLE_GNOMEPLATFORM
+if RELEASE_BUILDS
+PROFILE_NAME=ReleaseGnome
+else
PROFILE_NAME=DebugGnome
endif
+endif
if ENABLE_WINDOWSPLATFORM
+if RELEASE_BUILDS
+PROFILE_NAME=ReleaseWin32
+else
PROFILE_NAME=DebugWin32
endif
+endif
XBUILD=xbuild
XBUILD_VERBOSITY=normal
@@ -48,7 +60,7 @@ sln_clean:
print_extradist:
@echo $(WILDCARDED_FILES)
-EXTS:=*.bmp *.cs *.csproj *.html *.png *.snk *.config *.stetic *.glade *.xml *.xsd *.exe.addins *.template *.tt *.txt
+EXTS:=*.bmp *.cs *.csproj *.html *.png *.snk *.config *.stetic *.glade *.xml *.xsd *.exe.addins *.template *.tt *.txt *.targets *.sh
ALL_FILES:= $(EXTS) \
$(addprefix */,$(EXTS)) \
diff --git a/scripts/configure.sh b/scripts/configure.sh
index e4a361759e..277e47da5e 100755
--- a/scripts/configure.sh
+++ b/scripts/configure.sh
@@ -1,3 +1,5 @@
+#!/usr/bin/env bash
+
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
if [ ! -f $DIR/configure.exe ]; then
diff --git a/version-checks b/version-checks
index 16bd869299..f1ffdea7e6 100755
--- a/version-checks
+++ b/version-checks
@@ -17,7 +17,7 @@ DEP[0]=md-addins
DEP_NAME[0]=MDADDINS
DEP_PATH[0]=${top_srcdir}/../md-addins
DEP_MODULE[0]=git@github.com:xamarin/md-addins.git
-DEP_NEEDED_VERSION[0]=bd1bf202bb625780783cc57b2c16884dcfe074d2
+DEP_NEEDED_VERSION[0]=d5c9958a3a1fb38f89c8504bd4c0cb97a45f1aee
DEP_BRANCH_AND_REMOTE[0]="master origin/master"
# heap-shot
diff --git a/version.config b/version.config
index 5a3b877775..56f1b307f3 100644
--- a/version.config
+++ b/version.config
@@ -1,3 +1,3 @@
-Version=5.10
-Label=5.10
+Version=5.11
+Label=5.11
CompatVersion=5.0